diff options
4 files changed, 150 insertions, 11 deletions
diff --git a/clang-tools-extra/clang-move/ClangMove.cpp b/clang-tools-extra/clang-move/ClangMove.cpp index e23db7474b4..61922f78b5a 100644 --- a/clang-tools-extra/clang-move/ClangMove.cpp +++ b/clang-tools-extra/clang-move/ClangMove.cpp @@ -364,16 +364,15 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { isDefinition()) .bind("class_method"), this); - - //============================================================================ - // Matchers for old cc - //============================================================================ // Match static member variable definition of the moved class. Finder->addMatcher( - varDecl(InMovedClass, InOldCC, isDefinition(), isStaticDataMember()) + varDecl(InMovedClass, InOldFiles, isDefinition(), isStaticDataMember()) .bind("class_static_var_decl"), this); + //============================================================================ + // Matchers for old cc + //============================================================================ auto InOldCCNamedNamespace = allOf(hasParent(namespaceDecl(unless(isAnonymous()))), InOldCC); // Matching using decls/type alias decls which are in named namespace. Those @@ -412,25 +411,36 @@ void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) { if (!CMD->isInlined()) { MovedDecls.emplace_back(CMD, &Result.Context->getSourceManager()); RemovedDecls.push_back(MovedDecls.back()); + // Get template class method from its method declaration as + // UnremovedDecls stores template class method. + if (const auto *FTD = CMD->getDescribedFunctionTemplate()) + UnremovedDeclsInOldHeader.erase(FTD); + else + UnremovedDeclsInOldHeader.erase(CMD); } } else if (const auto *VD = Result.Nodes.getNodeAs<clang::VarDecl>( "class_static_var_decl")) { MovedDecls.emplace_back(VD, &Result.Context->getSourceManager()); RemovedDecls.push_back(MovedDecls.back()); - } else if (const auto *class_decl = + UnremovedDeclsInOldHeader.erase(MovedDecls.back().Decl); + } else if (const auto *CD = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("moved_class")) { - MovedDecls.emplace_back(class_decl, &Result.Context->getSourceManager()); + // Get class template from its class declaration as UnremovedDecls stores + // class template. + if (const auto * TC = CD->getDescribedClassTemplate()) + MovedDecls.emplace_back(TC, &Result.Context->getSourceManager()); + else + MovedDecls.emplace_back(CD, &Result.Context->getSourceManager()); RemovedDecls.push_back(MovedDecls.back()); - UnremovedDeclsInOldHeader.erase(class_decl); + UnremovedDeclsInOldHeader.erase(MovedDecls.back().Decl); } else if (const auto *FWD = Result.Nodes.getNodeAs<clang::CXXRecordDecl>("fwd_decl")) { // Skip all forwad declarations which appear after moved class declaration. if (RemovedDecls.empty()) { - if (const auto *DCT = FWD->getDescribedClassTemplate()) { + if (const auto *DCT = FWD->getDescribedClassTemplate()) MovedDecls.emplace_back(DCT, &Result.Context->getSourceManager()); - } else { + else MovedDecls.emplace_back(FWD, &Result.Context->getSourceManager()); - } } } else if (const auto *ANS = Result.Nodes.getNodeAs<clang::NamespaceDecl>("anonymous_ns")) { diff --git a/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp b/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp new file mode 100644 index 00000000000..8ad2dcb1eda --- /dev/null +++ b/clang-tools-extra/test/clang-move/Inputs/template_class_test.cpp @@ -0,0 +1,13 @@ +#include "template_class_test.h" + +template <typename T> +void A<T>::g() {} + +template <typename T> +template <typename U> +void A<T>::k() {} + +template <typename T> +int A<T>::c = 2; + +void B::f() {} diff --git a/clang-tools-extra/test/clang-move/Inputs/template_class_test.h b/clang-tools-extra/test/clang-move/Inputs/template_class_test.h new file mode 100644 index 00000000000..d42a158a6f9 --- /dev/null +++ b/clang-tools-extra/test/clang-move/Inputs/template_class_test.h @@ -0,0 +1,30 @@ +#ifndef TEMPLATE_CLASS_TEST_H // comment 1 +#define TEMPLATE_CLASS_TEST_H + +template <typename T> +class A { + public: + void f(); + void g(); + template <typename U> void h(); + template <typename U> void k(); + static int b; + static int c; +}; + +template <typename T> +void A<T>::f() {} + +template <typename T> +template <typename U> +void A<T>::h() {} + +template <typename T> +int A<T>::b = 2; + +class B { + public: + void f(); +}; + +#endif // TEMPLATE_CLASS_TEST_H diff --git a/clang-tools-extra/test/clang-move/move-template-class.cpp b/clang-tools-extra/test/clang-move/move-template-class.cpp new file mode 100644 index 00000000000..1a6a60bd2bd --- /dev/null +++ b/clang-tools-extra/test/clang-move/move-template-class.cpp @@ -0,0 +1,86 @@ +// RUN: mkdir -p %T/move-template-class +// RUN: cp %S/Inputs/template_class_test* %T/move-template-class +// RUN: cd %T/move-template-class +// RUN: clang-move -names="A,B" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp -- +// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s +// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-EMPTY -allow-empty %s +// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE1 %s +// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s +// +// RUN: cp %S/Inputs/template_class_test* %T/move-template-class +// RUN: clang-move -names="A" -new_cc=%T/move-template-class/new_template_class_test.cpp -new_header=%T/move-template-class/new_template_class_test.h -old_cc=%T/move-template-class/template_class_test.cpp -old_header=../move-template-class/template_class_test.h %T/move-template-class/template_class_test.cpp -- +// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s +// RUN: FileCheck -input-file=%T/move-template-class/template_class_test.cpp -check-prefix=CHECK-OLD-TEST-CPP-CASE2 %s +// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s +// RUN: FileCheck -input-file=%T/move-template-class/new_template_class_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE2 %s +// +// +// CHECK-OLD-TEST-EMPTY: {{^}}{{$}} +// +// CHECK-NEW-TEST-H-CASE1: #ifndef TEMPLATE_CLASS_TEST_H // comment 1 +// CHECK-NEW-TEST-H-CASE1: #define TEMPLATE_CLASS_TEST_H +// CHECK-NEW-TEST-H-CASE1: template <typename T> +// CHECK-NEW-TEST-H-CASE1: class A { +// CHECK-NEW-TEST-H-CASE1: public: +// CHECK-NEW-TEST-H-CASE1: void f(); +// CHECK-NEW-TEST-H-CASE1: void g(); +// CHECK-NEW-TEST-H-CASE1: template <typename U> void h(); +// CHECK-NEW-TEST-H-CASE1: template <typename U> void k(); +// CHECK-NEW-TEST-H-CASE1: static int b; +// CHECK-NEW-TEST-H-CASE1: static int c; +// CHECK-NEW-TEST-H-CASE1: }; +// CHECK-NEW-TEST-H-CASE1: template <typename T> +// CHECK-NEW-TEST-H-CASE1: void A<T>::f() {} +// CHECK-NEW-TEST-H-CASE1: template <typename T> +// CHECK-NEW-TEST-H-CASE1: template <typename U> +// CHECK-NEW-TEST-H-CASE1: void A<T>::h() {} +// CHECK-NEW-TEST-H-CASE1: template <typename T> +// CHECK-NEW-TEST-H-CASE1: int A<T>::b = 2; +// CHECK-NEW-TEST-H-CASE1: class B { +// CHECK-NEW-TEST-H-CASE1: public: +// CHECK-NEW-TEST-H-CASE1: void f(); +// CHECK-NEW-TEST-H-CASE1: }; +// CHECK-NEW-TEST-H-CASE1: #endif // TEMPLATE_CLASS_TEST_H +// +// CHECK-NEW-TEST-CPP-CASE1: #include "{{.*}}new_template_class_test.h" +// CHECK-NEW-TEST-CPP-CASE1: template <typename T> +// CHECK-NEW-TEST-CPP-CASE1: void A<T>::g() {} +// CHECK-NEW-TEST-CPP-CASE1: template <typename T> +// CHECK-NEW-TEST-CPP-CASE1: template <typename U> +// CHECK-NEW-TEST-CPP-CASE1: void A<T>::k() {} +// CHECK-NEW-TEST-CPP-CASE1: template <typename T> +// CHECK-NEW-TEST-CPP-CASE1: int A<T>::c = 2; +// CHECK-NEW-TEST-CPP-CASE1: void B::f() {} +// +// CHECK-OLD-TEST-H-CASE2: #ifndef TEMPLATE_CLASS_TEST_H // comment 1 +// CHECK-OLD-TEST-H-CASE2: #define TEMPLATE_CLASS_TEST_H +// CHECK-OLD-TEST-H-CASE2: class B { +// CHECK-OLD-TEST-H-CASE2: public: +// CHECK-OLD-TEST-H-CASE2: void f(); +// CHECK-OLD-TEST-H-CASE2: }; +// CHECK-OLD-TEST-H-CASE2: #endif // TEMPLATE_CLASS_TEST_H +// +// CHECK-OLD-TEST-CPP-CASE2: #include "template_class_test.h" +// CHECK-OLD-TEST-CPP-CASE2: void B::f() {} +// +// CHECK-NEW-TEST-H-CASE2: #ifndef {{.*}}NEW_TEMPLATE_CLASS_TEST_H +// CHECK-NEW-TEST-H-CASE2: #define {{.*}}NEW_TEMPLATE_CLASS_TEST_H +// CHECK-NEW-TEST-H-CASE2: template <typename T> +// CHECK-NEW-TEST-H-CASE2: class A { +// CHECK-NEW-TEST-H-CASE2: public: +// CHECK-NEW-TEST-H-CASE2: void f(); +// CHECK-NEW-TEST-H-CASE2: void g(); +// CHECK-NEW-TEST-H-CASE2: template <typename U> void h(); +// CHECK-NEW-TEST-H-CASE2: template <typename U> void k(); +// CHECK-NEW-TEST-H-CASE2: static int b; +// CHECK-NEW-TEST-H-CASE2: static int c; +// CHECK-NEW-TEST-H-CASE2: }; +// CHECK-NEW-TEST-H-CASE2: template <typename T> void A<T>::f() {} +// CHECK-NEW-TEST-H-CASE2: template <typename T> template <typename U> void A<T>::h() {} +// CHECK-NEW-TEST-H-CASE2: template <typename T> int A<T>::b = 2; +// CHECK-NEW-TEST-H-CASE2: #endif // {{.*}}NEW_TEMPLATE_CLASS_TEST_H +// +// CHECK-NEW-TEST-CPP-CASE2: #include "{{.*}}new_template_class_test.h" +// CHECK-NEW-TEST-CPP-CASE2: template <typename T> void A<T>::g() {} +// CHECK-NEW-TEST-CPP-CASE2: template <typename T> template <typename U> void A<T>::k() {} +// CHECK-NEW-TEST-CPP-CASE2: template <typename T> int A<T>::c = 2; |

