From 32a552f6b02d9174aa30bf8c90a9baa5b5a5867c Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Tue, 3 Jan 2017 14:22:25 +0000 Subject: [PATCH] [clang-move] Support moving enum declarations. Reviewers: ioeric Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D28228 llvm-svn: 290891 --- clang-tools-extra/clang-move/ClangMove.cpp | 54 ++++++++++++++++------ clang-tools-extra/test/clang-move/Inputs/enum.h | 9 ++++ .../test/clang-move/move-enum-decl.cpp | 44 ++++++++++++++++++ .../unittests/clang-move/ClangMoveTests.cpp | 1 - 4 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 clang-tools-extra/test/clang-move/Inputs/enum.h create mode 100644 clang-tools-extra/test/clang-move/move-enum-decl.cpp diff --git a/clang-tools-extra/clang-move/ClangMove.cpp b/clang-tools-extra/clang-move/ClangMove.cpp index 7817680..06a76f2 100644 --- a/clang-tools-extra/clang-move/ClangMove.cpp +++ b/clang-tools-extra/clang-move/ClangMove.cpp @@ -140,6 +140,14 @@ private: 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 @@ public: 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 @@ private: 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 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { 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 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { // 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 @@ void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) { 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 @@ void ClangMoveTool::onEndOfTranslationUnit() { case Decl::Kind::FunctionTemplate: case Decl::Kind::ClassTemplate: case Decl::Kind::CXXRecord: + case Decl::Kind::Enum: return true; default: return false; diff --git a/clang-tools-extra/test/clang-move/Inputs/enum.h b/clang-tools-extra/test/clang-move/Inputs/enum.h new file mode 100644 index 0000000..9ec3926 --- /dev/null +++ b/clang-tools-extra/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 diff --git a/clang-tools-extra/test/clang-move/move-enum-decl.cpp b/clang-tools-extra/test/clang-move/move-enum-decl.cpp new file mode 100644 index 0000000..42f6f99 --- /dev/null +++ b/clang-tools-extra/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: {{^}}{{$}} diff --git a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp index 98f0842..2c0f1ac 100644 --- a/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp +++ b/clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp @@ -370,7 +370,6 @@ TEST(ClangMove, IgnoreUnsupportedKindsAndMoveAll) { 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"); -- 2.7.4