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