kbobyrev created this revision. kbobyrev added a reviewer: kadircet. Herald added subscribers: usaxena95, arphaman, jkorous, MaskRay, ilya-biryukov. Herald added a project: clang. kbobyrev added a subscriber: hokein.
This patch allows the index does to provide a way to distinguish implicit references (e.g. coming from macro expansions). The corresponding flag was added to RefKind and symbols that are referenced without spelling their name explicitly are now marked implicit. This fixes incorrect behavior when renaming a symbol that was referenced in macro expansions would try to rename macro invocations. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D72746 Files: clang-tools-extra/clangd/index/Ref.h clang-tools-extra/clangd/index/SymbolCollector.cpp clang-tools-extra/clangd/refactor/Rename.cpp clang-tools-extra/clangd/unittests/RenameTests.cpp
Index: clang-tools-extra/clangd/unittests/RenameTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/RenameTests.cpp +++ clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -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) { Index: clang-tools-extra/clangd/refactor/Rename.cpp =================================================================== --- clang-tools-extra/clangd/refactor/Rename.cpp +++ 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<unsigned>(R.Kind & RefKind::Implicit)) + return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { if (*RefFilePath != MainFile) AffectedFiles[*RefFilePath].push_back(toRange(R.Location)); Index: clang-tools-extra/clangd/index/SymbolCollector.cpp =================================================================== --- clang-tools-extra/clangd/index/SymbolCollector.cpp +++ clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -180,7 +180,14 @@ } RefKind toRefKind(index::SymbolRoleSet Roles) { - return static_cast<RefKind>(static_cast<unsigned>(RefKind::All) & Roles); + // Because RefKind::Implicit != index::SymbolRole::Implicit because due to the + // memory considerations, all flags except "Implicit" should be set + // independently. + auto Result = + static_cast<RefKind>(static_cast<unsigned>(RefKind::NotImplicit) & Roles); + if (Roles & static_cast<unsigned>(index::SymbolRole::Implicit)) + Result |= RefKind::Implicit; + return Result; } bool shouldIndexRelation(const index::SymbolRelation &R) { @@ -291,7 +298,17 @@ // occurrence inside the base-specifier. processRelations(*ND, *ID, Relations); - bool CollectRef = static_cast<unsigned>(Opts.RefFilter) & Roles; + // 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(Loc, Buffer, SM, ASTCtx->getLangOpts()); + DeclarationName Name = ND->getDeclName(); + if (Name.isIdentifier() && Name.getAsString() != Spelling) + Roles |= static_cast<uint32_t>(index::SymbolRole::Implicit); + + bool CollectRef = static_cast<unsigned>(Opts.RefFilter & toRefKind(Roles)); bool IsOnlyRef = !(Roles & (static_cast<unsigned>(index::SymbolRole::Declaration) | static_cast<unsigned>(index::SymbolRole::Definition))); Index: clang-tools-extra/clangd/index/Ref.h =================================================================== --- clang-tools-extra/clangd/index/Ref.h +++ clang-tools-extra/clangd/index/Ref.h @@ -30,7 +30,12 @@ Declaration = static_cast<uint8_t>(index::SymbolRole::Declaration), Definition = static_cast<uint8_t>(index::SymbolRole::Definition), Reference = static_cast<uint8_t>(index::SymbolRole::Reference), - All = Declaration | Definition | Reference, + // This corresponds to index::SymbolRole::Implicit. In order to save memory + // and keep RefKind occupying 1 byte, the original value is modified to the + // one below. + Implicit = 1 << 3, + All = Declaration | Definition | Reference | Implicit, + NotImplicit = Declaration | Definition | Reference, }; inline RefKind operator|(RefKind L, RefKind R) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits