omtcyfz created this revision.
omtcyfz added reviewers: alexfh, klimek.
omtcyfz added a subscriber: cfe-commits.
This patch introduces basic capabilities of renaming templated class and its 
specializations.

https://reviews.llvm.org/D23058

Files:
  clang-rename/USRFinder.cpp
  clang-rename/USRFindingAction.cpp
  test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
  test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
  test/clang-rename/TemplateClassInstantiationFindByUninstantiatedType.cpp

Index: test/clang-rename/TemplateClassInstantiationFindByUninstantiatedType.cpp
===================================================================
--- /dev/null
+++ test/clang-rename/TemplateClassInstantiationFindByUninstantiatedType.cpp
@@ -0,0 +1,39 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-rename -offset=440 -new-name=Bar %t.cpp -i --
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+template <typename T>
+class Foo {               // CHECK: class Bar {
+public:
+  T foo(T arg, T& ref, T* ptr) {
+    T value;
+    int number = 42;
+    value = (T)number;
+    value = static_cast<T>(number);
+    return value;
+  }
+  static void foo(T value) {}
+  T member;
+};
+
+template <typename T>
+void func() {
+  Foo<T> obj;             // CHECK: Bar<T> obj;
+  obj.member = T();
+  Foo<T>::foo();          // CHECK: Bar<T>::foo();
+}
+
+int main() {
+  Foo<int> i;             // CHECK: Bar<int> i;
+  i.member = 0;
+  Foo<int>::foo(0);       // CHECK: Bar<int>::foo(0);
+
+  Foo<bool> b;            // CHECK: Bar<bool> b;
+  b.member = false;
+  Foo<bool>::foo(false);  // CHECK: Bar<bool>::foo(false);
+
+  return 0;
+}
+
+// Use grep -FUbo 'Foo' <file> to get the correct offset of foo when changing
+// this file.
Index: test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
===================================================================
--- test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
+++ test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
@@ -1,14 +1,9 @@
 // RUN: cat %s > %t.cpp
-// RUN: clang-rename -offset=703 -new-name=Bar %t.cpp -i --
+// RUN: clang-rename -offset=575 -new-name=Bar %t.cpp -i --
 // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
 
-// Currently unsupported test.
-// FIXME: clang-rename should be able to rename classes with templates
-// correctly.
-// XFAIL: *
-
 template <typename T>
-class Foo {               // CHECK: class Bar;
+class Foo {               // CHECK: class Bar {
 public:
   T foo(T arg, T& ref, T* ptr) {
     T value;
Index: test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
===================================================================
--- test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
+++ test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
@@ -1,14 +1,9 @@
 // RUN: cat %s > %t.cpp
-// RUN: clang-rename -offset=287 -new-name=Bar %t.cpp -i --
+// RUN: clang-rename -offset=159 -new-name=Bar %t.cpp -i --
 // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
 
-// Currently unsupported test.
-// FIXME: clang-rename should be able to rename classes with templates
-// correctly.
-// XFAIL: *
-
 template <typename T>
-class Foo {               // CHECK: class Bar;
+class Foo {               // CHECK: class Bar {
 public:
   T foo(T arg, T& ref, T* ptr) {
     T value;
Index: clang-rename/USRFindingAction.cpp
===================================================================
--- clang-rename/USRFindingAction.cpp
+++ clang-rename/USRFindingAction.cpp
@@ -53,12 +53,14 @@
     : FoundDecl(FoundDecl), Context(Context), USRs(USRs), USRSet(), Finder() {}
 
   void Find() {
-    USRSet.insert(getUSRForDecl(FoundDecl));
     if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
       addUSRsFromOverrideSets(MethodDecl);
-    }
-    if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
-      addUSRsOfCtorDtors(RecordDecl);
+    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
+      handleCXXRecordDecl(RecordDecl);
+    } else if (const auto *TemplateDecl = dyn_cast<ClassTemplateDecl>(FoundDecl)) {
+      handleClassTemplateDecl(TemplateDecl);
+    } else {
+      USRSet.insert(getUSRForDecl(FoundDecl));
     }
     addMatchers();
     Finder.matchAST(Context);
@@ -87,12 +89,29 @@
     }
   }
 
+  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
+    RecordDecl = RecordDecl->getDefinition();
+    if (const auto *ClassTemplateSpecDecl
+            = dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl)) {
+      handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
+    }
+    addUSRsOfCtorDtors(RecordDecl);
+  }
+
+  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
+    for (const auto *Specialization : TemplateDecl->specializations()) {
+      addUSRsOfCtorDtors(Specialization);
+    }
+    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
+  }
+
   void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
     RecordDecl = RecordDecl->getDefinition();
     for (const auto *CtorDecl : RecordDecl->ctors()) {
       USRSet.insert(getUSRForDecl(CtorDecl));
     }
     USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
+    USRSet.insert(getUSRForDecl(RecordDecl));
   }
 
   void addUSRsFromOverrideSets(const CXXMethodDecl *MethodDecl) {
Index: clang-rename/USRFinder.cpp
===================================================================
--- clang-rename/USRFinder.cpp
+++ clang-rename/USRFinder.cpp
@@ -81,6 +81,11 @@
             dyn_cast<TemplateTypeParmType>(Loc.getType())) {
       return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
     }
+    if (const auto *TemplateSpecType =
+            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+      return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+                       TypeBeginLoc, TypeEndLoc);
+    }
     return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
                      TypeEndLoc);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to