https://github.com/HighCommander4 created 
https://github.com/llvm/llvm-project/pull/123551

Fixes https://github.com/llvm/llvm-project/issues/123549

>From cd87f05f19f245e24f5c29b97af0b69266608d7a Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul...@hotmail.com>
Date: Mon, 20 Jan 2025 01:52:24 -0500
Subject: [PATCH 1/2] Upgrade HeuristicResolver to use QualType rather than
 Type*

---
 clang-tools-extra/clangd/FindTarget.cpp      |  3 +-
 clang-tools-extra/clangd/XRefs.cpp           |  7 +-
 clang/include/clang/Sema/HeuristicResolver.h |  4 +-
 clang/lib/Sema/HeuristicResolver.cpp         | 77 ++++++++++----------
 4 files changed, 47 insertions(+), 44 deletions(-)

diff --git a/clang-tools-extra/clangd/FindTarget.cpp 
b/clang-tools-extra/clangd/FindTarget.cpp
index 04fd6d437b7bdd..bb4c91b8313540 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -496,8 +496,7 @@ struct TargetFinder {
       return;
     case NestedNameSpecifier::Identifier:
       if (Resolver) {
-        add(QualType(Resolver->resolveNestedNameSpecifierToType(NNS), 0),
-            Flags);
+        add(Resolver->resolveNestedNameSpecifierToType(NNS), Flags);
       }
       return;
     case NestedNameSpecifier::TypeSpec:
diff --git a/clang-tools-extra/clangd/XRefs.cpp 
b/clang-tools-extra/clangd/XRefs.cpp
index 0a093108b752c3..1a23f6cca77561 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -2034,9 +2034,10 @@ static void unwrapFindType(
 
   // For smart pointer types, add the underlying type
   if (H)
-    if (const auto* PointeeType = 
H->getPointeeType(T.getNonReferenceType().getTypePtr())) {
-        unwrapFindType(QualType(PointeeType, 0), H, Out);
-        return Out.push_back(T);
+    if (auto PointeeType = H->getPointeeType(T.getNonReferenceType());
+        !PointeeType.isNull()) {
+      unwrapFindType(PointeeType, H, Out);
+      return Out.push_back(T);
     }
 
   return Out.push_back(T);
diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index 947de7a4e83ce0..3760003aab89f1 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -66,13 +66,13 @@ class HeuristicResolver {
   // Try to heuristically resolve a dependent nested name specifier
   // to the type it likely denotes. Note that *dependent* name specifiers 
always
   // denote types, not namespaces.
-  const Type *
+  QualType
   resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const;
 
   // Given the type T of a dependent expression that appears of the LHS of a
   // "->", heuristically find a corresponding pointee type in whose scope we
   // could look up the name appearing on the RHS.
-  const Type *getPointeeType(const Type *T) const;
+  const QualType getPointeeType(QualType T) const;
 
 private:
   ASTContext &Ctx;
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7c1b8450b96330..f883b85a80c60f 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -42,8 +42,8 @@ class HeuristicResolverImpl {
   resolveDependentNameType(const DependentNameType *DNT);
   std::vector<const NamedDecl *> resolveTemplateSpecializationType(
       const DependentTemplateSpecializationType *DTST);
-  const Type *resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
-  const Type *getPointeeType(const Type *T);
+  QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS);
+  QualType getPointeeType(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -61,12 +61,12 @@ class HeuristicResolverImpl {
   // This heuristic will give the desired answer in many cases, e.g.
   // for a call to vector<T>::size().
   std::vector<const NamedDecl *>
-  resolveDependentMember(const Type *T, DeclarationName Name,
+  resolveDependentMember(QualType T, DeclarationName Name,
                          llvm::function_ref<bool(const NamedDecl *ND)> Filter);
 
   // Try to heuristically resolve the type of a possibly-dependent expression
   // `E`.
-  const Type *resolveExprToType(const Expr *E);
+  QualType resolveExprToType(const Expr *E);
   std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E);
 
   // Helper function for HeuristicResolver::resolveDependentMember()
@@ -104,17 +104,17 @@ const auto TemplateFilter = [](const NamedDecl *D) {
   return isa<TemplateDecl>(D);
 };
 
-const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
-                               ASTContext &Ctx) {
+QualType resolveDeclsToType(const std::vector<const NamedDecl *> &Decls,
+                            ASTContext &Ctx) {
   if (Decls.size() != 1) // Names an overload set -- just bail.
-    return nullptr;
+    return QualType();
   if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) {
-    return Ctx.getTypeDeclType(TD).getTypePtr();
+    return Ctx.getTypeDeclType(TD);
   }
   if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) {
-    return VD->getType().getTypePtrOrNull();
+    return VD->getType();
   }
-  return nullptr;
+  return QualType();
 }
 
 TemplateName getReferencedTemplateName(const Type *T) {
@@ -137,7 +137,8 @@ CXXRecordDecl 
*HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
   T = T->getCanonicalTypeInternal().getTypePtr();
 
   if (const auto *DNT = T->getAs<DependentNameType>()) {
-    T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx);
+    T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
+            .getTypePtrOrNull();
     if (!T)
       return nullptr;
     T = T->getCanonicalTypeInternal().getTypePtr();
@@ -163,12 +164,12 @@ CXXRecordDecl 
*HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
   return TD->getTemplatedDecl();
 }
 
-const Type *HeuristicResolverImpl::getPointeeType(const Type *T) {
-  if (!T)
-    return nullptr;
+QualType HeuristicResolverImpl::getPointeeType(QualType T) {
+  if (T.isNull())
+    return QualType();
 
   if (T->isPointerType())
-    return T->castAs<PointerType>()->getPointeeType().getTypePtrOrNull();
+    return T->castAs<PointerType>()->getPointeeType();
 
   // Try to handle smart pointer types.
 
@@ -177,7 +178,7 @@ const Type *HeuristicResolverImpl::getPointeeType(const 
Type *T) {
   auto ArrowOps = resolveDependentMember(
       T, Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter);
   if (ArrowOps.empty())
-    return nullptr;
+    return QualType();
 
   // Getting the return type of the found operator-> method decl isn't useful,
   // because we discarded template arguments to perform lookup in the primary
@@ -187,13 +188,13 @@ const Type *HeuristicResolverImpl::getPointeeType(const 
Type *T) {
   // form of SmartPtr<X, ...>, and assume X is the pointee type.
   auto *TST = T->getAs<TemplateSpecializationType>();
   if (!TST)
-    return nullptr;
+    return QualType();
   if (TST->template_arguments().size() == 0)
-    return nullptr;
+    return QualType();
   const TemplateArgument &FirstArg = TST->template_arguments()[0];
   if (FirstArg.getKind() != TemplateArgument::Type)
-    return nullptr;
-  return FirstArg.getAsType().getTypePtrOrNull();
+    return QualType();
+  return FirstArg.getAsType();
 }
 
 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
@@ -210,7 +211,8 @@ std::vector<const NamedDecl *> 
HeuristicResolverImpl::resolveMemberExpr(
   //      with `this` as the base expression as `X` as the qualifier
   //      (which could be valid if `X` names a base class after instantiation).
   if (NestedNameSpecifier *NNS = ME->getQualifier()) {
-    if (const Type *QualifierType = resolveNestedNameSpecifierToType(NNS)) {
+    if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS);
+        !QualifierType.isNull()) {
       auto Decls =
           resolveDependentMember(QualifierType, ME->getMember(), NoFilter);
       if (!Decls.empty())
@@ -225,11 +227,11 @@ std::vector<const NamedDecl *> 
HeuristicResolverImpl::resolveMemberExpr(
   }
 
   // Try resolving the member inside the expression's base type.
-  const Type *BaseType = ME->getBaseType().getTypePtrOrNull();
+  QualType BaseType = ME->getBaseType();
   if (ME->isArrow()) {
     BaseType = getPointeeType(BaseType);
   }
-  if (!BaseType)
+  if (BaseType.isNull())
     return {};
   if (const auto *BT = BaseType->getAs<BuiltinType>()) {
     // If BaseType is the type of a dependent expression, it's just
@@ -245,17 +247,17 @@ std::vector<const NamedDecl *> 
HeuristicResolverImpl::resolveMemberExpr(
 
 std::vector<const NamedDecl *>
 HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) 
{
-  return resolveDependentMember(RE->getQualifier()->getAsType(),
+  return resolveDependentMember(QualType(RE->getQualifier()->getAsType(), 0),
                                 RE->getDeclName(), StaticFilter);
 }
 
 std::vector<const NamedDecl *>
 HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
-  const auto *CalleeType = resolveExprToType(CE->getCallee());
-  if (!CalleeType)
+  QualType CalleeType = resolveExprToType(CE->getCallee());
+  if (CalleeType.isNull())
     return {};
   if (const auto *FnTypePtr = CalleeType->getAs<PointerType>())
-    CalleeType = FnTypePtr->getPointeeType().getTypePtr();
+    CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
     if (const auto *D =
             resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
@@ -276,7 +278,7 @@ HeuristicResolverImpl::resolveCalleeOfCallExpr(const 
CallExpr *CE) {
 
 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl(
     const UnresolvedUsingValueDecl *UUVD) {
-  return resolveDependentMember(UUVD->getQualifier()->getAsType(),
+  return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0),
                                 UUVD->getNameInfo().getName(), ValueFilter);
 }
 
@@ -317,18 +319,18 @@ HeuristicResolverImpl::resolveExprToDecls(const Expr *E) {
   return {};
 }
 
-const Type *HeuristicResolverImpl::resolveExprToType(const Expr *E) {
+QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
   std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
   if (!Decls.empty())
     return resolveDeclsToType(Decls, Ctx);
 
-  return E->getType().getTypePtr();
+  return E->getType();
 }
 
-const Type *HeuristicResolverImpl::resolveNestedNameSpecifierToType(
+QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType(
     const NestedNameSpecifier *NNS) {
   if (!NNS)
-    return nullptr;
+    return QualType();
 
   // The purpose of this function is to handle the dependent (Kind ==
   // Identifier) case, but we need to recurse on the prefix because
@@ -337,7 +339,7 @@ const Type 
*HeuristicResolverImpl::resolveNestedNameSpecifierToType(
   switch (NNS->getKind()) {
   case NestedNameSpecifier::TypeSpec:
   case NestedNameSpecifier::TypeSpecWithTemplate:
-    return NNS->getAsType();
+    return QualType(NNS->getAsType(), 0);
   case NestedNameSpecifier::Identifier: {
     return resolveDeclsToType(
         resolveDependentMember(
@@ -348,7 +350,7 @@ const Type 
*HeuristicResolverImpl::resolveNestedNameSpecifierToType(
   default:
     break;
   }
-  return nullptr;
+  return QualType();
 }
 
 bool isOrdinaryMember(const NamedDecl *ND) {
@@ -410,8 +412,9 @@ std::vector<const NamedDecl *> 
HeuristicResolverImpl::lookupDependentName(
 }
 
 std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
-    const Type *T, DeclarationName Name,
+    QualType QT, DeclarationName Name,
     llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
+  const Type *T = QT.getTypePtrOrNull();
   if (!T)
     return {};
   if (auto *ET = T->getAs<EnumType>()) {
@@ -457,11 +460,11 @@ HeuristicResolver::resolveTemplateSpecializationType(
     const DependentTemplateSpecializationType *DTST) const {
   return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST);
 }
-const Type *HeuristicResolver::resolveNestedNameSpecifierToType(
+QualType HeuristicResolver::resolveNestedNameSpecifierToType(
     const NestedNameSpecifier *NNS) const {
   return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS);
 }
-const Type *HeuristicResolver::getPointeeType(const Type *T) const {
+const QualType HeuristicResolver::getPointeeType(QualType T) const {
   return HeuristicResolverImpl(Ctx).getPointeeType(T);
 }
 

>From c623e7eacb48788b33977caf68c07f6e9230f1a2 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul...@hotmail.com>
Date: Mon, 20 Jan 2025 01:57:42 -0500
Subject: [PATCH 2/2] Respect const-qualification on methods in
 resolveDependentMember()

---
 clang/lib/Sema/HeuristicResolver.cpp          | 10 +++++++++-
 .../unittests/Sema/HeuristicResolverTest.cpp  | 20 +++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index f883b85a80c60f..fbce1a026be61c 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -425,7 +425,15 @@ std::vector<const NamedDecl *> 
HeuristicResolverImpl::resolveDependentMember(
     if (!RD->hasDefinition())
       return {};
     RD = RD->getDefinition();
-    return lookupDependentName(RD, Name, Filter);
+    return lookupDependentName(RD, Name, [&](const NamedDecl *ND) {
+      if (!Filter(ND))
+        return false;
+      if (const auto *MD = dyn_cast<CXXMethodDecl>(ND)) {
+        if (QT.isConstQualified() && !MD->isConst())
+          return false;
+      }
+      return true;
+    });
   }
   return {};
 }
diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp 
b/clang/unittests/Sema/HeuristicResolverTest.cpp
index c4f054683ccdc9..2cd5486b3227f0 100644
--- a/clang/unittests/Sema/HeuristicResolverTest.cpp
+++ b/clang/unittests/Sema/HeuristicResolverTest.cpp
@@ -135,6 +135,26 @@ TEST(HeuristicResolver, MemberExpr_SmartPointer) {
       cxxMethodDecl(hasName("foo")).bind("output"));
 }
 
+TEST(HeuristicResolver, MemberExpr_SmartPointer_Qualified) {
+  std::string Code = R"cpp(
+    template <typename> struct Waldo {
+      void find();
+      void find() const;
+    };
+    template <typename T> struct unique_ptr {
+      T* operator->();
+    };
+    template <typename T>
+    void test(unique_ptr<const Waldo<T>>& w) {
+      w->find();
+    }
+  )cpp";
+  expectResolution(
+      Code, &HeuristicResolver::resolveMemberExpr,
+      cxxDependentScopeMemberExpr(hasMemberName("find")).bind("input"),
+      cxxMethodDecl(hasName("find"), isConst()).bind("output"));
+}
+
 TEST(HeuristicResolver, MemberExpr_Chained) {
   std::string Code = R"cpp(
     struct A { void foo() {} };

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to