kbobyrev created this revision.
kbobyrev added a reviewer: hokein.
Herald added subscribers: cfe-commits, usaxena95, arphaman.
Herald added a project: clang.
kbobyrev requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

This was originally a part of D71880 <https://reviews.llvm.org/D71880> but is 
separated for simplicity and ease
of reviewing.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D91952

Files:
  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
@@ -540,6 +540,81 @@
         }
       )cpp",
 
+      // Fields in classes & partial and full specialiations.
+      R"cpp(
+        class Foo {
+        public:
+          Foo(int Variable) : [[Variabl^e]](Variable) {}
+
+          int [[Va^riable]] = 42;
+
+        private:
+          void foo() { ++[[Vari^able]]; }
+        };
+
+        void bar() {
+          Foo f(9000);
+          f.[[Variable^]] = -1;
+        }
+      )cpp",
+      R"cpp(
+        template<typename T>
+        struct Foo {
+          T [[Vari^able]] = 42;
+        };
+
+        void foo() {
+          Foo<int> f;
+          f.[[Varia^ble]] = 9000;
+        }
+      )cpp",
+      R"cpp(
+        template<typename T, typename U>
+        struct Foo {
+          T Variable[42];
+          U Another;
+
+          void bar() {}
+        };
+
+        template<typename T>
+        struct Foo<T, bool> {
+          T [[Var^iable]];
+          void bar() { ++[[Var^iable]]; }
+        };
+
+        void foo() {
+          Foo<unsigned, bool> f;
+          f.[[Var^iable]] = 9000;
+        }
+      )cpp",
+      R"cpp(
+        template<typename T, typename U>
+        struct Foo {
+          T Variable[42];
+          U Another;
+
+          void bar() {}
+        };
+
+        template<typename T>
+        struct Foo<T, bool> {
+          T Variable;
+          void bar() { ++Variable; }
+        };
+
+        template<>
+        struct Foo<unsigned, bool> {
+          unsigned [[Var^iable]];
+          void bar() { ++[[Var^iable]]; }
+        };
+
+        void foo() {
+          Foo<unsigned, bool> f;
+          f.[[Var^iable]] = 9000;
+        }
+      )cpp",
+
       // Template parameters.
       R"cpp(
         template <typename [[^T]]>
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===================================================================
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -119,11 +119,35 @@
     // declaration.
     while (Method->isVirtual() && Method->size_overridden_methods())
       Method = *Method->overridden_methods().begin();
-    return dyn_cast<NamedDecl>(Method->getCanonicalDecl());
+    return Method->getCanonicalDecl();
   }
   if (const auto *Function = dyn_cast<FunctionDecl>(D))
     if (const FunctionTemplateDecl *Template = Function->getPrimaryTemplate())
       return canonicalRenameDecl(Template);
+  if (const auto *Field = dyn_cast<FieldDecl>(D)) {
+    // This is a hacky way to do something like
+    // CXXMethodDecl::getInstantiatedFromMemberFunction for the field because
+    // Clang AST does not store relevant information about the field that is
+    // instantiated.
+    const auto *TemplateSpec =
+        dyn_cast<ClassTemplateSpecializationDecl>(Field->getParent());
+    if (!TemplateSpec)
+      return Field->getCanonicalDecl();
+    const CXXRecordDecl *FieldParent =
+        TemplateSpec->getTemplateInstantiationPattern();
+    // Field is not instantiation.
+    if (!FieldParent || Field->getParent() == FieldParent)
+      return Field->getCanonicalDecl();
+    for (const FieldDecl *Candidate : FieldParent->fields()) {
+      if (Field->getFieldIndex() == Candidate->getFieldIndex()) {
+        assert(Field->getLocation() == Candidate->getLocation() &&
+               "Field should be generated from Candidate so it has the same "
+               "location.");
+        return Candidate->getCanonicalDecl();
+      }
+    }
+    llvm_unreachable("FieldParent should have field with same index as Field.");
+  }
   return dyn_cast<NamedDecl>(D->getCanonicalDecl());
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to