[clang-move] Enable dump all declarations in old header.
Summary:
* Add -dump_dels option to dump all declarations from old header. It
will allow clang-move used as a frontend to get declarations from
header. Further more, this will make debugging stuff easier. Currently only
class/function types are supported.
* Refactoring code a little bit by creating a ClangMoveContext which
holds all options for ClangMoveTool, which can simplify the code in
some degree.
Reviewers: ioeric
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D27059
llvm-svn: 287863
diff --git a/clang-tools-extra/clang-move/ClangMove.cpp b/clang-tools-extra/clang-move/ClangMove.cpp
index d4d0af8..bd8bbe3 100644
--- a/clang-tools-extra/clang-move/ClangMove.cpp
+++ b/clang-tools-extra/clang-move/ClangMove.cpp
@@ -401,15 +401,11 @@
return MatchFinder.newASTConsumer();
}
-ClangMoveTool::ClangMoveTool(
- const MoveDefinitionSpec &MoveSpec,
- std::map<std::string, tooling::Replacements> &FileToReplacements,
- llvm::StringRef OriginalRunningDirectory, llvm::StringRef FallbackStyle)
- : Spec(MoveSpec), FileToReplacements(FileToReplacements),
- OriginalRunningDirectory(OriginalRunningDirectory),
- FallbackStyle(FallbackStyle) {
- if (!Spec.NewHeader.empty())
- CCIncludes.push_back("#include \"" + Spec.NewHeader + "\"\n");
+ClangMoveTool::ClangMoveTool(ClangMoveContext *const Context,
+ DeclarationReporter *const Reporter)
+ : Context(Context), Reporter(Reporter) {
+ if (!Context->Spec.NewHeader.empty())
+ CCIncludes.push_back("#include \"" + Context->Spec.NewHeader + "\"\n");
}
void ClangMoveTool::addRemovedDecl(const MovedDecl &Decl) {
@@ -421,24 +417,10 @@
}
void ClangMoveTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
- Optional<ast_matchers::internal::Matcher<NamedDecl>> 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 (!HasAnySymbolNames) {
- llvm::errs() << "No symbols being moved.\n";
- return;
- }
-
- auto InOldHeader = isExpansionInFile(makeAbsolutePath(Spec.OldHeader));
- auto InOldCC = isExpansionInFile(makeAbsolutePath(Spec.OldCC));
+ auto InOldHeader =
+ isExpansionInFile(makeAbsolutePath(Context->Spec.OldHeader));
+ auto InOldCC = isExpansionInFile(makeAbsolutePath(Context->Spec.OldCC));
auto InOldFiles = anyOf(InOldHeader, InOldCC);
- auto InMovedClass =
- hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));
-
auto ForwardDecls =
cxxRecordDecl(unless(anyOf(isImplicit(), isDefinition())));
@@ -448,15 +430,21 @@
// Match all top-level named declarations (e.g. function, variable, enum) in
// old header, exclude forward class declarations and namespace declarations.
//
- // The old header which contains only one declaration being moved and forward
- // declarations is considered to be moved totally.
+ // We consider declarations inside a class belongs to the class. So these
+ // declarations will be ignored.
auto AllDeclsInHeader = namedDecl(
unless(ForwardDecls), unless(namespaceDecl()),
- unless(usingDirectiveDecl()), // using namespace decl.
+ unless(usingDirectiveDecl()), // using namespace decl.
unless(classTemplateDecl(has(ForwardDecls))), // template forward decl.
InOldHeader,
- hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
+ hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
+ hasDeclContext(decl(anyOf(namespaceDecl(), translationUnitDecl()))));
Finder->addMatcher(AllDeclsInHeader.bind("decls_in_header"), this);
+
+ // Don't register other matchers when dumping all declarations in header.
+ if (Context->DumpDeclarations)
+ return;
+
// Match forward declarations in old header.
Finder->addMatcher(namedDecl(ForwardDecls, InOldHeader).bind("fwd_decl"),
this);
@@ -484,6 +472,20 @@
// Match static functions/variable definitions which are defined in named
// namespaces.
+ Optional<ast_matchers::internal::Matcher<NamedDecl>> HasAnySymbolNames;
+ for (StringRef SymbolName : Context->Spec.Names) {
+ llvm::StringRef GlobalSymbolName = SymbolName.trim().ltrim(':');
+ const auto HasName = hasName(("::" + GlobalSymbolName).str());
+ HasAnySymbolNames =
+ HasAnySymbolNames ? anyOf(*HasAnySymbolNames, HasName) : HasName;
+ }
+
+ if (!HasAnySymbolNames) {
+ llvm::errs() << "No symbols being moved.\n";
+ return;
+ }
+ auto InMovedClass =
+ hasOutermostEnclosingClass(cxxRecordDecl(*HasAnySymbolNames));
auto IsOldCCStaticDefinition =
allOf(isDefinition(), unless(InMovedClass), InOldCCNamedOrGlobalNamespace,
isStaticStorageClass());
@@ -531,7 +533,7 @@
UnremovedDeclsInOldHeader.insert(D);
} else if (const auto *FWD =
Result.Nodes.getNodeAs<clang::CXXRecordDecl>("fwd_decl")) {
- // Skip all forwad declarations which appear after moved class declaration.
+ // Skip all forward declarations which appear after moved class declaration.
if (RemovedDecls.empty()) {
if (const auto *DCT = FWD->getDescribedClassTemplate())
MovedDecls.emplace_back(DCT, &Result.Context->getSourceManager());
@@ -551,7 +553,7 @@
}
std::string ClangMoveTool::makeAbsolutePath(StringRef Path) {
- return MakeAbsolutePath(OriginalRunningDirectory, Path);
+ return MakeAbsolutePath(Context->OriginalRunningDirectory, Path);
}
void ClangMoveTool::addIncludes(llvm::StringRef IncludeHeader, bool IsAngled,
@@ -561,7 +563,7 @@
const SourceManager &SM) {
SmallVector<char, 128> HeaderWithSearchPath;
llvm::sys::path::append(HeaderWithSearchPath, SearchPath, IncludeHeader);
- std::string AbsoluteOldHeader = makeAbsolutePath(Spec.OldHeader);
+ std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader);
// FIXME: Add old.h to the new.cc/h when the new target has dependencies on
// old.h/c. For instance, when moved class uses another class defined in
// old.h, the old.h should be added in new.h.
@@ -579,7 +581,7 @@
std::string AbsoluteCurrentFile = MakeAbsolutePath(SM, FileName);
if (AbsoluteOldHeader == AbsoluteCurrentFile) {
HeaderIncludes.push_back(IncludeLine);
- } else if (makeAbsolutePath(Spec.OldCC) == AbsoluteCurrentFile) {
+ } else if (makeAbsolutePath(Context->Spec.OldCC) == AbsoluteCurrentFile) {
CCIncludes.push_back(IncludeLine);
}
}
@@ -594,20 +596,22 @@
clang::CharSourceRange::getCharRange(Range.getBegin(), Range.getEnd()),
"");
std::string FilePath = RemoveReplacement.getFilePath().str();
- auto Err = FileToReplacements[FilePath].add(RemoveReplacement);
+ auto Err = Context->FileToReplacements[FilePath].add(RemoveReplacement);
if (Err)
llvm::errs() << llvm::toString(std::move(Err)) << "\n";
}
const SourceManager* SM = RemovedDecls[0].SM;
// Post process of cleanup around all the replacements.
- for (auto& FileAndReplacements: FileToReplacements) {
+ for (auto &FileAndReplacements : Context->FileToReplacements) {
StringRef FilePath = FileAndReplacements.first;
// Add #include of new header to old header.
- if (Spec.OldDependOnNew &&
- MakeAbsolutePath(*SM, FilePath) == makeAbsolutePath(Spec.OldHeader)) {
+ if (Context->Spec.OldDependOnNew &&
+ MakeAbsolutePath(*SM, FilePath) ==
+ makeAbsolutePath(Context->Spec.OldHeader)) {
// FIXME: Minimize the include path like include-fixer.
- std::string IncludeNewH = "#include \"" + Spec.NewHeader + "\"\n";
+ std::string IncludeNewH =
+ "#include \"" + Context->Spec.NewHeader + "\"\n";
// This replacment for inserting header will be cleaned up at the end.
auto Err = FileAndReplacements.second.add(
tooling::Replacement(FilePath, UINT_MAX, 0, IncludeNewH));
@@ -620,15 +624,15 @@
if (SI == FilePathToFileID.end()) continue;
llvm::StringRef Code = SM->getBufferData(SI->second);
format::FormatStyle Style =
- format::getStyle("file", FilePath, FallbackStyle);
+ format::getStyle("file", FilePath, Context->FallbackStyle);
auto CleanReplacements = format::cleanupAroundReplacements(
- Code, FileToReplacements[FilePath], Style);
+ Code, Context->FileToReplacements[FilePath], Style);
if (!CleanReplacements) {
llvm::errs() << llvm::toString(CleanReplacements.takeError()) << "\n";
continue;
}
- FileToReplacements[FilePath] = *CleanReplacements;
+ Context->FileToReplacements[FilePath] = *CleanReplacements;
}
}
@@ -636,23 +640,27 @@
std::vector<MovedDecl> NewHeaderDecls;
std::vector<MovedDecl> NewCCDecls;
for (const auto &MovedDecl : MovedDecls) {
- if (isInHeaderFile(*MovedDecl.SM, MovedDecl.Decl, OriginalRunningDirectory,
- Spec.OldHeader))
+ if (isInHeaderFile(*MovedDecl.SM, MovedDecl.Decl,
+ Context->OriginalRunningDirectory,
+ Context->Spec.OldHeader))
NewHeaderDecls.push_back(MovedDecl);
else
NewCCDecls.push_back(MovedDecl);
}
- if (!Spec.NewHeader.empty()) {
+ if (!Context->Spec.NewHeader.empty()) {
std::string OldHeaderInclude =
- Spec.NewDependOnOld ? "#include \"" + Spec.OldHeader + "\"\n" : "";
- FileToReplacements[Spec.NewHeader] = createInsertedReplacements(
- HeaderIncludes, NewHeaderDecls, Spec.NewHeader, /*IsHeader=*/true,
- OldHeaderInclude);
+ Context->Spec.NewDependOnOld
+ ? "#include \"" + Context->Spec.OldHeader + "\"\n"
+ : "";
+ Context->FileToReplacements[Context->Spec.NewHeader] =
+ createInsertedReplacements(HeaderIncludes, NewHeaderDecls,
+ Context->Spec.NewHeader, /*IsHeader=*/true,
+ OldHeaderInclude);
}
- if (!Spec.NewCC.empty())
- FileToReplacements[Spec.NewCC] =
- createInsertedReplacements(CCIncludes, NewCCDecls, Spec.NewCC);
+ if (!Context->Spec.NewCC.empty())
+ Context->FileToReplacements[Context->Spec.NewCC] =
+ createInsertedReplacements(CCIncludes, NewCCDecls, Context->Spec.NewCC);
}
// Move all contents from OldFile to NewFile.
@@ -669,7 +677,8 @@
clang::tooling::Replacement RemoveAll (
SM, clang::CharSourceRange::getCharRange(Begin, End), "");
std::string FilePath = RemoveAll.getFilePath().str();
- FileToReplacements[FilePath] = clang::tooling::Replacements(RemoveAll);
+ Context->FileToReplacements[FilePath] =
+ clang::tooling::Replacements(RemoveAll);
StringRef Code = SM.getBufferData(ID);
if (!NewFile.empty()) {
@@ -677,22 +686,36 @@
clang::tooling::Replacement(NewFile, 0, 0, Code));
// If we are moving from old.cc, an extra step is required: excluding
// the #include of "old.h", instead, we replace it with #include of "new.h".
- if (Spec.NewCC == NewFile && OldHeaderIncludeRange.isValid()) {
+ if (Context->Spec.NewCC == NewFile && OldHeaderIncludeRange.isValid()) {
AllCode = AllCode.merge(
clang::tooling::Replacements(clang::tooling::Replacement(
- SM, OldHeaderIncludeRange, '"' + Spec.NewHeader + '"')));
+ SM, OldHeaderIncludeRange, '"' + Context->Spec.NewHeader + '"')));
}
- FileToReplacements[NewFile] = std::move(AllCode);
+ Context->FileToReplacements[NewFile] = std::move(AllCode);
}
}
void ClangMoveTool::onEndOfTranslationUnit() {
+ if (Context->DumpDeclarations) {
+ assert(Reporter);
+ for (const auto *Decl : UnremovedDeclsInOldHeader) {
+ auto Kind = Decl->getKind();
+ const std::string QualifiedName = Decl->getQualifiedNameAsString();
+ if (Kind == Decl::Kind::Function || Kind == Decl::Kind::FunctionTemplate)
+ Reporter->reportDeclaration(QualifiedName, "Function");
+ else if (Kind == Decl::Kind::ClassTemplate ||
+ Kind == Decl::Kind::CXXRecord)
+ Reporter->reportDeclaration(QualifiedName, "Class");
+ }
+ return;
+ }
+
if (RemovedDecls.empty())
return;
- if (UnremovedDeclsInOldHeader.empty() && !Spec.OldHeader.empty()) {
+ if (UnremovedDeclsInOldHeader.empty() && !Context->Spec.OldHeader.empty()) {
auto &SM = *RemovedDecls[0].SM;
- moveAll(SM, Spec.OldHeader, Spec.NewHeader);
- moveAll(SM, Spec.OldCC, Spec.NewCC);
+ moveAll(SM, Context->Spec.OldHeader, Context->Spec.NewHeader);
+ moveAll(SM, Context->Spec.OldCC, Context->Spec.NewCC);
return;
}
removeClassDefinitionInOldFiles();