https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/123818
>From 25fdf43fb182212e859aba806ab32cc25ec466af Mon Sep 17 00:00:00 2001 From: Nathan Ridge <zeratul...@hotmail.com> Date: Thu, 26 Dec 2024 20:59:06 -0500 Subject: [PATCH 1/3] [clang][CodeComplete] Use HeuristicResolver to resolve pointee types Fixes https://github.com/clangd/clangd/issues/810 --- clang/include/clang/Sema/SemaCodeCompletion.h | 2 ++ clang/lib/Sema/SemaCodeComplete.cpp | 15 ++++++++++----- clang/test/CodeCompletion/member-access.cpp | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h b/clang/include/clang/Sema/SemaCodeCompletion.h index 50409439389b06..e931596c215d31 100644 --- a/clang/include/clang/Sema/SemaCodeCompletion.h +++ b/clang/include/clang/Sema/SemaCodeCompletion.h @@ -23,6 +23,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" +#include "clang/Sema/HeuristicResolver.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/SemaBase.h" #include "llvm/ADT/StringRef.h" @@ -43,6 +44,7 @@ class SemaCodeCompletion : public SemaBase { /// Code-completion consumer. CodeCompleteConsumer *CodeCompleter; + HeuristicResolver Resolver; /// Describes the context in which code completion occurs. enum ParserCompletionContext { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 8a848df70cc5a1..69cda6e68bd36b 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -34,6 +34,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Designator.h" +#include "clang/Sema/HeuristicResolver.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/ParsedAttr.h" @@ -5861,8 +5862,10 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr( enum CodeCompletionContext::Kind contextKind; if (IsArrow) { - if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>()) - ConvertedBaseType = Ptr->getPointeeType(); + if (QualType PointeeType = Resolver.getPointeeType(ConvertedBaseType); + !PointeeType.isNull()) { + ConvertedBaseType = PointeeType; + } } if (IsArrow) { @@ -5899,8 +5902,9 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr( ExprValueKind BaseKind = Base->getValueKind(); if (IsArrow) { - if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { - BaseType = Ptr->getPointeeType(); + if (QualType PointeeType = Resolver.getPointeeType(BaseType); + !PointeeType.isNull()) { + BaseType = PointeeType; BaseKind = VK_LValue; } else if (BaseType->isObjCObjectPointerType() || BaseType->isTemplateTypeParmType()) { @@ -10472,4 +10476,5 @@ void SemaCodeCompletion::GatherGlobalCodeCompletions( SemaCodeCompletion::SemaCodeCompletion(Sema &S, CodeCompleteConsumer *CompletionConsumer) - : SemaBase(S), CodeCompleter(CompletionConsumer) {} + : SemaBase(S), CodeCompleter(CompletionConsumer), + Resolver(S.getASTContext()) {} diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index 912f269db6c1ac..ab6dc69bf2923d 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -384,3 +384,20 @@ void Foo() { // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:382:5 %s -o - | FileCheck -check-prefix=CHECK-DEREF-DEPENDENT %s // CHECK-DEREF-DEPENDENT: [#void#]Add() } + +namespace dependent_smart_pointer { +template <typename T> +struct smart_pointer { + T* operator->(); +}; + +template <typename T> +struct node { + smart_pointer<node<T>> next; + void foo() { + next->next; + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:398:11 %s -o - | FileCheck -check-prefix=CHECK-DEPENDENT-SMARTPTR %s + // CHECK-DEPENDENT-SMARTPTR: [#smart_pointer<node<T>>#]next + } +}; +} >From 58029449d63af7f452820dd02aba0d10134f588c Mon Sep 17 00:00:00 2001 From: Nathan Ridge <zeratul...@hotmail.com> Date: Tue, 21 Jan 2025 15:56:27 -0500 Subject: [PATCH 2/3] [clang][CodeComplete] Use HeuristicResolver to resolve DependentNameTypes Fixes https://github.com/clangd/clangd/issues/1249 --- clang/lib/Sema/SemaCodeComplete.cpp | 25 +++++++++++++++------ clang/test/CodeCompletion/member-access.cpp | 16 +++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 69cda6e68bd36b..d349928e1a171b 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5736,11 +5736,20 @@ class ConceptInfo { // In particular, when E->getType() is DependentTy, try to guess a likely type. // We accept some lossiness (like dropping parameters). // We only try to handle common expressions on the LHS of MemberExpr. -QualType getApproximateType(const Expr *E) { +QualType getApproximateType(const Expr *E, HeuristicResolver &Resolver) { if (E->getType().isNull()) return QualType(); E = E->IgnoreParenImpCasts(); QualType Unresolved = E->getType(); + // Resolve DependentNameType + if (const auto *DNT = Unresolved->getAs<DependentNameType>()) { + auto Decls = Resolver.resolveDependentNameType(DNT); + if (Decls.size() == 1) { + if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) { + return QualType(TD->getTypeForDecl(), 0); + } + } + } // We only resolve DependentTy, or undeduced autos (including auto* etc). if (!Unresolved->isSpecificBuiltinType(BuiltinType::Dependent)) { AutoType *Auto = Unresolved->getContainedAutoType(); @@ -5749,7 +5758,7 @@ QualType getApproximateType(const Expr *E) { } // A call: approximate-resolve callee to a function type, get its return type if (const CallExpr *CE = llvm::dyn_cast<CallExpr>(E)) { - QualType Callee = getApproximateType(CE->getCallee()); + QualType Callee = getApproximateType(CE->getCallee(), Resolver); if (Callee.isNull() || Callee->isSpecificPlaceholderType(BuiltinType::BoundMember)) Callee = Expr::findBoundMemberType(CE->getCallee()); @@ -5792,7 +5801,7 @@ QualType getApproximateType(const Expr *E) { if (const auto *CDSME = llvm::dyn_cast<CXXDependentScopeMemberExpr>(E)) { QualType Base = CDSME->isImplicitAccess() ? CDSME->getBaseType() - : getApproximateType(CDSME->getBase()); + : getApproximateType(CDSME->getBase(), Resolver); if (CDSME->isArrow() && !Base.isNull()) Base = Base->getPointeeType(); // could handle unique_ptr etc here? auto *RD = @@ -5813,14 +5822,15 @@ QualType getApproximateType(const Expr *E) { if (const auto *DRE = llvm::dyn_cast<DeclRefExpr>(E)) { if (const auto *VD = llvm::dyn_cast<VarDecl>(DRE->getDecl())) { if (VD->hasInit()) - return getApproximateType(VD->getInit()); + return getApproximateType(VD->getInit(), Resolver); } } if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) { if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) { // We recurse into the subexpression because it could be of dependent // type. - if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType(); + if (auto Pointee = + getApproximateType(UO->getSubExpr(), Resolver)->getPointeeType(); !Pointee.isNull()) return Pointee; // Our caller expects a non-null result, even though the SubType is @@ -5857,7 +5867,8 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr( SemaRef.PerformMemberExprBaseConversion(Base, IsArrow); if (ConvertedBase.isInvalid()) return; - QualType ConvertedBaseType = getApproximateType(ConvertedBase.get()); + QualType ConvertedBaseType = + getApproximateType(ConvertedBase.get(), Resolver); enum CodeCompletionContext::Kind contextKind; @@ -5896,7 +5907,7 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr( return false; Base = ConvertedBase.get(); - QualType BaseType = getApproximateType(Base); + QualType BaseType = getApproximateType(Base, Resolver); if (BaseType.isNull()) return false; ExprValueKind BaseKind = Base->getValueKind(); diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index ab6dc69bf2923d..bf35f7ad021f71 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -401,3 +401,19 @@ struct node { } }; } + +namespace dependent_nested_class { +template <typename T> +struct Foo { + struct Bar { + int field; + }; +}; +template <typename T> +void f() { + typename Foo<T>::Bar bar; + bar.field; + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:415:7 %s -o - | FileCheck -check-prefix=CHECK-DEPENDENT-NESTEDCLASS %s + // CHECK-DEPENDENT-NESTEDCLASS: [#int#]field +} +} >From bc4b90d8b6599d6108e6873e59b6974d6971af19 Mon Sep 17 00:00:00 2001 From: Nathan Ridge <zeratul...@hotmail.com> Date: Wed, 22 Jan 2025 02:46:59 -0500 Subject: [PATCH 3/3] Add blank line Co-authored-by: Younan Zhang <zyn7...@gmail.com> --- clang/test/CodeCompletion/member-access.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index 4efb1fa0cc90fe..bf35f7ad021f71 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -416,4 +416,4 @@ void f() { // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:415:7 %s -o - | FileCheck -check-prefix=CHECK-DEPENDENT-NESTEDCLASS %s // CHECK-DEPENDENT-NESTEDCLASS: [#int#]field } -} \ No newline at end of file +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits