Index: clang-tools-extra/trunk/clang-move/ClangMove.cpp =================================================================== --- clang-tools-extra/trunk/clang-move/ClangMove.cpp +++ clang-tools-extra/trunk/clang-move/ClangMove.cpp @@ -140,6 +140,14 @@ ClangMoveTool *const MoveTool; }; +/// Add a declatration being moved to new.h/cc. Note that the declaration will +/// also be deleted in old.h/cc. +void MoveDeclFromOldFileToNewFile(ClangMoveTool *MoveTool, const NamedDecl *D) { + MoveTool->getMovedDecls().push_back(D); + MoveTool->addRemovedDecl(D); + MoveTool->getUnremovedDeclsInOldHeader().erase(D); +} + class FunctionDeclarationMatch : public MatchFinder::MatchCallback { public: explicit FunctionDeclarationMatch(ClangMoveTool *MoveTool) @@ -151,9 +159,22 @@ const clang::NamedDecl *D = FD; if (const auto *FTD = FD->getDescribedFunctionTemplate()) D = FTD; - MoveTool->getMovedDecls().push_back(D); - MoveTool->getUnremovedDeclsInOldHeader().erase(D); - MoveTool->addRemovedDecl(D); + MoveDeclFromOldFileToNewFile(MoveTool, D); + } + +private: + ClangMoveTool *MoveTool; +}; + +class EnumDeclarationMatch : public MatchFinder::MatchCallback { +public: + explicit EnumDeclarationMatch(ClangMoveTool *MoveTool) + : MoveTool(MoveTool) {} + + void run(const MatchFinder::MatchResult &Result) override { + const auto *ED = Result.Nodes.getNodeAs("enum"); + assert(ED); + MoveDeclFromOldFileToNewFile(MoveTool, ED); } private: @@ -196,9 +217,7 @@ void MatchClassStaticVariable(const clang::NamedDecl *VD, clang::SourceManager* SM) { - MoveTool->getMovedDecls().push_back(VD); - MoveTool->addRemovedDecl(VD); - MoveTool->getUnremovedDeclsInOldHeader().erase(VD); + MoveDeclFromOldFileToNewFile(MoveTool, VD); } void MatchClassDeclaration(const clang::CXXRecordDecl *CD, @@ -449,6 +468,8 @@ auto InOldFiles = anyOf(InOldHeader, InOldCC); auto ForwardDecls = cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition()))); + auto TopLevelDecl = + hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl())); //============================================================================ // Matchers for old header @@ -544,11 +565,9 @@ // Create a MatchCallback for class declarations. MatchCallbacks.push_back(llvm::make_unique(this)); // Match moved class declarations. - auto MovedClass = - cxxRecordDecl( - InOldFiles, *HasAnySymbolNames, isDefinition(), - hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl()))) - .bind("moved_class"); + auto MovedClass = cxxRecordDecl(InOldFiles, *HasAnySymbolNames, + isDefinition(), TopLevelDecl) + .bind("moved_class"); Finder->addMatcher(MovedClass, MatchCallbacks.back().get()); // Match moved class methods (static methods included) which are defined // outside moved class declaration. @@ -564,11 +583,17 @@ MatchCallbacks.back().get()); MatchCallbacks.push_back(llvm::make_unique(this)); - Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, - anyOf(hasDeclContext(namespaceDecl()), - hasDeclContext(translationUnitDecl()))) + Finder->addMatcher(functionDecl(InOldFiles, *HasAnySymbolNames, TopLevelDecl) .bind("function"), MatchCallbacks.back().get()); + + // Match enum definition in old.h. Enum helpers (which are definied in old.cc) + // will not be moved for now no matter whether they are used or not. + MatchCallbacks.push_back(llvm::make_unique(this)); + Finder->addMatcher( + enumDecl(InOldHeader, *HasAnySymbolNames, isDefinition(), TopLevelDecl) + .bind("enum"), + MatchCallbacks.back().get()); } void ClangMoveTool::run(const ast_matchers::MatchFinder::MatchResult &Result) { @@ -802,6 +827,7 @@ case Decl::Kind::FunctionTemplate: case Decl::Kind::ClassTemplate: case Decl::Kind::CXXRecord: + case Decl::Kind::Enum: return true; default: return false; Index: clang-tools-extra/trunk/test/clang-move/Inputs/enum.h =================================================================== --- clang-tools-extra/trunk/test/clang-move/Inputs/enum.h +++ clang-tools-extra/trunk/test/clang-move/Inputs/enum.h @@ -0,0 +1,9 @@ +namespace a { +enum E1 { Green, Red }; + +enum class E2 { Yellow }; + +class C { + enum E3 { Blue }; +}; +} // namespace a Index: clang-tools-extra/trunk/test/clang-move/move-enum-decl.cpp =================================================================== --- clang-tools-extra/trunk/test/clang-move/move-enum-decl.cpp +++ clang-tools-extra/trunk/test/clang-move/move-enum-decl.cpp @@ -0,0 +1,44 @@ +// RUN: mkdir -p %T/move-enum +// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h +// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp +// RUN: cd %T/move-enum +// +// ----------------------------------------------------------------------------- +// Test moving enum declarations. +// ----------------------------------------------------------------------------- +// RUN: clang-move -names="a::E1" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11 +// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE1 %s +// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE1 %s +// +// CHECK-NEW-TEST-H-CASE1: namespace a { +// CHECK-NEW-TEST-H-CASE1-NEXT: enum E1 { Green, Red }; +// CHECK-NEW-TEST-H-CASE1-NEXT: } + +// CHECK-OLD-TEST-H-CASE1-NOT: enum E1 { Green, Red }; + + +// ----------------------------------------------------------------------------- +// Test moving scoped enum declarations. +// ----------------------------------------------------------------------------- +// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h +// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp +// RUN: clang-move -names="a::E2" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11 +// RUN: FileCheck -input-file=%T/move-enum/new_test.h -check-prefix=CHECK-NEW-TEST-H-CASE2 %s +// RUN: FileCheck -input-file=%T/move-enum/enum.h -check-prefix=CHECK-OLD-TEST-H-CASE2 %s + +// CHECK-NEW-TEST-H-CASE2: namespace a { +// CHECK-NEW-TEST-H-CASE2-NEXT: enum class E2 { Yellow }; +// CHECK-NEW-TEST-H-CASE2-NEXT: } + +// CHECK-OLD-TEST-H-CASE2-NOT: enum class E2 { Yellow }; + + +// ----------------------------------------------------------------------------- +// Test not moving class-insided enum declarations. +// ----------------------------------------------------------------------------- +// RUN: cp %S/Inputs/enum.h %T/move-enum/enum.h +// RUN: echo '#include "enum.h"' > %T/move-enum/enum.cpp +// RUN: clang-move -names="a::C::E3" -new_cc=%T/move-enum/new_test.cpp -new_header=%T/move-enum/new_test.h -old_cc=%T/move-enum/enum.cpp -old_header=%T/move-enum/enum.h %T/move-enum/enum.cpp -- -std=c++11 +// RUN: FileCheck -input-file=%T/move-enum/new_test.h -allow-empty -check-prefix=CHECK-EMPTY %s + +// CHECK-EMPTY: {{^}}{{$}} Index: clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp =================================================================== --- clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp +++ clang-tools-extra/trunk/unittests/clang-move/ClangMoveTests.cpp @@ -370,7 +370,6 @@ std::vector TestHeaders = { "typedef int Int;\nclass A {\npublic:\n int f();\n};\n", "using Int = int;\nclass A {\npublic:\n int f();\n};\n", - "enum Color { RED };\nclass A {\npublic:\n int f();\n};\n", }; move::MoveDefinitionSpec Spec; Spec.Names.push_back("A");