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

Reply via email to