Author: Nathan Ridge
Date: 2023-06-20T13:40:26-04:00
New Revision: 6fe9cfe4137bc140c909850c26b52e9406495566

URL: 
https://github.com/llvm/llvm-project/commit/6fe9cfe4137bc140c909850c26b52e9406495566
DIFF: 
https://github.com/llvm/llvm-project/commit/6fe9cfe4137bc140c909850c26b52e9406495566.diff

LOG: [clangd] Use resolveTypeToRecordDecl() to resolve the type of a base 
specifier during heuristic resolution

The code for resolving the type of a base specifier was inside
CXXRecordDecl::lookupDependentName(), so this patch reimplements
lookupDependentName() in HeuristicResolver.

Fixes https://github.com/clangd/clangd/issues/1657

Differential Revision: https://reviews.llvm.org/D153248

Added: 
    

Modified: 
    clang-tools-extra/clangd/HeuristicResolver.cpp
    clang-tools-extra/clangd/HeuristicResolver.h
    clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/HeuristicResolver.cpp 
b/clang-tools-extra/clangd/HeuristicResolver.cpp
index 7960ab92ba9e6..719094dbf2b7e 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -8,6 +8,7 @@
 
 #include "HeuristicResolver.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/Type.h"
@@ -264,6 +265,68 @@ const Type 
*HeuristicResolver::resolveNestedNameSpecifierToType(
   return nullptr;
 }
 
+namespace {
+
+bool isOrdinaryMember(const NamedDecl *ND) {
+  return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
+                                     Decl::IDNS_Member);
+}
+
+bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
+                        DeclarationName Name) {
+  Path.Decls = RD->lookup(Name).begin();
+  for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
+    if (isOrdinaryMember(*I))
+      return true;
+
+  return false;
+}
+
+} // namespace
+
+bool HeuristicResolver::findOrdinaryMemberInDependentClasses(
+    const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
+    DeclarationName Name) const {
+  CXXRecordDecl *RD =
+      resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
+  if (!RD)
+    return false;
+  return findOrdinaryMember(RD, Path, Name);
+}
+
+std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
+    CXXRecordDecl *RD, DeclarationName Name,
+    llvm::function_ref<bool(const NamedDecl *ND)> Filter) const {
+  std::vector<const NamedDecl *> Results;
+
+  // Lookup in the class.
+  bool AnyOrdinaryMembers = false;
+  for (const NamedDecl *ND : RD->lookup(Name)) {
+    if (isOrdinaryMember(ND))
+      AnyOrdinaryMembers = true;
+    if (Filter(ND))
+      Results.push_back(ND);
+  }
+  if (AnyOrdinaryMembers)
+    return Results;
+
+  // Perform lookup into our base classes.
+  CXXBasePaths Paths;
+  Paths.setOrigin(RD);
+  if (!RD->lookupInBases(
+          [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
+            return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
+          },
+          Paths, /*LookupInDependent=*/true))
+    return Results;
+  for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
+       I != E; ++I) {
+    if (isOrdinaryMember(*I) && Filter(*I))
+      Results.push_back(*I);
+  }
+  return Results;
+}
+
 std::vector<const NamedDecl *> HeuristicResolver::resolveDependentMember(
     const Type *T, DeclarationName Name,
     llvm::function_ref<bool(const NamedDecl *ND)> Filter) const {
@@ -277,7 +340,7 @@ std::vector<const NamedDecl *> 
HeuristicResolver::resolveDependentMember(
     if (!RD->hasDefinition())
       return {};
     RD = RD->getDefinition();
-    return RD->lookupDependentName(Name, Filter);
+    return lookupDependentName(RD, Name, Filter);
   }
   return {};
 }

diff  --git a/clang-tools-extra/clangd/HeuristicResolver.h 
b/clang-tools-extra/clangd/HeuristicResolver.h
index 6e3a8349a8606..dc04123d37593 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.h
+++ b/clang-tools-extra/clangd/HeuristicResolver.h
@@ -16,6 +16,7 @@ namespace clang {
 
 class ASTContext;
 class CallExpr;
+class CXXBasePath;
 class CXXDependentScopeMemberExpr;
 class DeclarationName;
 class DependentScopeDeclRefExpr;
@@ -99,6 +100,20 @@ class HeuristicResolver {
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a CXXRecordDecl in which we can try name lookup.
   CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const;
+
+  // This is a reimplementation of CXXRecordDecl::lookupDependentName()
+  // so that the implementation can call into other HeuristicResolver helpers.
+  // FIXME: Once HeuristicResolver is upstreamed to the clang libraries
+  // (https://github.com/clangd/clangd/discussions/1662),
+  // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites
+  // can be modified to benefit from the more comprehensive heuristics offered
+  // by HeuristicResolver instead.
+  std::vector<const NamedDecl *> lookupDependentName(
+      CXXRecordDecl *RD, DeclarationName Name,
+      llvm::function_ref<bool(const NamedDecl *ND)> Filter) const;
+  bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
+                                            CXXBasePath &Path,
+                                            DeclarationName Name) const;
 };
 
 } // namespace clangd

diff  --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp 
b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 8a69d4f9ed4a7..81e891b2db01e 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -893,6 +893,19 @@ TEST_F(TargetDeclTest, DependentExprs) {
         }
   )cpp";
   EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
+
+  Code = R"cpp(
+        struct Waldo {
+          void find();
+        };
+        template <typename T>
+        using Wally = Waldo;
+        template <typename>
+        struct S : Wally<int> {
+          void Foo() { this->[[find]](); }
+        };
+  )cpp";
+  EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");
 }
 
 TEST_F(TargetDeclTest, DependentTypes) {


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

Reply via email to