nridge updated this revision to Diff 259160.
nridge added a comment.
Rebase on top of D75479 <https://reviews.llvm.org/D75479>
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D76451/new/
https://reviews.llvm.org/D76451
Files:
clang-tools-extra/clangd/XRefs.cpp
clang-tools-extra/clangd/XRefs.h
clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -663,14 +663,42 @@
int myFunction(int);
// Not triggered for token which survived preprocessing.
int var = m^yFunction();
- )cpp",
+ )cpp"};
+
+ for (const char *Test : Tests) {
+ Annotations T(Test);
+ llvm::Optional<Range> WantDecl;
+ if (!T.ranges().empty())
+ WantDecl = T.range();
+
+ auto TU = TestTU::withCode(T.code());
+
+ auto AST = TU.build();
+ auto Index = TU.index();
+ auto Word = SpelledWord::touching(
+ cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
+ AST.getTokens(), AST.getLangOpts());
+ ASSERT_TRUE(Word);
+ auto Results = locateSymbolTextually(
+ *Word, AST, Index.get(), testPath(TU.Filename), /*IsDependent=*/false);
+
+ if (!WantDecl) {
+ EXPECT_THAT(Results, IsEmpty()) << Test;
+ } else {
+ ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
+ EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
+ }
+ }
+} // namespace
+
+TEST(LocateSymbol, TextualDependent) {
+ const char *Tests[] = {
R"cpp(// Dependent type
struct Foo {
- void uniqueMethodName();
+ void [[uniqueMethodName]]();
};
template <typename T>
void f(T t) {
- // Not triggered for token which survived preprocessing.
t->u^niqueMethodName();
}
)cpp"};
@@ -685,15 +713,10 @@
auto AST = TU.build();
auto Index = TU.index();
- auto Word = SpelledWord::touching(
- cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
- AST.getTokens(), AST.getLangOpts());
- if (!Word) {
- ADD_FAILURE() << "No word touching point!" << Test;
- continue;
- }
- auto Results =
- locateSymbolTextually(*Word, AST, Index.get(), testPath(TU.Filename));
+ // Need to use locateSymbolAt() since we are testing an
+ // interaction between locateASTReferent() and
+ // locateSymbolNamedTextuallyAt().
+ auto Results = locateSymbolAt(AST, T.point(), Index.get());
if (!WantDecl) {
EXPECT_THAT(Results, IsEmpty()) << Test;
@@ -786,19 +809,18 @@
struct Bar {
void $BarLoc[[uniqueMethodName]]();
};
- // Will call u^niqueMethodName() on t.
template <typename T>
- void f(T t);
+ void f(T t) {
+ t.u^niqueMethodName();
+ }
)cpp");
auto TU = TestTU::withCode(T.code());
auto AST = TU.build();
auto Index = TU.index();
- auto Word = SpelledWord::touching(
- cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),
- AST.getTokens(), AST.getLangOpts());
- ASSERT_TRUE(Word);
- auto Results =
- locateSymbolTextually(*Word, AST, Index.get(), testPath(TU.Filename));
+ // Need to use locateSymbolAt() since we are testing an
+ // interaction between locateASTReferent() and
+ // locateSymbolNamedTextuallyAt().
+ auto Results = locateSymbolAt(AST, T.point(), Index.get());
EXPECT_THAT(Results,
UnorderedElementsAre(Sym("uniqueMethodName", T.range("FooLoc")),
Sym("uniqueMethodName", T.range("BarLoc"))));
Index: clang-tools-extra/clangd/XRefs.h
===================================================================
--- clang-tools-extra/clangd/XRefs.h
+++ clang-tools-extra/clangd/XRefs.h
@@ -62,8 +62,8 @@
// (This is for internal use by locateSymbolAt, and is exposed for testing).
std::vector<LocatedSymbol>
locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST,
- const SymbolIndex *Index,
- const std::string &MainFilePath);
+ const SymbolIndex *Index, const std::string &MainFilePath,
+ bool IsDependent);
// Try to find a proximate occurrence of `Word` as an identifier, which can be
// used to resolve it.
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -22,6 +22,7 @@
#include "index/Relation.h"
#include "index/SymbolLocation.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Attrs.inc"
#include "clang/AST/Decl.h"
@@ -139,19 +140,31 @@
return Merged.CanonicalDeclaration;
}
-std::vector<const NamedDecl *> getDeclAtPosition(ParsedAST &AST,
- SourceLocation Pos,
- DeclRelationSet Relations) {
+bool isDependentName(const DynTypedNode &N) {
+ if (const Stmt *S = N.get<Stmt>()) {
+ return llvm::isa<OverloadExpr>(S) ||
+ llvm::isa<CXXDependentScopeMemberExpr>(S) ||
+ llvm::isa<DependentScopeDeclRefExpr>(S);
+ }
+ return false;
+}
+
+std::vector<const NamedDecl *>
+getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, DeclRelationSet Relations,
+ bool *IsDependentName = nullptr) {
unsigned Offset = AST.getSourceManager().getDecomposedSpellingLoc(Pos).second;
std::vector<const NamedDecl *> Result;
- SelectionTree::createEach(AST.getASTContext(), AST.getTokens(), Offset,
- Offset, [&](SelectionTree ST) {
- if (const SelectionTree::Node *N =
- ST.commonAncestor())
- llvm::copy(targetDecl(N->ASTNode, Relations),
- std::back_inserter(Result));
- return !Result.empty();
- });
+ SelectionTree::createEach(
+ AST.getASTContext(), AST.getTokens(), Offset, Offset,
+ [&](SelectionTree ST) {
+ if (const SelectionTree::Node *N = ST.commonAncestor()) {
+ if (IsDependentName && isDependentName(N->ASTNode))
+ *IsDependentName = true;
+ llvm::copy(targetDecl(N->ASTNode, Relations),
+ std::back_inserter(Result));
+ }
+ return !Result.empty();
+ });
return Result;
}
@@ -221,7 +234,7 @@
std::vector<LocatedSymbol>
locateASTReferent(SourceLocation CurLoc, const syntax::Token *TouchedIdentifier,
ParsedAST &AST, llvm::StringRef MainFilePath,
- const SymbolIndex *Index) {
+ const SymbolIndex *Index, bool *IsDependentName) {
const SourceManager &SM = AST.getSourceManager();
// Results follow the order of Symbols.Decls.
std::vector<LocatedSymbol> Result;
@@ -250,7 +263,8 @@
// Emit all symbol locations (declaration or definition) from AST.
DeclRelationSet Relations =
DeclRelation::TemplatePattern | DeclRelation::Alias;
- for (const NamedDecl *D : getDeclAtPosition(AST, CurLoc, Relations)) {
+ for (const NamedDecl *D :
+ getDeclAtPosition(AST, CurLoc, Relations, IsDependentName)) {
// Special case: void foo() ^override: jump to the overridden method.
if (const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
const InheritableAttr *Attr = D->getAttr<OverrideAttr>();
@@ -336,10 +350,11 @@
std::vector<LocatedSymbol>
locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST,
- const SymbolIndex *Index,
- const std::string &MainFilePath) {
- // Don't use heuristics if this is a real identifier, or not an identifier.
- if (Word.ExpandedToken || !Word.LikelyIdentifier || !Index)
+ const SymbolIndex *Index, const std::string &MainFilePath,
+ bool IsDependent) {
+ // Don't use heuristics if this is a real non-dependent identifier, or not an
+ // identifier.
+ if ((Word.ExpandedToken && !IsDependent) || !Word.LikelyIdentifier || !Index)
return {};
// We don't want to handle words in string literals. It'd be nice to whitelist
// comments instead, but they're not retained in TokenBuffer.
@@ -535,8 +550,9 @@
// expansion.)
return {*std::move(Macro)};
- auto ASTResults =
- locateASTReferent(*CurLoc, TouchedIdentifier, AST, *MainFilePath, Index);
+ bool IsDependentName = false;
+ auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST,
+ *MainFilePath, Index, &IsDependentName);
if (!ASTResults.empty())
return ASTResults;
@@ -550,13 +566,13 @@
if (auto Macro = locateMacroReferent(*NearbyIdent, AST, *MainFilePath))
return {*std::move(Macro)};
ASTResults = locateASTReferent(NearbyIdent->location(), NearbyIdent, AST,
- *MainFilePath, Index);
+ *MainFilePath, Index, &IsDependentName);
if (!ASTResults.empty())
return ASTResults;
}
// No nearby word, or it didn't refer to anything either. Try the index.
- auto TextualResults =
- locateSymbolTextually(*Word, AST, Index, *MainFilePath);
+ auto TextualResults = locateSymbolTextually(*Word, AST, Index,
+ *MainFilePath, IsDependentName);
if (!TextualResults.empty())
return TextualResults;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits