diff --git a/clang-tools-extra/clangd/index/Ref.h b/clang-tools-extra/clangd/index/Ref.h --- a/clang-tools-extra/clangd/index/Ref.h +++ b/clang-tools-extra/clangd/index/Ref.h @@ -27,10 +27,11 @@ /// This is a bitfield which can be combined from different kinds. enum class RefKind : uint8_t { Unknown = 0, - Declaration = static_cast(index::SymbolRole::Declaration), - Definition = static_cast(index::SymbolRole::Definition), - Reference = static_cast(index::SymbolRole::Reference), - All = Declaration | Definition | Reference, + Declaration = 1 << 0, + Definition = 1 << 1, + Reference = 1 << 2, + Spelled = 1 << 3, + All = Declaration | Definition | Reference | Spelled, }; inline RefKind operator|(RefKind L, RefKind R) { diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -28,6 +28,7 @@ #include "clang/Index/IndexingAction.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Tooling/Syntax/Tokens.h" #include "llvm/Support/Casting.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -180,7 +181,16 @@ } RefKind toRefKind(index::SymbolRoleSet Roles) { - return static_cast(static_cast(RefKind::All) & Roles); + RefKind Result = RefKind::Unknown; + if (Roles & static_cast(index::SymbolRole::Declaration)) + Result |= RefKind::Declaration; + if (Roles & static_cast(index::SymbolRole::Definition)) + Result |= RefKind::Definition; + if (Roles & static_cast(index::SymbolRole::Reference)) + Result |= RefKind::Reference; + if (!(Roles & static_cast(index::SymbolRole::Implicit))) + Result |= RefKind::Spelled; + return Result; } bool shouldIndexRelation(const index::SymbolRelation &R) { @@ -291,7 +301,7 @@ // occurrence inside the base-specifier. processRelations(*ND, *ID, Relations); - bool CollectRef = static_cast(Opts.RefFilter) & Roles; + bool CollectRef = static_cast(Opts.RefFilter & toRefKind(Roles)); bool IsOnlyRef = !(Roles & (static_cast(index::SymbolRole::Declaration) | static_cast(index::SymbolRole::Definition))); @@ -578,10 +588,22 @@ } // Populate Refs slab from DeclRefs. if (auto MainFileURI = GetURI(SM.getMainFileID())) { - for (const auto &It : DeclRefs) { - if (auto ID = getSymbolID(It.first)) { - for (const auto &LocAndRole : It.second) + for (auto &DeclAndRef : DeclRefs) { + if (auto ID = getSymbolID(DeclAndRef.first)) { + for (auto &LocAndRole : DeclAndRef.second) { + // Check if the referenced symbol is spelled exactly the same way the + // corresponding NamedDecl is. If it isn't, mark this reference as + // implicit. An example of implicit references would be a macro + // expansion. + llvm::SmallString<16> Buffer; + const auto Spelling = Lexer::getSpelling(LocAndRole.first, Buffer, SM, + ASTCtx->getLangOpts()); + DeclarationName Name = DeclAndRef.first->getDeclName(); + if (Name.isIdentifier() && Name.getAsString() != Spelling) + LocAndRole.second |= + static_cast(index::SymbolRole::Implicit); CollectRef(*ID, LocAndRole); + } } } } diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -296,6 +296,8 @@ bool HasMore = Index.refs(RQuest, [&](const Ref &R) { if (AffectedFiles.size() > MaxLimitFiles) return; + if (!static_cast(R.Kind & RefKind::Spelled)) + return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { if (*RefFilePath != MainFile) AffectedFiles[*RefFilePath].push_back(toRange(R.Location)); diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -33,7 +33,7 @@ // Convert a Range to a Ref. Ref refWithRange(const clangd::Range &Range, const std::string &URI) { Ref Result; - Result.Kind = RefKind::Reference; + Result.Kind = RefKind::Reference | RefKind::Spelled; Result.Location.Start.setLine(Range.start.line); Result.Location.Start.setColumn(Range.start.character); Result.Location.End.setLine(Range.end.line); @@ -837,7 +837,7 @@ { // variables. R"cpp( - static const int [[VA^R]] = 123; + static const int [[VA^R]] = 123; )cpp", R"cpp( #include "foo.h" @@ -868,6 +868,22 @@ } )cpp", }, + { + // Implicit references in macro expansions. + R"cpp( + class [[Fo^o]] {}; + #define FooFoo Foo + #define FOO Foo + )cpp", + R"cpp( + #include "foo.h" + void bar() { + [[Foo]] x; + FOO y; + FooFoo z; + } + )cpp", + }, }; for (const auto& T : Cases) {