From fb68ca182573813b7aa1cfeef522636f84b9c7c6 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 31 Jan 2018 12:12:29 +0000 Subject: [clang-move] Clever on handling header file which includes itself. Summary: Previously, we assume only old.cc includes "old.h", which would introduce incorrect fixes for the cases where old.h also includes `#include "old.h"` Although it should not be occurred in real projects, clang-move should handle this. Old.h: ``` class Foo {}; ``` after moving to a new old.h: ``` class Foo {}; ``` Reviewers: ioeric Reviewed By: ioeric Subscribers: cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D42639 llvm-svn: 323865 --- clang-tools-extra/clang-move/ClangMove.cpp | 39 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) (limited to 'clang-tools-extra/clang-move/ClangMove.cpp') diff --git a/clang-tools-extra/clang-move/ClangMove.cpp b/clang-tools-extra/clang-move/ClangMove.cpp index 3a44aa3e9da..8397c956e5b 100644 --- a/clang-tools-extra/clang-move/ClangMove.cpp +++ b/clang-tools-extra/clang-move/ClangMove.cpp @@ -694,22 +694,28 @@ void ClangMoveTool::addIncludes(llvm::StringRef IncludeHeader, bool IsAngled, const SourceManager &SM) { SmallVector HeaderWithSearchPath; llvm::sys::path::append(HeaderWithSearchPath, SearchPath, IncludeHeader); - std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader); - if (AbsoluteOldHeader == + std::string AbsoluteIncludeHeader = MakeAbsolutePath(SM, llvm::StringRef(HeaderWithSearchPath.data(), - HeaderWithSearchPath.size()))) { - OldHeaderIncludeRange = IncludeFilenameRange; - return; - } - + HeaderWithSearchPath.size())); std::string IncludeLine = IsAngled ? ("#include <" + IncludeHeader + ">\n").str() : ("#include \"" + IncludeHeader + "\"\n").str(); + std::string AbsoluteOldHeader = makeAbsolutePath(Context->Spec.OldHeader); std::string AbsoluteCurrentFile = MakeAbsolutePath(SM, FileName); if (AbsoluteOldHeader == AbsoluteCurrentFile) { + // Find old.h includes "old.h". + if (AbsoluteOldHeader == AbsoluteIncludeHeader) { + OldHeaderIncludeRangeInHeader = IncludeFilenameRange; + return; + } HeaderIncludes.push_back(IncludeLine); } else if (makeAbsolutePath(Context->Spec.OldCC) == AbsoluteCurrentFile) { + // Find old.cc includes "old.h". + if (AbsoluteOldHeader == AbsoluteIncludeHeader) { + OldHeaderIncludeRangeInCC = IncludeFilenameRange; + return; + } CCIncludes.push_back(IncludeLine); } } @@ -857,13 +863,18 @@ void ClangMoveTool::moveAll(SourceManager &SM, StringRef OldFile, if (!NewFile.empty()) { auto AllCode = clang::tooling::Replacements( 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 (Context->Spec.NewCC == NewFile && OldHeaderIncludeRange.isValid()) { - AllCode = AllCode.merge( - clang::tooling::Replacements(clang::tooling::Replacement( - SM, OldHeaderIncludeRange, '"' + Context->Spec.NewHeader + '"'))); - } + auto ReplaceOldInclude = [&](clang::CharSourceRange OldHeaderIncludeRange) { + AllCode = AllCode.merge(clang::tooling::Replacements( + clang::tooling::Replacement(SM, OldHeaderIncludeRange, + '"' + Context->Spec.NewHeader + '"'))); + }; + // Fix the case where old.h/old.cc includes "old.h", we replace the + // `#include "old.h"` with `#include "new.h"`. + if (Context->Spec.NewCC == NewFile && OldHeaderIncludeRangeInCC.isValid()) + ReplaceOldInclude(OldHeaderIncludeRangeInCC); + else if (Context->Spec.NewHeader == NewFile && + OldHeaderIncludeRangeInHeader.isValid()) + ReplaceOldInclude(OldHeaderIncludeRangeInHeader); Context->FileToReplacements[NewFile] = std::move(AllCode); } } -- cgit v1.2.3