[clang-tools-extra] 6fe9cfe - [clangd] Use resolveTypeToRecordDecl() to resolve the type of a base specifier during heuristic resolution
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 20 10:40:44 PDT 2023
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) {
More information about the cfe-commits
mailing list