Index: clang-move/ClangMove.cpp =================================================================== --- clang-move/ClangMove.cpp +++ clang-move/ClangMove.cpp @@ -160,6 +160,23 @@ 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); + MoveTool->getMovedDecls().push_back(ED); + MoveTool->getUnremovedDeclsInOldHeader().erase(ED); + MoveTool->addRemovedDecl(ED); + } + +private: + ClangMoveTool *MoveTool; +}; + class ClassDeclarationMatch : public MatchFinder::MatchCallback { public: explicit ClassDeclarationMatch(ClangMoveTool *MoveTool) @@ -449,6 +466,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 +563,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 +581,16 @@ 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 declarations. + 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 +824,7 @@ case Decl::Kind::FunctionTemplate: case Decl::Kind::ClassTemplate: case Decl::Kind::CXXRecord: + case Decl::Kind::Enum: return true; default: return false; Index: test/clang-move/Inputs/enum.h =================================================================== --- /dev/null +++ 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: test/clang-move/move-enum-decl.cpp =================================================================== --- /dev/null +++ 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: unittests/clang-move/ClangMoveTests.cpp =================================================================== --- unittests/clang-move/ClangMoveTests.cpp +++ 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");