diff options
author | Edwin Vane <edwin.vane@intel.com> | 2013-09-03 13:16:02 +0000 |
---|---|---|
committer | Edwin Vane <edwin.vane@intel.com> | 2013-09-03 13:16:02 +0000 |
commit | 147984a8adf15183de3f3a25f74b7b3620e2a1a6 (patch) | |
tree | bf419f9698f16461fb7d4160a9a6175c5d5d6383 /clang-tools-extra/cpp11-migrate | |
parent | 249c7fb10eb837cc78a6e6d26aef9ad802111440 (diff) | |
download | bcm5719-llvm-147984a8adf15183de3f3a25f74b7b3620e2a1a6.tar.gz bcm5719-llvm-147984a8adf15183de3f3a25f74b7b3620e2a1a6.zip |
cpp11-migrate: Refactor for driver model of operation
Re-commit of r189691 and r189689 now with a proper autoconf fix.
Massive simplification of how replacements and file overrides are
handled by the migrator:
* Sources and headers are all treated the same.
* All replacements for a given translation unit are stored in the same
TranslationUnitReplacements structure.
* Change tracking is updated only from main file; no need for
propagating "is tracking" flag around.
* Transform base class no longer responsible for applying replacements.
They are simply stored and main() looks after deduplication and
application.
* Renamed -yaml-only to -serialize-replacements. Same restrictions apply:
Can only request one transform. New restriction: formatting cannot also
be turned on since it's basically a transform.
* If -serialize-replacements is requested, changes to files will not be
applied on disk.
* Changed behaviour of function generating names for serialized
replacements: Only the main source file goes into the name of the file
since a file may contain changes for multiple different files.
* Updated HeaderReplacements LIT test for new serialization behaviour.
* Replaced old test that ensures replacements are not serialized if
-serialize-replacements is not provided. New version ensures changes
are made directly to all files in the translation unit.
* Updated unit tests.
* Due to major simplification of structures in FileOverrides.h, the
FileOverridesTest is quite a bit simpler now.
llvm-svn: 189798
Diffstat (limited to 'clang-tools-extra/cpp11-migrate')
37 files changed, 475 insertions, 598 deletions
diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp index db38fa64b56..9a13c044e5d 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp @@ -29,13 +29,13 @@ static cl::opt<bool> DetectMacros( cl::desc("Detect and use macros that expand to the 'override' keyword."), cl::cat(TransformsOptionsCategory)); -int AddOverrideTransform::apply(FileOverrides &InputStates, +int AddOverrideTransform::apply(const FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) { ClangTool AddOverrideTool(Database, SourcePaths); unsigned AcceptedChanges = 0; MatchFinder Finder; - AddOverrideFixer Fixer(getReplacements(), AcceptedChanges, DetectMacros, + AddOverrideFixer Fixer(AcceptedChanges, DetectMacros, /*Owner=*/ *this); Finder.addMatcher(makeCandidateForOverrideAttrMatcher(), &Fixer); diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.h b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.h index 81ceaed859c..8c39775e48d 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.h +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.h @@ -31,7 +31,7 @@ public: : Transform("AddOverride", Options) {} /// \see Transform::run(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp index 47c070e55ae..134318ed386 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp @@ -95,6 +95,7 @@ void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) { if (!MacroName.empty()) ReplacementText = (" " + MacroName).str(); } - Replace.insert(tooling::Replacement(SM, StartLoc, 0, ReplacementText)); + Owner.addReplacementForCurrentTU( + tooling::Replacement(SM, StartLoc, 0, ReplacementText)); ++AcceptedChanges; } diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h index 54877d538a4..afcebeffd4b 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h @@ -25,11 +25,10 @@ class Transform; /// class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - AddOverrideFixer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, bool DetectMacros, - const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), - DetectMacros(DetectMacros), Owner(Owner) {} + AddOverrideFixer(unsigned &AcceptedChanges, bool DetectMacros, + Transform &Owner) + : AcceptedChanges(AcceptedChanges), DetectMacros(DetectMacros), + Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result); @@ -38,10 +37,9 @@ public: private: clang::Preprocessor *PP; - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; bool DetectMacros; - const Transform &Owner; + Transform &Owner; }; #endif // CPP11_MIGRATE_ADD_OVERRIDE_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/CMakeLists.txt b/clang-tools-extra/cpp11-migrate/CMakeLists.txt index 13ec7ac2e73..41bb68ef82d 100644 --- a/clang-tools-extra/cpp11-migrate/CMakeLists.txt +++ b/clang-tools-extra/cpp11-migrate/CMakeLists.txt @@ -1,4 +1,10 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +get_filename_component(ClangReplaceLocation + "${CMAKE_CURRENT_SOURCE_DIR}/../clang-replace/include" ABSOLUTE) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${ClangReplaceLocation} + ) add_subdirectory(tool) add_subdirectory(Core) diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp index d8d4b3f27e1..7ab7e91c30c 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp @@ -29,157 +29,14 @@ using namespace clang; using namespace clang::tooling; -void HeaderOverride::recordReplacements( - const clang::tooling::Replacements &Replaces) { - Replacements.Replacements.resize(Replaces.size()); - std::copy(Replaces.begin(), Replaces.end(), - Replacements.Replacements.begin()); -} - -SourceOverrides::SourceOverrides(llvm::StringRef MainFileName, - bool TrackChanges) - : MainFileName(MainFileName), TrackChanges(TrackChanges) {} - -void -SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces) { - llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( - new DiagnosticOptions()); - DiagnosticsEngine Diagnostics( - llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), - DiagOpts.getPtr()); - FileManager Files((FileSystemOptions())); - SourceManager SM(Diagnostics, Files); - applyReplacements(Replaces, SM); -} - -void SourceOverrides::applyReplacements(clang::tooling::Replacements &Replaces, - clang::SourceManager &SM) { - applyOverrides(SM); - - Rewriter Rewrites(SM, LangOptions()); - - // FIXME: applyAllReplacements will indicate if it couldn't apply all - // replacements. Handle that case. - bool Success = tooling::applyAllReplacements(Replaces, Rewrites); - - if (!Success) - llvm::errs() << "error: failed to apply some replacements."; - - std::string ResultBuf; - - for (Rewriter::buffer_iterator I = Rewrites.buffer_begin(), - E = Rewrites.buffer_end(); - I != E; ++I) { - const FileEntry *Entry = - Rewrites.getSourceMgr().getFileEntryForID(I->first); - assert(Entry != NULL && "unexpected null FileEntry"); - assert(Entry->getName() != NULL && - "unexpected null return from FileEntry::getName()"); - llvm::StringRef FileName = Entry->getName(); - - // Get a copy of the rewritten buffer from the Rewriter. - ResultBuf.clear(); - llvm::raw_string_ostream StringStream(ResultBuf); - I->second.write(StringStream); - StringStream.flush(); - - if (MainFileName == FileName) { - MainFileOverride.swap(ResultBuf); - continue; - } - - // Header overrides are treated differently. Eventually, raw replacements - // will be stored as well for later output to disk. Applying replacements - // in memory will always be necessary as the source goes down the transform - // pipeline. - HeaderOverride &HeaderOv = Headers[FileName]; - // "Create" HeaderOverride if not already existing - if (HeaderOv.getHeaderPath().empty()) - HeaderOv = HeaderOverride(FileName, MainFileName); - - HeaderOv.swapContentOverride(ResultBuf); - } - - // Separate replacements to header files - Replacements MainFileReplaces; - ReplacementsMap HeadersReplaces; - for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end(); - I != E; ++I) { - llvm::StringRef ReplacementFileName = I->getFilePath(); - - if (ReplacementFileName == MainFileName) { - MainFileReplaces.insert(*I); - continue; - } - - HeadersReplaces[ReplacementFileName].insert(*I); - } - - // Record all replacements to headers. - for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(), - E = HeadersReplaces.end(); - I != E; ++I) { - HeaderOverride &HeaderOv = Headers[I->getKey()]; - HeaderOv.recordReplacements(I->getValue()); - } - - if (TrackChanges) - adjustChangedRanges(MainFileReplaces, HeadersReplaces); -} - -void -SourceOverrides::adjustChangedRanges(const Replacements &MainFileReplaces, - const ReplacementsMap &HeadersReplaces) { - // Adjust the changed ranges for each individual file - MainFileChanges.adjustChangedRanges(MainFileReplaces); - for (ReplacementsMap::const_iterator I = HeadersReplaces.begin(), - E = HeadersReplaces.end(); - I != E; ++I) { - Headers[I->getKey()].adjustChangedRanges(I->getValue()); - } -} - -void SourceOverrides::applyOverrides(SourceManager &SM) const { - FileManager &FM = SM.getFileManager(); - - if (isSourceOverriden()) - SM.overrideFileContents(FM.getFile(MainFileName), - llvm::MemoryBuffer::getMemBuffer(MainFileOverride)); - - for (HeaderOverrides::const_iterator I = Headers.begin(), E = Headers.end(); - I != E; ++I) { - assert(!I->second.getContentOverride().empty() && - "Header override should not be empty!"); - SM.overrideFileContents( - FM.getFile(I->second.getHeaderPath()), - llvm::MemoryBuffer::getMemBuffer(I->second.getContentOverride())); - } -} - -bool generateReplacementsFileName(llvm::StringRef SourceFile, - llvm::StringRef HeaderFile, - llvm::SmallVectorImpl<char> &Result, - llvm::SmallVectorImpl<char> &Error) { +bool generateReplacementsFileName(const llvm::StringRef MainSourceFile, + llvm::SmallVectorImpl<char> &Result, + llvm::SmallVectorImpl<char> &Error) { using namespace llvm::sys; - std::string UniqueHeaderNameModel; - - // Get the filename portion of the path. - llvm::StringRef SourceFileRef(path::filename(SourceFile)); - llvm::StringRef HeaderFileRef(path::filename(HeaderFile)); - - // Get the actual path for the header file. - llvm::SmallString<128> HeaderPath(HeaderFile); - path::remove_filename(HeaderPath); - - // Build the model of the filename. - llvm::raw_string_ostream UniqueHeaderNameStream(UniqueHeaderNameModel); - UniqueHeaderNameStream << SourceFileRef << "_" << HeaderFileRef - << "_%%_%%_%%_%%_%%_%%" << ".yaml"; - path::append(HeaderPath, UniqueHeaderNameStream.str()); Error.clear(); - if (llvm::error_code EC = - fs::createUniqueFile(HeaderPath.c_str(), Result)) { + if (llvm::error_code EC = fs::createUniqueFile( + MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) { Error.append(EC.message().begin(), EC.message().end()); return false; } @@ -187,20 +44,6 @@ bool generateReplacementsFileName(llvm::StringRef SourceFile, return true; } -FileOverrides::~FileOverrides() { - for (SourceOverridesMap::iterator I = Overrides.begin(), E = Overrides.end(); - I != E; ++I) - delete I->getValue(); -} - -SourceOverrides &FileOverrides::getOrCreate(llvm::StringRef Filename) { - SourceOverrides *&Override = Overrides[Filename]; - - if (Override == NULL) - Override = new SourceOverrides(Filename, TrackChanges); - return *Override; -} - namespace { /// \brief Comparator to be able to order tooling::Range based on their offset. @@ -247,10 +90,11 @@ struct RangeReplacedAdjuster { } // end anonymous namespace -void ChangedRanges::adjustChangedRanges(const tooling::Replacements &Replaces) { +void +ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) { // first adjust existing ranges in case they overlap with the replacements - for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; - ++I) { + for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end(); + I != E; ++I) { const tooling::Replacement &Replace = *I; std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(), @@ -265,8 +109,8 @@ void ChangedRanges::adjustChangedRanges(const tooling::Replacements &Replaces) { } // then generate the new ranges from the replacements - for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; - ++I) { + for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end(); + I != E; ++I) { const tooling::Replacement &R = *I; unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset()); unsigned Length = R.getReplacementText().size(); @@ -303,3 +147,52 @@ void ChangedRanges::coalesceRanges() { std::mem_fun_ref(&Range::contains)), Ranges.end()); } + +void FileOverrides::applyOverrides(clang::SourceManager &SM) const { + FileManager &FM = SM.getFileManager(); + + for (FileStateMap::const_iterator I = FileStates.begin(), + E = FileStates.end(); + I != E; ++I) { + SM.overrideFileContents(FM.getFile(I->getKey()), + llvm::MemoryBuffer::getMemBuffer(I->getValue())); + } +} + +void FileOverrides::adjustChangedRanges( + const clang::replace::FileToReplacementsMap &Replaces) { + + for (replace::FileToReplacementsMap::const_iterator I = Replaces.begin(), + E = Replaces.end(); I != E; ++I) { + ChangeTracking[I->getKey()].adjustChangedRanges(I->getValue()); + } +} + +void FileOverrides::updateState(const clang::Rewriter &Rewrites) { + for (Rewriter::const_buffer_iterator BufferI = Rewrites.buffer_begin(), + BufferE = Rewrites.buffer_end(); + BufferI != BufferE; ++BufferI) { + const char *FileName = + Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName(); + const RewriteBuffer &RewriteBuf = BufferI->second; + FileStates[FileName].assign(RewriteBuf.begin(), RewriteBuf.end()); + } +} + +bool FileOverrides::writeToDisk(DiagnosticsEngine &Diagnostics) const { + bool Errors = false; + for (FileStateMap::const_iterator I = FileStates.begin(), + E = FileStates.end(); + I != E; ++I) { + std::string ErrorInfo; + // The extra transform through std::string is to ensure null-termination + // of the filename stored as the key of the StringMap. + llvm::raw_fd_ostream FileStream(I->getKey().str().c_str(), ErrorInfo); + if (!ErrorInfo.empty()) { + llvm::errs() << "Failed to write new state for " << I->getKey() << ".\n"; + Errors = true; + } + FileStream << I->getValue(); + } + return !Errors; +} diff --git a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h index 3e81abc6d34..8cde7591303 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h @@ -16,7 +16,8 @@ #ifndef CPP11_MIGRATE_FILE_OVERRIDES_H #define CPP11_MIGRATE_FILE_OVERRIDES_H -#include "clang/Tooling/Refactoring.h" +#include "Core/Refactoring.h" +#include "clang-replace/Tooling/ApplyReplacements.h" #include "clang/Tooling/ReplacementsYaml.h" #include "llvm/ADT/StringMap.h" @@ -44,13 +45,13 @@ public: /// to remove replaced parts. /// /// Note that all replacements should come from the same file. - void adjustChangedRanges(const clang::tooling::Replacements &Replaces); + void adjustChangedRanges(const clang::tooling::ReplacementsVec &Replaces); /// \brief Iterators. - /// @{ + /// \{ const_iterator begin() const { return Ranges.begin(); } const_iterator end() const { return Ranges.end(); } - /// @} + /// \} private: void coalesceRanges(); @@ -58,178 +59,71 @@ private: RangeVec Ranges; }; -/// \brief Container for storing override information for a single headers. -class HeaderOverride { +/// \brief Maintains current state of transformed files and tracks source ranges +/// where changes have been made. +class FileOverrides { public: - /// \brief Constructors. - /// @{ - HeaderOverride() {} - HeaderOverride(llvm::StringRef HeaderPath, - llvm::StringRef MainSourceFile) : HeaderPath(HeaderPath) { - Replacements.MainSourceFile = MainSourceFile; - } - /// @} - - /// \brief Getter for HeaderPath. - llvm::StringRef getHeaderPath() const { - return HeaderPath; - } + /// \brief Maps file names to file contents. + typedef llvm::StringMap<std::string> FileStateMap; - /// \brief Accessor for ContentOverride. - /// @{ - llvm::StringRef getContentOverride() const { return ContentOverride; } - void setContentOverride(const llvm::StringRef S) { ContentOverride = S; } - /// @} + /// \brief Maps file names to change tracking info for a file. + typedef llvm::StringMap<ChangedRanges> ChangeMap; - /// \brief Getter for Changes. - const ChangedRanges &getChanges() const { return Changes; } - /// \brief Swaps the content of ContentOverride with \p S. - void swapContentOverride(std::string &S) { ContentOverride.swap(S); } - - /// \brief Getter for Replacements. - const clang::tooling::TranslationUnitReplacements &getReplacements() const { - return Replacements; - } + /// \brief Override file contents seen by \c SM for all files stored by this + /// object. + void applyOverrides(clang::SourceManager &SM) const; - /// \brief Stores the replacements made by a transform to the header this - /// object represents. - void recordReplacements(const clang::tooling::Replacements &Replaces); + /// \brief Update change tracking information based on replacements stored in + /// \c Replaces. + void + adjustChangedRanges(const clang::replace::FileToReplacementsMap &Replaces); - /// \brief Helper function to adjust the changed ranges. - void adjustChangedRanges(const clang::tooling::Replacements &Replaces) { - Changes.adjustChangedRanges(Replaces); + /// \brief Accessor for change tracking information. + const ChangeMap &getChangedRanges() const { + return ChangeTracking; } -private: - std::string ContentOverride; - ChangedRanges Changes; - std::string HeaderPath; - clang::tooling::TranslationUnitReplacements Replacements; -}; - -/// \brief Container mapping header file names to override information. -typedef llvm::StringMap<HeaderOverride> HeaderOverrides; - -/// \brief Container storing the file content overrides for a source file and -/// any headers included by the source file either directly or indirectly to -/// which changes have been made. -class SourceOverrides { -public: - SourceOverrides(llvm::StringRef MainFileName, bool TrackChanges); - - /// \brief Accessors. - /// @{ - llvm::StringRef getMainFileName() const { return MainFileName; } - llvm::StringRef getMainFileContent() const { return MainFileOverride; } - const ChangedRanges &getChangedRanges() const { return MainFileChanges; } - - /// \brief Is file change tracking enabled? + /// \brief Coalesce changes stored in \c Rewrites and replace file contents + /// overrides stored in this object. /// - /// Tracking file changes can be useful to reformat the code for example. - bool isTrackingFileChanges() const { return TrackChanges; } - /// @} + /// \param Rewrites Rewriter containing changes to files. + void updateState(const clang::Rewriter &Rewrites); - /// \brief Indicates if the source file has been overridden. - /// - /// It's possible for a source to remain unchanged while only headers are - /// changed. - bool isSourceOverriden() const { return !MainFileOverride.empty(); } + /// \brief Accessor for current file state. + const FileStateMap &getState() const { return FileStates; } - /// \brief Override the file contents by applying all the replacements. + /// \brief Write all file contents overrides to disk. /// - /// \param Replaces The replacements to apply. - /// \param SM A user provided SourceManager to be used when applying rewrites. - void applyReplacements(clang::tooling::Replacements &Replaces, - clang::SourceManager &SM); - void applyReplacements(clang::tooling::Replacements &Replaces); - - /// \brief Convenience function for applying this source's overrides to - /// the given SourceManager. - void applyOverrides(clang::SourceManager &SM) const; - - /// \brief Iterators. - /// @{ - HeaderOverrides::iterator headers_begin() { return Headers.begin(); } - HeaderOverrides::iterator headers_end() { return Headers.end(); } - HeaderOverrides::const_iterator headers_begin() const { - return Headers.begin(); - } - HeaderOverrides::const_iterator headers_end() const { return Headers.end(); } - /// @} - -private: - typedef llvm::StringMap<clang::tooling::Replacements> ReplacementsMap; - - /// \brief Flatten the Rewriter buffers of \p Rewrite and store results as - /// file content overrides. - void applyRewrites(clang::Rewriter &Rewrite); - - /// \brief Adjust the changed ranges to reflect the parts of the files that - /// have been replaced. - void adjustChangedRanges(const clang::tooling::Replacements &Replaces, - const ReplacementsMap &HeadersReplaces); - - const std::string MainFileName; - std::string MainFileOverride; - const bool TrackChanges; - ChangedRanges MainFileChanges; - HeaderOverrides Headers; -}; - -/// \brief Maps source file names to content override information. -class FileOverrides { -public: - typedef llvm::StringMap<SourceOverrides *> SourceOverridesMap; - typedef SourceOverridesMap::const_iterator const_iterator; - - /// \brief Construct the SourceOverrides manager. + /// \param Diagnostics DiagnosticsEngine for error output. /// - /// \param TrackChanges Wether or not the \c SourceOverrides should keep track - /// of changes. See \c SourceOverrides::isTrackingFileChanges(). - FileOverrides(bool TrackChanges) : TrackChanges(TrackChanges) {} - ~FileOverrides(); - - const_iterator find(llvm::StringRef Filename) const { - return Overrides.find(Filename); - } - - /// \brief Get the \c SourceOverrides for \p Filename, creating it if - /// necessary. - SourceOverrides &getOrCreate(llvm::StringRef Filename); - - /// \brief Iterators. - /// @{ - const_iterator begin() const { return Overrides.begin(); } - const_iterator end() const { return Overrides.end(); } - /// @} + /// \returns \li true if all files with overridden file contents were written + /// to disk successfully. + /// \li false if any failure occurred. + bool writeToDisk(clang::DiagnosticsEngine &Diagnostics) const; private: - FileOverrides(const FileOverrides &) LLVM_DELETED_FUNCTION; - FileOverrides &operator=(const FileOverrides &) LLVM_DELETED_FUNCTION; - - SourceOverridesMap Overrides; - const bool TrackChanges; + FileStateMap FileStates; + ChangeMap ChangeTracking; }; /// \brief Generate a unique filename to store the replacements. /// -/// Generates a unique filename in the same directory as the header file. The -/// filename is based on the following model: +/// Generates a unique filename in the same directory as \c MainSourceFile. The +/// filename is generated following this pattern: /// -/// source.cpp_header.h_%%_%%_%%_%%_%%_%%.yaml +/// MainSourceFile_%%_%%_%%_%%_%%_%%.yaml /// /// where all '%' will be replaced by a randomly chosen hex number. /// -/// @param SourceFile Full path to the source file. -/// @param HeaderFile Full path to the header file. -/// @param Result The resulting unique filename in the same directory as the -/// header file. -/// @param Error Description of the error if there is any. -/// @returns true if succeeded, false otherwise. -bool generateReplacementsFileName(llvm::StringRef SourceFile, - llvm::StringRef HeaderFile, - llvm::SmallVectorImpl<char> &Result, - llvm::SmallVectorImpl<char> &Error); +/// \param[in] MainSourceFile Full path to the source file. +/// \param[out] Result The resulting unique filename in the same directory as +/// the \c MainSourceFile. +/// \param[out] Error If an error occurs a description of that error is +/// placed in this string. +/// \returns true on success, false if a unique file name could not be created. +bool generateReplacementsFileName(const llvm::StringRef MainSourceFile, + llvm::SmallVectorImpl<char> &Result, + llvm::SmallVectorImpl<char> &Error); #endif // CPP11_MIGRATE_FILE_OVERRIDES_H diff --git a/clang-tools-extra/cpp11-migrate/Core/Makefile b/clang-tools-extra/cpp11-migrate/Core/Makefile index 5da4cec8481..51bc98defee 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Makefile +++ b/clang-tools-extra/cpp11-migrate/Core/Makefile @@ -11,4 +11,4 @@ LIBRARYNAME := migrateCore include $(CLANG_LEVEL)/Makefile -CPP.Flags += -I$(PROJ_SRC_DIR)/.. +CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include diff --git a/clang-tools-extra/cpp11-migrate/Core/Refactoring.h b/clang-tools-extra/cpp11-migrate/Core/Refactoring.h new file mode 100644 index 00000000000..a15634a3704 --- /dev/null +++ b/clang-tools-extra/cpp11-migrate/Core/Refactoring.h @@ -0,0 +1,31 @@ +//===-- Core/Refactoring.h - Stand-in for Tooling/Refactoring.h -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file is meant to be used instead of clang/Tooling/Refactoring.h +/// until such time as clang::tooling::Replacements is re-implemented as a +/// vector instead of a set. +/// +//===----------------------------------------------------------------------===// + +#ifndef CPP11_MIGRATE_REPLACEMENTS_VEC_H +#define CPP11_MIGRATE_REPLACEMENTS_VEC_H + +#include "clang/Tooling/Refactoring.h" + +// FIXME: Remove this file when clang::tooling::Replacements becomes a vector +// instead of a set. + +namespace clang { +namespace tooling { +typedef std::vector<clang::tooling::Replacement> ReplacementsVec; +} +} + +#endif // CPP11_MIGRATE_REPLACEMENTS_VEC_H diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp index 4e14ea5784e..50ba1f19f7a 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp @@ -22,39 +22,23 @@ using namespace clang; -void Reformatter::reformatChanges(SourceOverrides &Overrides) { - llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( - new DiagnosticOptions()); - DiagnosticsEngine Diagnostics( - llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), - DiagOpts.getPtr()); - FileManager Files((FileSystemOptions())); - SourceManager SM(Diagnostics, Files); - - reformatChanges(Overrides, SM); -} - -void Reformatter::reformatChanges(SourceOverrides &Overrides, - clang::SourceManager &SM) { - tooling::Replacements Replaces; - Overrides.applyOverrides(SM); - if (Overrides.isSourceOverriden()) - Replaces = reformatSingleFile(Overrides.getMainFileName(), - Overrides.getChangedRanges(), SM); - - for (HeaderOverrides::const_iterator I = Overrides.headers_begin(), - E = Overrides.headers_end(); +void Reformatter::reformatChanges(const FileOverrides &FileStates, + clang::SourceManager &SM, + clang::tooling::ReplacementsVec &Replaces) { + FileStates.applyOverrides(SM); + + for (FileOverrides::ChangeMap::const_iterator + I = FileStates.getChangedRanges().begin(), + E = FileStates.getChangedRanges().end(); I != E; ++I) { - const HeaderOverride &Header = I->getValue(); - const tooling::Replacements &HeaderReplaces = - reformatSingleFile(Header.getHeaderPath(), Header.getChanges(), SM); - Replaces.insert(HeaderReplaces.begin(), HeaderReplaces.end()); + reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces); } - Overrides.applyReplacements(Replaces, SM); } -tooling::Replacements Reformatter::reformatSingleFile( - llvm::StringRef FileName, const ChangedRanges &Changes, SourceManager &SM) { +void Reformatter::reformatSingleFile( + const llvm::StringRef FileName, const ChangedRanges &Changes, + SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) { + const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName); assert(Entry && "expected an existing file"); @@ -72,5 +56,7 @@ tooling::Replacements Reformatter::reformatSingleFile( } Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard)); - return format::reformat(Style, Lex, SM, ReformatRanges); + const tooling::Replacements &R = + format::reformat(Style, Lex, SM, ReformatRanges); + std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements)); } diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h index e63e51d2160..9a10171a742 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h +++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h @@ -16,9 +16,10 @@ #ifndef CPP11_MIGRATE_REFORMATTING_H #define CPP11_MIGRATE_REFORMATTING_H +#include "Core/Refactoring.h" #include "clang/Format/Format.h" -class SourceOverrides; +class FileOverrides; class ChangedRanges; class Reformatter { @@ -27,31 +28,30 @@ public: /// \brief Reformat the changes made to the file overrides. /// - /// \param Overrides Overriden source files to reformat. Note that since only - /// the changes are reformatted, file change tracking has to be enabled. - /// \param SM A SourceManager where the overridens files can be found. + /// This function will apply the state of files stored in \c FileState to \c + /// SM. /// - /// \sa \c SourceOverrides::isTrackingFileChanges() - void reformatChanges(SourceOverrides &Overrides, clang::SourceManager &SM); - - /// \brief Overload of \c reformatChanges() providing it's own - /// \c SourceManager. - void reformatChanges(SourceOverrides &Overrides); + /// \param[in] FileState Files to reformat. + /// \param[in] SM SourceManager for access to source files. + /// \param[out] Replaces Container to store all reformatting replacements. + void reformatChanges(const FileOverrides &FileState, clang::SourceManager &SM, + clang::tooling::ReplacementsVec &Replaces); /// \brief Produce a list of replacements to apply on \p FileName, only the /// ranges in \p Changes are replaced. /// - /// Since this routine use \c clang::format::reformat() the rules that applies - /// on the ranges are identical: + /// Since this routine use \c clang::format::reformat() the rules that + /// function applies to ranges also apply here. /// - /// \par - /// Each range is extended on either end to its next bigger logic - /// unit, i.e. everything that might influence its formatting or might be - /// influenced by its formatting. - /// -- \c clang::format::reformat() - clang::tooling::Replacements reformatSingleFile(llvm::StringRef FileName, - const ChangedRanges &Changes, - clang::SourceManager &SM); + /// \param[in] FileName Name of file to reformat. + /// \param[in] Changes Description of where changes were made to the file. + /// \param[in] SM SourceManager required to create replacements. + /// \param[out] FormatReplacements New reformatting replacements are appended + /// to this container. + void reformatSingleFile(const llvm::StringRef FileName, + const ChangedRanges &Changes, + clang::SourceManager &SM, + clang::tooling::ReplacementsVec &FormatReplacements); private: clang::format::FormatStyle Style; diff --git a/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp b/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp index 7315768f360..bd2eb63044f 100644 --- a/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp @@ -30,9 +30,7 @@ public: if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename)) return false; - FileOverrides::const_iterator I = Overrides.find(Filename); - if (I != Overrides.end()) - I->second->applyOverrides(CI.getSourceManager()); + Overrides.applyOverrides(CI.getSourceManager()); return true; } diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp index 4354df2987e..cd76723d316 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp @@ -100,13 +100,8 @@ bool Transform::isFileModifiable(const SourceManager &SM, bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { assert(Overrides != 0 && "Subclass transform didn't provide InputState"); - CurrentSource = Filename.str(); - - FileOverrides::const_iterator I = Overrides->find(CurrentSource); - if (I != Overrides->end()) - I->second->applyOverrides(CI.getSourceManager()); - - Replace.clear(); + Overrides->applyOverrides(CI.getSourceManager()); + CurrentSource = Filename; if (Options().EnableTiming) { Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord())); @@ -116,11 +111,7 @@ bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { } void Transform::handleEndSource() { - if (!getReplacements().empty()) { - SourceOverrides &SO = Overrides->getOrCreate(CurrentSource); - SO.applyReplacements(getReplacements()); - } - + CurrentSource.clear(); if (Options().EnableTiming) Timings.back().second += llvm::TimeRecord::getCurrentTime(false); } @@ -129,6 +120,19 @@ void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) { Timings.push_back(std::make_pair(Label.str(), Duration)); } +bool +Transform::addReplacementForCurrentTU(const clang::tooling::Replacement &R) { + if (CurrentSource.empty()) + return false; + + TranslationUnitReplacements &TU = Replacements[CurrentSource]; + if (TU.MainSourceFile.empty()) + TU.MainSourceFile = CurrentSource; + TU.Replacements.push_back(R); + + return true; +} + FrontendActionFactory *Transform::createActionFactory(MatchFinder &Finder) { return new ActionFactory(Finder, /*Owner=*/ *this); } diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.h b/clang-tools-extra/cpp11-migrate/Core/Transform.h index 43082111d54..45e470d64e4 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.h +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.h @@ -17,7 +17,7 @@ #define CPP11_MIGRATE_TRANSFORM_H #include "Core/IncludeExcludeInfo.h" -#include "clang/Tooling/Refactoring.h" +#include "Core/Refactoring.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Registry.h" @@ -52,6 +52,12 @@ class MatchFinder; class FileOverrides; + +// \brief Maps main source file names to a TranslationUnitReplacements +// structure storing replacements for that translation unit. +typedef llvm::StringMap<clang::tooling::TranslationUnitReplacements> +TUReplacementsMap; + /// \brief To group transforms' options together when printing the help. extern llvm::cl::OptionCategory TransformsOptionsCategory; @@ -99,7 +105,7 @@ public: /// SourcePaths and should take precedence over content of files on disk. /// Upon return, \p ResultStates shall contain the result of performing this /// transform on the files listed in \p SourcePaths. - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) = 0; @@ -172,6 +178,17 @@ public: /// \brief Return an iterator to the start of collected timing data. TimingVec::const_iterator timing_end() const { return Timings.end(); } + /// \brief Add a Replacement to the list for the current translation unit. + /// + /// \returns \li true on success + /// \li false if there is no current translation unit + bool addReplacementForCurrentTU(const clang::tooling::Replacement &R); + + /// \brief Accessor to Replacements across all transformed translation units. + const TUReplacementsMap &getAllReplacements() const { + return Replacements; + } + protected: void setAcceptedChanges(unsigned Changes) { @@ -195,16 +212,12 @@ protected: /// created with. const TransformOptions &Options() { return GlobalOptions; } - /// \brief Provide access for subclasses for the container to store - /// translation unit replacements. - clang::tooling::Replacements &getReplacements() { return Replace; } - /// \brief Affords a subclass to provide file contents overrides before /// applying frontend actions. /// /// It is an error not to call this function before calling ClangTool::run() /// with the factory provided by createActionFactory(). - void setOverrides(FileOverrides &Overrides) { + void setOverrides(const FileOverrides &Overrides) { this->Overrides = &Overrides; } @@ -219,8 +232,8 @@ protected: private: const std::string Name; const TransformOptions &GlobalOptions; - FileOverrides *Overrides; - clang::tooling::Replacements Replace; + const FileOverrides *Overrides; + TUReplacementsMap Replacements; std::string CurrentSource; TimingVec Timings; unsigned AcceptedChanges; diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp index da9d7b56557..0ba49d8ad4f 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.cpp @@ -815,9 +815,9 @@ void LoopFixer::doConversion(ASTContext *Context, // the declaration of the alias variable. This is probably a bug. ReplacementText = ";"; - Replace->insert(Replacement(Context->getSourceManager(), - CharSourceRange::getTokenRange(ReplaceRange), - ReplacementText)); + Owner.addReplacementForCurrentTU(Replacement( + Context->getSourceManager(), + CharSourceRange::getTokenRange(ReplaceRange), ReplacementText)); // No further replacements are made to the loop, since the iterator or index // was used exactly once - in the initialization of AliasVar. } else { @@ -830,10 +830,9 @@ void LoopFixer::doConversion(ASTContext *Context, I != E; ++I) { std::string ReplaceText = I->IsArrow ? VarName + "." : VarName; ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar)); - Replace->insert( + Owner.addReplacementForCurrentTU( Replacement(Context->getSourceManager(), - CharSourceRange::getTokenRange(I->Range), - ReplaceText)); + CharSourceRange::getTokenRange(I->Range), ReplaceText)); } } @@ -862,9 +861,9 @@ void LoopFixer::doConversion(ASTContext *Context, std::string TypeString = AutoRefType.getAsString(); std::string Range = ("(" + TypeString + " " + VarName + " : " + MaybeDereference + ContainerString + ")").str(); - Replace->insert(Replacement(Context->getSourceManager(), - CharSourceRange::getTokenRange(ParenRange), - Range)); + Owner.addReplacementForCurrentTU( + Replacement(Context->getSourceManager(), + CharSourceRange::getTokenRange(ParenRange), Range)); GeneratedDecls->insert(make_pair(TheLoop, VarName)); } diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h index 95c1b021576..b72576bde82 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h @@ -41,12 +41,11 @@ enum LoopFixerKind { class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: LoopFixer(StmtAncestorASTVisitor *ParentFinder, - clang::tooling::Replacements *Replace, StmtGeneratedVarNameMap *GeneratedDecls, ReplacedVarsMap *ReplacedVarRanges, unsigned *AcceptedChanges, unsigned *DeferredChanges, unsigned *RejectedChanges, - RiskLevel MaxRisk, LoopFixerKind FixerKind, const Transform &Owner) - : ParentFinder(ParentFinder), Replace(Replace), + RiskLevel MaxRisk, LoopFixerKind FixerKind, Transform &Owner) + : ParentFinder(ParentFinder), GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges), AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges), RejectedChanges(RejectedChanges), MaxRisk(MaxRisk), @@ -57,7 +56,6 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { private: StmtAncestorASTVisitor *ParentFinder; - clang::tooling::Replacements *Replace; StmtGeneratedVarNameMap *GeneratedDecls; ReplacedVarsMap *ReplacedVarRanges; unsigned *AcceptedChanges; @@ -65,7 +63,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { unsigned *RejectedChanges; RiskLevel MaxRisk; LoopFixerKind FixerKind; - const Transform &Owner; + Transform &Owner; /// \brief Computes the changes needed to convert a given for loop, and /// applies it. diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp index 73c2560e796..2dfa4562929 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.cpp @@ -24,7 +24,7 @@ using clang::ast_matchers::MatchFinder; using namespace clang::tooling; using namespace clang; -int LoopConvertTransform::apply(FileOverrides &InputStates, +int LoopConvertTransform::apply(const FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) { ClangTool LoopTool(Database, SourcePaths); @@ -37,20 +37,20 @@ int LoopConvertTransform::apply(FileOverrides &InputStates, unsigned RejectedChanges = 0; MatchFinder Finder; - LoopFixer ArrayLoopFixer(&ParentFinder, &getReplacements(), &GeneratedDecls, - &ReplacedVars, &AcceptedChanges, &DeferredChanges, - &RejectedChanges, Options().MaxRiskLevel, LFK_Array, + LoopFixer ArrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, + &AcceptedChanges, &DeferredChanges, &RejectedChanges, + Options().MaxRiskLevel, LFK_Array, /*Owner=*/ *this); Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer); - LoopFixer IteratorLoopFixer( - &ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, - &AcceptedChanges, &DeferredChanges, &RejectedChanges, - Options().MaxRiskLevel, LFK_Iterator, /*Owner=*/ *this); + LoopFixer IteratorLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, + &AcceptedChanges, &DeferredChanges, + &RejectedChanges, Options().MaxRiskLevel, + LFK_Iterator, /*Owner=*/ *this); Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer); - LoopFixer PseudoarrrayLoopFixer( - &ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, - &AcceptedChanges, &DeferredChanges, &RejectedChanges, - Options().MaxRiskLevel, LFK_PseudoArray, /*Owner=*/ *this); + LoopFixer PseudoarrrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, + &AcceptedChanges, &DeferredChanges, + &RejectedChanges, Options().MaxRiskLevel, + LFK_PseudoArray, /*Owner=*/ *this); Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer); setOverrides(InputStates); diff --git a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.h b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.h index af287652485..b45d9555b3d 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.h +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopConvert.h @@ -28,7 +28,7 @@ public: : Transform("LoopConvert", Options) {} /// \see Transform::run(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp index 968fb5c8fff..fbd641233af 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp @@ -21,15 +21,14 @@ using namespace clang; using namespace clang::tooling; using namespace clang::ast_matchers; -int PassByValueTransform::apply( - FileOverrides &InputStates, const tooling::CompilationDatabase &Database, - const std::vector<std::string> &SourcePaths) { +int PassByValueTransform::apply(const FileOverrides &InputStates, + const tooling::CompilationDatabase &Database, + const std::vector<std::string> &SourcePaths) { ClangTool Tool(Database, SourcePaths); unsigned AcceptedChanges = 0; unsigned RejectedChanges = 0; MatchFinder Finder; - ConstructorParamReplacer Replacer(getReplacements(), AcceptedChanges, - RejectedChanges, + ConstructorParamReplacer Replacer(AcceptedChanges, RejectedChanges, /*Owner=*/ *this); Finder.addMatcher(makePassByValueCtorParamMatcher(), &Replacer); diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.h b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.h index 00949526254..6dad5497c99 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.h +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.h @@ -58,7 +58,7 @@ public: : Transform("PassByValue", Options), Replacer(0) {} /// \see Transform::apply(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp index 612850a70db..63189219294 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp @@ -151,17 +151,21 @@ void ConstructorParamReplacer::run(const MatchFinder::MatchResult &Result) { const tooling::Replacement &IncludeReplace = IncludeManager->addAngledInclude(STDMoveFile, "utility"); if (IncludeReplace.isApplicable()) { - Replaces.insert(IncludeReplace); + Owner.addReplacementForCurrentTU(IncludeReplace); AcceptedChanges++; } // const-ref params becomes values (const Foo & -> Foo) - Replaces.insert(ParamReplaces.begin(), ParamReplaces.end()); + for (const Replacement *I = ParamReplaces.begin(), *E = ParamReplaces.end(); + I != E; ++I) { + Owner.addReplacementForCurrentTU(*I); + } AcceptedChanges += ParamReplaces.size(); // move the value in the init-list - Replaces.insert(Replacement( + Owner.addReplacementForCurrentTU(Replacement( SM, Initializer->getLParenLoc().getLocWithOffset(1), 0, "std::move(")); - Replaces.insert(Replacement(SM, Initializer->getRParenLoc(), 0, ")")); + Owner.addReplacementForCurrentTU( + Replacement(SM, Initializer->getRParenLoc(), 0, ")")); AcceptedChanges += 2; } diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h index 5564fc54caf..5aeaae4f9fb 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h @@ -51,11 +51,10 @@ class IncludeDirectives; class ConstructorParamReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - ConstructorParamReplacer(clang::tooling::Replacements &Replaces, - unsigned &AcceptedChanges, unsigned &RejectedChanges, - const Transform &Owner) - : Replaces(Replaces), AcceptedChanges(AcceptedChanges), - RejectedChanges(RejectedChanges), Owner(Owner), IncludeManager(0) {} + ConstructorParamReplacer(unsigned &AcceptedChanges, unsigned &RejectedChanges, + Transform &Owner) + : AcceptedChanges(AcceptedChanges), RejectedChanges(RejectedChanges), + Owner(Owner), IncludeManager(0) {} void setIncludeDirectives(IncludeDirectives *Includes) { IncludeManager = Includes; @@ -66,10 +65,9 @@ private: virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) LLVM_OVERRIDE; - clang::tooling::Replacements &Replaces; unsigned &AcceptedChanges; unsigned &RejectedChanges; - const Transform &Owner; + Transform &Owner; IncludeDirectives *IncludeManager; }; diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp index 47dce8e7c89..fae7970b416 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp @@ -22,16 +22,14 @@ using namespace clang::tooling; using namespace clang::ast_matchers; int -ReplaceAutoPtrTransform::apply(FileOverrides &InputStates, +ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) { ClangTool Tool(Database, SourcePaths); unsigned AcceptedChanges = 0; MatchFinder Finder; - AutoPtrReplacer Replacer(getReplacements(), AcceptedChanges, - /*Owner=*/*this); - OwnershipTransferFixer Fixer(getReplacements(), AcceptedChanges, - /*Owner=*/*this); + AutoPtrReplacer Replacer(AcceptedChanges, /*Owner=*/ *this); + OwnershipTransferFixer Fixer(AcceptedChanges, /*Owner=*/ *this); Finder.addMatcher(makeAutoPtrTypeLocMatcher(), &Replacer); Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer); diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h index 2bc711480a3..c236c99b6c8 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.h @@ -47,7 +47,7 @@ public: : Transform("ReplaceAutoPtr", Options) {} /// \see Transform::run(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp index f538d94d53a..2074e3764bb 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp @@ -66,7 +66,7 @@ void AutoPtrReplacer::run(const MatchFinder::MatchResult &Result) { if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions())) return; - Replace.insert( + Owner.addReplacementForCurrentTU( Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr")); ++AcceptedChanges; } @@ -101,7 +101,8 @@ void OwnershipTransferFixer::run(const MatchFinder::MatchResult &Result) { if (!Owner.isFileModifiable(SM, Range.getBegin())) return; - Replace.insert(Replacement(SM, Range.getBegin(), 0, "std::move(")); - Replace.insert(Replacement(SM, Range.getEnd(), 0, ")")); + Owner.addReplacementForCurrentTU( + Replacement(SM, Range.getBegin(), 0, "std::move(")); + Owner.addReplacementForCurrentTU(Replacement(SM, Range.getEnd(), 0, ")")); AcceptedChanges += 2; } diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h index 2cf55a09742..fb805965b01 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h @@ -25,9 +25,8 @@ class Transform; /// using declarations. class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - AutoPtrReplacer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} + AutoPtrReplacer(unsigned &AcceptedChanges, Transform &Owner) + : AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) @@ -63,9 +62,8 @@ private: const clang::SourceManager &SM); private: - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; - const Transform &Owner; + Transform &Owner; }; /// \brief The callback to be used to fix the ownership transfers of @@ -86,18 +84,16 @@ private: class OwnershipTransferFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - OwnershipTransferFixer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} + OwnershipTransferFixer(unsigned &AcceptedChanges, Transform &Owner) + : AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) LLVM_OVERRIDE; private: - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; - const Transform &Owner; + Transform &Owner; }; #endif // CPP11_MIGRATE_REPLACE_AUTO_PTR_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp index ccf49d88c92..72f5ae077f2 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.cpp @@ -20,7 +20,7 @@ using clang::ast_matchers::MatchFinder; using namespace clang; using namespace clang::tooling; -int UseAutoTransform::apply(FileOverrides &InputStates, +int UseAutoTransform::apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) { ClangTool UseAutoTool(Database, SourcePaths); @@ -28,10 +28,11 @@ int UseAutoTransform::apply(FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - IteratorReplacer ReplaceIterators(getReplacements(), AcceptedChanges, - Options().MaxRiskLevel, /*Owner=*/ *this); - NewReplacer ReplaceNew(getReplacements(), AcceptedChanges, - Options().MaxRiskLevel, /*Owner=*/ *this); + ReplacementsVec Replaces; + IteratorReplacer ReplaceIterators(AcceptedChanges, Options().MaxRiskLevel, + /*Owner=*/ *this); + NewReplacer ReplaceNew(AcceptedChanges, Options().MaxRiskLevel, + /*Owner=*/ *this); Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators); Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew); diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.h b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.h index 71b8dd7dc95..26b5e4496f6 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.h +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAuto.h @@ -34,7 +34,7 @@ public: : Transform("UseAuto", Options) {} /// \see Transform::run(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp index 643de63069e..2a8d5c5935d 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp @@ -73,7 +73,7 @@ void IteratorReplacer::run(const MatchFinder::MatchResult &Result) { // iterators but something to keep in mind in the future. CharSourceRange Range(TL.getSourceRange(), true); - Replace.insert(tooling::Replacement(SM, Range, "auto")); + Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto")); ++AcceptedChanges; } @@ -131,8 +131,9 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) { for (std::vector<SourceLocation>::iterator I = StarLocations.begin(), E = StarLocations.end(); I != E; ++I) { - Replace.insert(tooling::Replacement(SM, *I, 1, "")); + Owner.addReplacementForCurrentTU(tooling::Replacement(SM, *I, 1, "")); } + // FIXME: There is, however, one case we can address: when the VarDecl // pointee is the same as the initializer, just more CV-qualified. However, // TypeLoc information is not reliable where CV qualifiers are concerned so @@ -141,6 +142,6 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) { FirstDecl->getTypeSourceInfo()->getTypeLoc().getSourceRange(), true); // Space after 'auto' to handle cases where the '*' in the pointer type // is next to the identifier. This avoids changing 'int *p' into 'autop'. - Replace.insert(tooling::Replacement(SM, Range, "auto ")); + Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto ")); ++AcceptedChanges; } diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h index 403621803c3..0ddb0e0c5af 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h @@ -25,36 +25,32 @@ class IteratorReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - IteratorReplacer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, RiskLevel, const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} + IteratorReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner) + : AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) LLVM_OVERRIDE; private: - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; - const Transform &Owner; + Transform &Owner; }; /// \brief The callback used when replacing type specifiers of variable /// declarations initialized by a C++ new expression. class NewReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - NewReplacer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, - RiskLevel, const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) {} + NewReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner) + : AcceptedChanges(AcceptedChanges), Owner(Owner) {} /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) LLVM_OVERRIDE; private: - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; - const Transform &Owner; + Transform &Owner; }; #endif // CPP11_MIGRATE_USE_AUTO_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp index e170801a034..23a8fd3a476 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.cpp @@ -47,7 +47,7 @@ bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc, /// \brief Replaces the provided range with the text "nullptr", but only if /// the start and end location are both in main file. /// Returns true if and only if a replacement was made. -void ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM, +void ReplaceWithNullptr(Transform &Owner, SourceManager &SM, SourceLocation StartLoc, SourceLocation EndLoc) { CharSourceRange Range(SourceRange(StartLoc, EndLoc), true); // Add a space if nullptr follows an alphanumeric character. This happens @@ -55,9 +55,11 @@ void ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM, // parentheses and right beside a return statement. SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1); if (isAlphanumeric(*FullSourceLoc(PreviousLocation, SM).getCharacterData())) - Replace.insert(tooling::Replacement(SM, Range, " nullptr")); + Owner.addReplacementForCurrentTU( + tooling::Replacement(SM, Range, " nullptr")); else - Replace.insert(tooling::Replacement(SM, Range, "nullptr")); + Owner.addReplacementForCurrentTU( + tooling::Replacement(SM, Range, "nullptr")); } /// \brief Returns the name of the outermost macro. @@ -153,10 +155,9 @@ private: /// ambiguities. class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> { public: - CastSequenceVisitor(tooling::Replacements &R, ASTContext &Context, - const UserMacroNames &UserNullMacros, - unsigned &AcceptedChanges, const Transform &Owner) - : Replace(R), SM(Context.getSourceManager()), Context(Context), + CastSequenceVisitor(ASTContext &Context, const UserMacroNames &UserNullMacros, + unsigned &AcceptedChanges, Transform &Owner) + : SM(Context.getSourceManager()), Context(Context), UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges), Owner(Owner), FirstSubExpr(0), PruneSubtree(false) {} @@ -196,7 +197,7 @@ public: FileLocEnd = SM.getFileLoc(EndLoc); if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) && allArgUsesValid(C)) { - ReplaceWithNullptr(Replace, SM, FileLocStart, FileLocEnd); + ReplaceWithNullptr(Owner, SM, FileLocStart, FileLocEnd); ++AcceptedChanges; } return skipSubTree(); @@ -220,7 +221,7 @@ public: if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) { return skipSubTree(); } - ReplaceWithNullptr(Replace, SM, StartLoc, EndLoc); + ReplaceWithNullptr(Owner, SM, StartLoc, EndLoc); ++AcceptedChanges; return skipSubTree(); @@ -417,21 +418,19 @@ private: } private: - tooling::Replacements &Replace; SourceManager &SM; ASTContext &Context; const UserMacroNames &UserNullMacros; unsigned &AcceptedChanges; - const Transform &Owner; + Transform &Owner; Expr *FirstSubExpr; bool PruneSubtree; }; } // namespace -NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace, - unsigned &AcceptedChanges, RiskLevel, - const Transform &Owner) - : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) { +NullptrFixer::NullptrFixer(unsigned &AcceptedChanges, RiskLevel, + Transform &Owner) + : AcceptedChanges(AcceptedChanges), Owner(Owner) { if (!UserNullMacroNames.empty()) { llvm::StringRef S = UserNullMacroNames; S.split(UserNullMacros, ","); @@ -445,7 +444,7 @@ void NullptrFixer::run(const ast_matchers::MatchFinder::MatchResult &Result) { // Given an implicit null-ptr cast or an explicit cast with an implicit // null-to-pointer cast within use CastSequenceVisitor to identify sequences // of explicit casts that can be converted into 'nullptr'. - CastSequenceVisitor Visitor(Replace, *Result.Context, UserNullMacros, - AcceptedChanges, Owner); + CastSequenceVisitor Visitor(*Result.Context, UserNullMacros, AcceptedChanges, + Owner); Visitor.TraverseStmt(const_cast<CastExpr *>(NullCast)); } diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h index f647d8e4d65..02da6b76db0 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h @@ -27,17 +27,15 @@ typedef llvm::SmallVector<llvm::StringRef, 1> UserMacroNames; /// class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - NullptrFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, - RiskLevel, const Transform &Owner); + NullptrFixer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner); /// \brief Entry point to the callback called when matches are made. virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result); private: - clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; UserMacroNames UserNullMacros; - const Transform &Owner; + Transform &Owner; }; #endif // CPP11_MIGRATE_NULLPTR_ACTIONS_H diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp index afeec4a10af..e07ee6682ee 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.cpp @@ -24,7 +24,7 @@ using clang::ast_matchers::MatchFinder; using namespace clang::tooling; using namespace clang; -int UseNullptrTransform::apply(FileOverrides &InputStates, +int UseNullptrTransform::apply(const FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) { ClangTool UseNullptrTool(Database, SourcePaths); @@ -32,8 +32,7 @@ int UseNullptrTransform::apply(FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - NullptrFixer Fixer(getReplacements(), AcceptedChanges, Options().MaxRiskLevel, - /*Owner=*/ *this); + NullptrFixer Fixer(AcceptedChanges, Options().MaxRiskLevel, /*Owner=*/ *this); Finder.addMatcher(makeCastSequenceMatcher(), &Fixer); diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h index 873ffab0702..ed90f9a5bbc 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/UseNullptr.h @@ -28,7 +28,7 @@ public: : Transform("UseNullptr", Options) {} /// \see Transform::run(). - virtual int apply(FileOverrides &InputStates, + virtual int apply(const FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt b/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt index a40e0f3e31a..8721b5e5c25 100644 --- a/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt +++ b/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt @@ -34,6 +34,7 @@ add_dependencies(cpp11-migrate ) target_link_libraries(cpp11-migrate + clangReplace migrateCore ) diff --git a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp index eaaec3c91de..e75a4754881 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp +++ b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp @@ -21,9 +21,14 @@ #include "Core/Transform.h" #include "Core/Transforms.h" #include "Core/Reformatting.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/SourceManager.h" #include "clang/Frontend/FrontendActions.h" +#include "clang/Rewrite/Core/Rewriter.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Tooling.h" +#include "clang-replace/Tooling/ApplyReplacements.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/MemoryBuffer.h" @@ -122,12 +127,12 @@ static cl::opt<bool, /*ExternalStorage=*/true> EnableHeaderModifications( cl::location(GlobalOptions.EnableHeaderModifications), cl::init(false)); -static cl::opt<bool> YAMLOnly("yaml-only", - cl::Hidden, // Associated with -headers - cl::desc("Don't change headers on disk. Write " - "changes to change description files " - "only."), - cl::init(false)); +static cl::opt<bool> +SerializeReplacements("serialize-replacements", + cl::Hidden, // Associated with -headers + cl::desc("Serialize translation unit replacements to " + "disk instead of changing files."), + cl::init(false)); cl::opt<std::string> SupportedCompilers( "for-compilers", cl::value_desc("string"), @@ -225,6 +230,68 @@ static Reformatter *handleFormatStyle(const char *ProgName, bool &Error) { return 0; } +/// \brief Use \c ChangesReformatter to reformat all changed regions of all +/// files stored in \c Overrides and write the result to disk. +/// +/// \returns \li true if reformatting replacements were successfully applied +/// without conflicts and all files were successfully written to +/// disk. +/// \li false if reformatting could not be successfully applied or +/// if at least one file failed to write to disk. +bool reformat(Reformatter &ChangesReformatter, const FileOverrides &Overrides, + DiagnosticsEngine &Diagnostics) { + FileManager Files((FileSystemOptions())); + SourceManager SM(Diagnostics, Files); + + replace::TUReplacements AllReplacements(1); + ChangesReformatter.reformatChanges(Overrides, SM, + AllReplacements.front().Replacements); + + replace::FileToReplacementsMap GroupedReplacements; + if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements, SM)) { + llvm::errs() << "Warning: Reformatting produced conflicts.\n"; + return false; + } + + Rewriter DestRewriter(SM, LangOptions()); + if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) { + llvm::errs() << "Warning: Failed to apply reformatting conflicts!\n"; + return false; + } + + return replace::writeFiles(DestRewriter); +} + +bool serializeReplacements(const replace::TUReplacements &Replacements) { + bool Errors = false; + for (replace::TUReplacements::const_iterator I = Replacements.begin(), + E = Replacements.end(); + I != E; ++I) { + llvm::SmallString<128> ReplacementsFileName; + llvm::SmallString<64> Error; + bool Result = generateReplacementsFileName(I->MainSourceFile, + ReplacementsFileName, Error); + if (!Result) { + llvm::errs() << "Failed to generate replacements filename:" << Error + << "\n"; + Errors = true; + continue; + } + + std::string ErrorInfo; + llvm::raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(), + ErrorInfo, llvm::sys::fs::F_Binary); + if (!ErrorInfo.empty()) { + llvm::errs() << "Error opening file: " << ErrorInfo << "\n"; + Errors = true; + continue; + } + llvm::yaml::Output YAML(ReplacementsFile); + YAML << const_cast<TranslationUnitReplacements &>(*I); + } + return !Errors; +} + int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); Transforms TransformManager; @@ -280,6 +347,15 @@ int main(int argc, const char **argv) { TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions); + llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( + new DiagnosticOptions()); + DiagnosticsEngine Diagnostics( + llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), + DiagOpts.getPtr()); + + // FIXME: Make this DiagnosticsEngine available to all Transforms probably via + // GlobalOptions. + if (TransformManager.begin() == TransformManager.end()) { if (SupportedCompilers.empty()) llvm::errs() << argv[0] << ": no selected transforms\n"; @@ -289,21 +365,22 @@ int main(int argc, const char **argv) { return 1; } - if (std::distance(TransformManager.begin(), TransformManager.end()) > 1 && - YAMLOnly) { - llvm::errs() << "Header change description files requested for multiple " + // If SerializeReplacements is requested, then change reformatting must be + // turned off and only one transform should be requested. Reformatting is + // basically another transform so even if there's only one other transform, + // the reformatting pass would make two. + if (SerializeReplacements && + (std::distance(TransformManager.begin(), TransformManager.end()) > 1 || + ChangesReformatter)) { + llvm::errs() << "Serialization of replacements requested for multiple " "transforms.\nChanges from only one transform can be " - "recorded in a change description file.\n"; + "serialized.\n"; return 1; } - // if reformatting is enabled we wants to track file changes so that it's - // possible to reformat them. - bool TrackReplacements = static_cast<bool>(ChangesReformatter); - FileOverrides FileStates(TrackReplacements); SourcePerfData PerfData; + FileOverrides FileStates; - // Apply transforms. for (Transforms::const_iterator I = TransformManager.begin(), E = TransformManager.end(); I != E; ++I) { @@ -326,79 +403,67 @@ int main(int argc, const char **argv) { } llvm::outs() << "\n"; } - } - // Reformat changes if a reformatter is provided. - if (ChangesReformatter) - for (FileOverrides::const_iterator I = FileStates.begin(), - E = FileStates.end(); - I != E; ++I) { - SourceOverrides &Overrides = *I->second; - ChangesReformatter->reformatChanges(Overrides); + // Collect all TranslationUnitReplacements generated from the translation + // units the transform worked on and store them in AllReplacements. + replace::TUReplacements AllReplacements; + const TUReplacementsMap &ReplacementsMap = T->getAllReplacements(); + const TranslationUnitReplacements &( + TUReplacementsMap::value_type::*getValue)() const = + &TUReplacementsMap::value_type::getValue; + std::transform(ReplacementsMap.begin(), ReplacementsMap.end(), + std::back_inserter(AllReplacements), + std::mem_fun_ref(getValue)); + + if (SerializeReplacements) + serializeReplacements(AllReplacements); + + FileManager Files((FileSystemOptions())); + SourceManager SM(Diagnostics, Files); + + // Make sure SourceManager is updated to have the same initial state as the + // transforms. + FileStates.applyOverrides(SM); + + replace::FileToReplacementsMap GroupedReplacements; + if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements, + SM)) { + llvm::outs() << "Transform " << T->getName() + << " resulted in conflicts. Discarding all " + << "replacements.\n"; + continue; } - if (FinalSyntaxCheck) - if (!doSyntaxCheck(*Compilations, SourcePaths, FileStates)) - return 1; - - // Write results to file. - for (FileOverrides::const_iterator I = FileStates.begin(), - E = FileStates.end(); - I != E; ++I) { - const SourceOverrides &Overrides = *I->second; - if (Overrides.isSourceOverriden()) { - std::string ErrorInfo; - std::string MainFileName = I->getKey(); - llvm::raw_fd_ostream FileStream(MainFileName.c_str(), ErrorInfo, - llvm::sys::fs::F_Binary); - FileStream << Overrides.getMainFileContent(); + // Apply replacements and update FileStates with new state. + Rewriter DestRewriter(SM, LangOptions()); + if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) { + llvm::outs() << "Some replacements failed to apply. Discarding " + "all replacements.\n"; + continue; } - for (HeaderOverrides::const_iterator HeaderI = Overrides.headers_begin(), - HeaderE = Overrides.headers_end(); - HeaderI != HeaderE; ++HeaderI) { - std::string ErrorInfo; - if (YAMLOnly) { - // Replacements for header files need to be written in a YAML file for - // every transform and will be merged together with an external tool. - llvm::SmallString<128> ReplacementsHeaderName; - llvm::SmallString<64> Error; - bool Result = - generateReplacementsFileName(I->getKey(), HeaderI->getKey().data(), - ReplacementsHeaderName, Error); - if (!Result) { - llvm::errs() << "Failed to generate replacements filename:" << Error - << "\n"; - continue; - } - - llvm::raw_fd_ostream ReplacementsFile( - ReplacementsHeaderName.c_str(), ErrorInfo, llvm::sys::fs::F_Binary); - if (!ErrorInfo.empty()) { - llvm::errs() << "Error opening file: " << ErrorInfo << "\n"; - continue; - } - llvm::yaml::Output YAML(ReplacementsFile); - YAML << const_cast<TranslationUnitReplacements &>( - HeaderI->getValue().getReplacements()); - } else { - // If -yaml-only was not specified, then change headers on disk. - // FIXME: This is transitional behaviour. Remove this functionality - // when header change description tool is ready. - assert(!HeaderI->second.getContentOverride().empty() && - "A header override should not be empty"); - std::string HeaderFileName = HeaderI->getKey(); - llvm::raw_fd_ostream HeaderStream(HeaderFileName.c_str(), ErrorInfo, - llvm::sys::fs::F_Binary); - if (!ErrorInfo.empty()) { - llvm::errs() << "Error opening file: " << ErrorInfo << "\n"; - continue; - } - HeaderStream << HeaderI->second.getContentOverride(); - } - } + // Update contents of files in memory to serve as initial state for next + // transform. + FileStates.updateState(DestRewriter); + + // Update changed ranges for reformatting + if (ChangesReformatter) + FileStates.adjustChangedRanges(GroupedReplacements); } + // Skip writing final file states to disk if we were asked to serialize + // replacements. Otherwise reformat changes if reformatting is enabled. If + // not enabled or if reformatting fails write un-formated changes to disk + // instead. reformat() takes care of writing successfully formatted changes. + if (!SerializeReplacements && + (!ChangesReformatter || + !reformat(*ChangesReformatter, FileStates, Diagnostics))) + FileStates.writeToDisk(Diagnostics); + + if (FinalSyntaxCheck) + if (!doSyntaxCheck(*Compilations, SourcePaths, FileStates)) + return 1; + // Report execution times. if (GlobalOptions.EnableTiming && !PerfData.empty()) { std::string DirectoryName = TimingDirectoryName; diff --git a/clang-tools-extra/cpp11-migrate/tool/Makefile b/clang-tools-extra/cpp11-migrate/tool/Makefile index f1780265aa9..82abe8ab569 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Makefile +++ b/clang-tools-extra/cpp11-migrate/tool/Makefile @@ -36,14 +36,14 @@ SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/.. BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option -USEDLIBS = migrateCore.a clangFormat.a clangTooling.a clangFrontend.a \ +USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFrontend.a \ clangSerialization.a clangDriver.a clangRewriteFrontend.a \ clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \ clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a include $(CLANG_LEVEL)/Makefile -CPP.Flags += -I$(PROJ_SRC_DIR)/.. +CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include # BUILT_SOURCES gets used as a prereq for many top-level targets. However, at # the point those targets are defined, $(ObjDir) hasn't been defined and so the |