Index: clang-move/ClangMove.cpp =================================================================== --- clang-move/ClangMove.cpp +++ clang-move/ClangMove.cpp @@ -136,6 +136,27 @@ ClangMoveTool *const MoveTool; }; +class FunctionDeclarationMatch : public MatchFinder::MatchCallback { + public: + explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool) + : MoveTool(MoveTool) {} + + void run(const MatchFinder::MatchResult &Result) override { + auto *SM = &Result.Context->getSourceManager(); + if (const auto *FD = + Result.Nodes.getNodeAs("function")) { + const clang::NamedDecl *D = FD; + if (const auto *FTD = FD->getDescribedFunctionTemplate()) + D = FTD; + MoveTool->getMovedDecls().emplace_back(D, SM); + MoveTool->getUnremovedDeclsInOldHeader().erase(D); + MoveTool->getRemovedDecls().push_back(MoveTool->getMovedDecls().back()); + } + } + private: + ClangMoveTool *MoveTool; +}; + class ClassDeclarationMatch : public MatchFinder::MatchCallback { public: explicit ClassDeclarationMatch(ClangMoveTool *MoveTool) @@ -389,15 +410,15 @@ } void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { - Optional> InMovedClassNames; - for (StringRef ClassName : Spec.Names) { - llvm::StringRef GlobalClassName = ClassName.trim().ltrim(':'); - const auto HasName = hasName(("::" + GlobalClassName).str()); - InMovedClassNames = - InMovedClassNames ? anyOf(*InMovedClassNames, HasName) : HasName; + Optional> HasAnySymbolNames; + for (StringRef SymbolName: Spec.Names) { + llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':'); + const auto HasName = hasName(("::" + GlobalSymbolName).str()); + HasAnySymbolNames = + HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName; } - if (!InMovedClassNames) { - llvm::errs() << "No classes being moved.\n"; + if (!HasAnySymbolNames) { + llvm::errs() << "No symbols being moved.\n"; return; } @@ -405,7 +426,7 @@ auto InOldCC = isExpansionInFile(makeAbsolutePath(Spec.OldCC)); auto InOldFiles = anyOf(InOldHeader, InOldCC); auto InMovedClass = - hasOutermostEnclosingClass(cxxRecordDecl(*InMovedClassNames)); + hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames)); auto ForwardDecls = cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition()))); @@ -466,14 +487,14 @@ // Match moved class declarations. auto MovedClass = cxxRecordDecl( - InOldFiles, *InMovedClassNames, isDefinition(), + InOldFiles, *HasAnySymbolNames, isDefinition(), hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()))) .bind("moved_class"); Finder->addMatcher(MovedClass, MatchCallbacks.back().get()); // Match moved class methods (static methods included) which are defined // outside moved class declaration. Finder->addMatcher( - cxxMethodDecl(InOldFiles, ofOutermostEnclosingClass(*InMovedClassNames), + cxxMethodDecl(InOldFiles, ofOutermostEnclosingClass(*HasAnySymbolNames), isDefinition()) .bind("class_method"), MatchCallbacks.back().get()); @@ -483,6 +504,12 @@ .bind("class_static_var_decl"), MatchCallbacks.back().get()); + MatchCallbacks.push_back(llvm::make_unique(this)); + Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, + anyOf(hasDeclContext(namespaceDecl()), + hasDeclContext(translationUnitDecl()))) + .bind("function"), + MatchCallbacks.back().get()); } void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) { Index: test/clang-move/Inputs/function_test.h =================================================================== --- /dev/null +++ test/clang-move/Inputs/function_test.h @@ -0,0 +1,14 @@ +void f(); + +inline int g() { return 0; } + +template +void h(T t) {} + +template<> +void h(int t) {} + +class A { + public: + void f(); +}; Index: test/clang-move/Inputs/function_test.cpp =================================================================== --- /dev/null +++ test/clang-move/Inputs/function_test.cpp @@ -0,0 +1,5 @@ +#include "function_test.h" + +void f() {} + +void A::f() {} Index: test/clang-move/move-function.cpp =================================================================== --- /dev/null +++ test/clang-move/move-function.cpp @@ -0,0 +1,67 @@ +// RUN: mkdir -p %T/move-function +// RUN: cp %S/Inputs/function_test* %T/move-function +// RUN: cd %T/move-function +// RUN: clang-move -names="g" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp -- +// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s +// +// CHECK-NEW-TEST-H-CASE1: #ifndef {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE1: #define {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE1: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE1: inline int g() { return 0; } +// CHECK-NEW-TEST-H-CASE1: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE1: #endif // {{.*}}NEW_FUNCTION_TEST_H +// +// RUN: cp %S/Inputs/function_test* %T/move-function +// RUN: clang-move -names="h" -new_header=%T/move-function/new_function_test.h -old_header=../move-function/function_test.h %T/move-function/function_test.cpp -- +// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s +// +// CHECK-NEW-TEST-H-CASE2: #ifndef {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE2: #define {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE2: template void h(T t) {} +// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE2: template <> void h(int t) {} +// CHECK-NEW-TEST-H-CASE2: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE2: #endif // {{.*}}NEW_FUNCTION_TEST_H +// +// RUN: cp %S/Inputs/function_test* %T/move-function +// RUN: clang-move -names="f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp -- +// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE3 %s +// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE3 %s +// +// CHECK-NEW-TEST-H-CASE3: #ifndef {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE3: #define {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE3: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE3: void f(); +// CHECK-NEW-TEST-H-CASE3: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE3: #endif // {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-CPP-CASE3: #include "{{.*}}new_function_test.h" +// CHECK-NEW-TEST-CPP-CASE3: {{[[:space:]]+}} +// CHECK-NEW-TEST-CPP-CASE3: void f() {} +// +// RUN: cp %S/Inputs/function_test* %T/move-function +// RUN: clang-move -names="A::f" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp -dump_result -- | FileCheck %s -check-prefix=CHECK-EMPTY +// +// CHECK-EMPTY: [{{[[:space:]]*}}] +// +// RUN: cp %S/Inputs/function_test* %T/move-function +// RUN: clang-move -names="f,A" -new_header=%T/move-function/new_function_test.h -new_cc=%T/move-function/new_function_test.cpp -old_header=../move-function/function_test.h -old_cc=../move-function/function_test.cpp %T/move-function/function_test.cpp -- +// RUN: FileCheck -input-file=%T/move-function/new_function_test.h -check-prefix=CHECK-NEW-TEST-H-CASE4 %s +// RUN: FileCheck -input-file=%T/move-function/new_function_test.cpp -check-prefix=CHECK-NEW-TEST-CPP-CASE4 %s + +// CHECK-NEW-TEST-H-CASE4: #ifndef {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE4: #define {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE4: void f(); +// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE4: class A { +// CHECK-NEW-TEST-H-CASE4: public: +// CHECK-NEW-TEST-H-CASE4: void f(); +// CHECK-NEW-TEST-H-CASE4: }; +// CHECK-NEW-TEST-H-CASE4: {{[[:space:]]+}} +// CHECK-NEW-TEST-H-CASE4: #endif // {{.*}}NEW_FUNCTION_TEST_H +// CHECK-NEW-TEST-CPP-CASE4: #include "{{.*}}new_function_test.h" +// CHECK-NEW-TEST-CPP-CASE4: {{[[:space:]]+}} +// CHECK-NEW-TEST-CPP-CASE4: void f() {} +// CHECK-NEW-TEST-CPP-CASE4: {{[[:space:]]+}} +// CHECK-NEW-TEST-CPP-CASE4: void A::f() {}