nridge created this revision.
nridge added a reviewer: hokein.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
nridge requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.
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
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D153248
Files:
clang-tools-extra/clangd/HeuristicResolver.cpp
clang-tools-extra/clangd/HeuristicResolver.h
clang-tools-extra/clangd/unittests/FindTargetTests.cpp
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -893,6 +893,19 @@
}
)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) {
Index: clang-tools-extra/clangd/HeuristicResolver.h
===================================================================
--- clang-tools-extra/clangd/HeuristicResolver.h
+++ clang-tools-extra/clangd/HeuristicResolver.h
@@ -16,6 +16,7 @@
class ASTContext;
class CallExpr;
+class CXXBasePath;
class CXXDependentScopeMemberExpr;
class DeclarationName;
class DependentScopeDeclRefExpr;
@@ -99,6 +100,20 @@
// 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
Index: clang-tools-extra/clangd/HeuristicResolver.cpp
===================================================================
--- clang-tools-extra/clangd/HeuristicResolver.cpp
+++ 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 @@
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 @@
if (!RD->hasDefinition())
return {};
RD = RD->getDefinition();
- return RD->lookupDependentName(Name, Filter);
+ return lookupDependentName(RD, Name, Filter);
}
return {};
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits