diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverride.cpp index 9a13c044e5d2..db38fa64b56b 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 DetectMacros( cl::desc("Detect and use macros that expand to the 'override' keyword."), cl::cat(TransformsOptionsCategory)); -int AddOverrideTransform::apply(const FileOverrides &InputStates, +int AddOverrideTransform::apply(FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector &SourcePaths) { ClangTool AddOverrideTool(Database, SourcePaths); unsigned AcceptedChanges = 0; MatchFinder Finder; - AddOverrideFixer Fixer(AcceptedChanges, DetectMacros, + AddOverrideFixer Fixer(getReplacements(), 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 8c39775e48db..81ceaed859c9 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; diff --git a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp index 134318ed3864..47c070e55aea 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.cpp @@ -95,7 +95,6 @@ void AddOverrideFixer::run(const MatchFinder::MatchResult &Result) { if (!MacroName.empty()) ReplacementText = (" " + MacroName).str(); } - Owner.addReplacementForCurrentTU( - tooling::Replacement(SM, StartLoc, 0, ReplacementText)); + Replace.insert(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 afcebeffd4bf..54877d538a48 100644 --- a/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h +++ b/clang-tools-extra/cpp11-migrate/AddOverride/AddOverrideActions.h @@ -25,10 +25,11 @@ class Transform; /// class AddOverrideFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - AddOverrideFixer(unsigned &AcceptedChanges, bool DetectMacros, - Transform &Owner) - : AcceptedChanges(AcceptedChanges), DetectMacros(DetectMacros), - Owner(Owner) {} + AddOverrideFixer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, bool DetectMacros, + const Transform &Owner) + : Replace(Replace), 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); @@ -37,9 +38,10 @@ public: private: clang::Preprocessor *PP; + clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; bool DetectMacros; - Transform &Owner; + const 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 41bb68ef82d3..13ec7ac2e736 100644 --- a/clang-tools-extra/cpp11-migrate/CMakeLists.txt +++ b/clang-tools-extra/cpp11-migrate/CMakeLists.txt @@ -1,10 +1,4 @@ -get_filename_component(ClangReplaceLocation - "${CMAKE_CURRENT_SOURCE_DIR}/../clang-replace/include" ABSOLUTE) - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR} - ${ClangReplaceLocation} - ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 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 7ab7e91c30c0..d8d4b3f27e1a 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.cpp @@ -29,14 +29,157 @@ using namespace clang; using namespace clang::tooling; -bool generateReplacementsFileName(const llvm::StringRef MainSourceFile, - llvm::SmallVectorImpl &Result, - llvm::SmallVectorImpl &Error) { +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 DiagOpts( + new DiagnosticOptions()); + DiagnosticsEngine Diagnostics( + llvm::IntrusiveRefCntPtr(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 &Result, + llvm::SmallVectorImpl &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( - MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) { + if (llvm::error_code EC = + fs::createUniqueFile(HeaderPath.c_str(), Result)) { Error.append(EC.message().begin(), EC.message().end()); return false; } @@ -44,6 +187,20 @@ bool generateReplacementsFileName(const llvm::StringRef MainSourceFile, 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. @@ -90,11 +247,10 @@ struct RangeReplacedAdjuster { } // end anonymous namespace -void -ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) { +void ChangedRanges::adjustChangedRanges(const tooling::Replacements &Replaces) { // first adjust existing ranges in case they overlap with the replacements - for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end(); - I != E; ++I) { + for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; + ++I) { const tooling::Replacement &Replace = *I; std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(), @@ -109,8 +265,8 @@ ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) { } // then generate the new ranges from the replacements - for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end(); - I != E; ++I) { + for (Replacements::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(); @@ -147,52 +303,3 @@ 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 8cde7591303c..3e81abc6d343 100644 --- a/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h +++ b/clang-tools-extra/cpp11-migrate/Core/FileOverrides.h @@ -16,8 +16,7 @@ #ifndef CPP11_MIGRATE_FILE_OVERRIDES_H #define CPP11_MIGRATE_FILE_OVERRIDES_H -#include "Core/Refactoring.h" -#include "clang-replace/Tooling/ApplyReplacements.h" +#include "clang/Tooling/Refactoring.h" #include "clang/Tooling/ReplacementsYaml.h" #include "llvm/ADT/StringMap.h" @@ -45,13 +44,13 @@ public: /// to remove replaced parts. /// /// Note that all replacements should come from the same file. - void adjustChangedRanges(const clang::tooling::ReplacementsVec &Replaces); + void adjustChangedRanges(const clang::tooling::Replacements &Replaces); /// \brief Iterators. - /// \{ + /// @{ const_iterator begin() const { return Ranges.begin(); } const_iterator end() const { return Ranges.end(); } - /// \} + /// @} private: void coalesceRanges(); @@ -59,71 +58,178 @@ private: RangeVec Ranges; }; -/// \brief Maintains current state of transformed files and tracks source ranges -/// where changes have been made. -class FileOverrides { +/// \brief Container for storing override information for a single headers. +class HeaderOverride { public: - /// \brief Maps file names to file contents. - typedef llvm::StringMap FileStateMap; + /// \brief Constructors. + /// @{ + HeaderOverride() {} + HeaderOverride(llvm::StringRef HeaderPath, + llvm::StringRef MainSourceFile) : HeaderPath(HeaderPath) { + Replacements.MainSourceFile = MainSourceFile; + } + /// @} - /// \brief Maps file names to change tracking info for a file. - typedef llvm::StringMap ChangeMap; - - - /// \brief Override file contents seen by \c SM for all files stored by this - /// object. - void applyOverrides(clang::SourceManager &SM) const; - - /// \brief Update change tracking information based on replacements stored in - /// \c Replaces. - void - adjustChangedRanges(const clang::replace::FileToReplacementsMap &Replaces); - - /// \brief Accessor for change tracking information. - const ChangeMap &getChangedRanges() const { - return ChangeTracking; + /// \brief Getter for HeaderPath. + llvm::StringRef getHeaderPath() const { + return HeaderPath; } - /// \brief Coalesce changes stored in \c Rewrites and replace file contents - /// overrides stored in this object. - /// - /// \param Rewrites Rewriter containing changes to files. - void updateState(const clang::Rewriter &Rewrites); + /// \brief Accessor for ContentOverride. + /// @{ + llvm::StringRef getContentOverride() const { return ContentOverride; } + void setContentOverride(const llvm::StringRef S) { ContentOverride = S; } + /// @} - /// \brief Accessor for current file state. - const FileStateMap &getState() const { return FileStates; } + /// \brief Getter for Changes. + const ChangedRanges &getChanges() const { return Changes; } - /// \brief Write all file contents overrides to disk. - /// - /// \param Diagnostics DiagnosticsEngine for error output. - /// - /// \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; + /// \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 Stores the replacements made by a transform to the header this + /// object represents. + void recordReplacements(const clang::tooling::Replacements &Replaces); + + /// \brief Helper function to adjust the changed ranges. + void adjustChangedRanges(const clang::tooling::Replacements &Replaces) { + Changes.adjustChangedRanges(Replaces); + } private: - FileStateMap FileStates; - ChangeMap ChangeTracking; + std::string ContentOverride; + ChangedRanges Changes; + std::string HeaderPath; + clang::tooling::TranslationUnitReplacements Replacements; +}; + +/// \brief Container mapping header file names to override information. +typedef llvm::StringMap 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? + /// + /// Tracking file changes can be useful to reformat the code for example. + bool isTrackingFileChanges() const { return TrackChanges; } + /// @} + + /// \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 Override the file contents by applying all the replacements. + /// + /// \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 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 SourceOverridesMap; + typedef SourceOverridesMap::const_iterator const_iterator; + + /// \brief Construct the SourceOverrides manager. + /// + /// \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(); } + /// @} + +private: + FileOverrides(const FileOverrides &) LLVM_DELETED_FUNCTION; + FileOverrides &operator=(const FileOverrides &) LLVM_DELETED_FUNCTION; + + SourceOverridesMap Overrides; + const bool TrackChanges; }; /// \brief Generate a unique filename to store the replacements. /// -/// Generates a unique filename in the same directory as \c MainSourceFile. The -/// filename is generated following this pattern: +/// Generates a unique filename in the same directory as the header file. The +/// filename is based on the following model: /// -/// MainSourceFile_%%_%%_%%_%%_%%_%%.yaml +/// source.cpp_header.h_%%_%%_%%_%%_%%_%%.yaml /// /// where all '%' will be replaced by a randomly chosen hex number. /// -/// \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 &Result, - llvm::SmallVectorImpl &Error); +/// @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 &Result, + llvm::SmallVectorImpl &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 51bc98defee6..5da4cec8481f 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)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include +CPP.Flags += -I$(PROJ_SRC_DIR)/.. diff --git a/clang-tools-extra/cpp11-migrate/Core/Refactoring.h b/clang-tools-extra/cpp11-migrate/Core/Refactoring.h deleted file mode 100644 index a15634a37041..000000000000 --- a/clang-tools-extra/cpp11-migrate/Core/Refactoring.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- 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 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 50ba1f19f7a1..4e14ea5784eb 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.cpp @@ -22,23 +22,39 @@ using namespace clang; -void Reformatter::reformatChanges(const FileOverrides &FileStates, - clang::SourceManager &SM, - clang::tooling::ReplacementsVec &Replaces) { - FileStates.applyOverrides(SM); +void Reformatter::reformatChanges(SourceOverrides &Overrides) { + llvm::IntrusiveRefCntPtr DiagOpts( + new DiagnosticOptions()); + DiagnosticsEngine Diagnostics( + llvm::IntrusiveRefCntPtr(new DiagnosticIDs()), + DiagOpts.getPtr()); + FileManager Files((FileSystemOptions())); + SourceManager SM(Diagnostics, Files); - for (FileOverrides::ChangeMap::const_iterator - I = FileStates.getChangedRanges().begin(), - E = FileStates.getChangedRanges().end(); - I != E; ++I) { - reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces); - } + reformatChanges(Overrides, SM); } -void Reformatter::reformatSingleFile( - const llvm::StringRef FileName, const ChangedRanges &Changes, - SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) { +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(); + I != E; ++I) { + const HeaderOverride &Header = I->getValue(); + const tooling::Replacements &HeaderReplaces = + reformatSingleFile(Header.getHeaderPath(), Header.getChanges(), SM); + Replaces.insert(HeaderReplaces.begin(), HeaderReplaces.end()); + } + Overrides.applyReplacements(Replaces, SM); +} + +tooling::Replacements Reformatter::reformatSingleFile( + llvm::StringRef FileName, const ChangedRanges &Changes, SourceManager &SM) { const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName); assert(Entry && "expected an existing file"); @@ -56,7 +72,5 @@ void Reformatter::reformatSingleFile( } Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard)); - const tooling::Replacements &R = - format::reformat(Style, Lex, SM, ReformatRanges); - std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements)); + return format::reformat(Style, Lex, SM, ReformatRanges); } diff --git a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h index 9a10171a7426..e63e51d21608 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Reformatting.h +++ b/clang-tools-extra/cpp11-migrate/Core/Reformatting.h @@ -16,10 +16,9 @@ #ifndef CPP11_MIGRATE_REFORMATTING_H #define CPP11_MIGRATE_REFORMATTING_H -#include "Core/Refactoring.h" #include "clang/Format/Format.h" -class FileOverrides; +class SourceOverrides; class ChangedRanges; class Reformatter { @@ -28,30 +27,31 @@ public: /// \brief Reformat the changes made to the file overrides. /// - /// This function will apply the state of files stored in \c FileState to \c - /// SM. + /// \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. /// - /// \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); + /// \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); /// \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 - /// function applies to ranges also apply here. + /// Since this routine use \c clang::format::reformat() the rules that applies + /// on the ranges are identical: /// - /// \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); + /// \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); 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 bd2eb63044f0..7315768f3608 100644 --- a/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/SyntaxCheck.cpp @@ -30,7 +30,9 @@ public: if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename)) return false; - Overrides.applyOverrides(CI.getSourceManager()); + FileOverrides::const_iterator I = Overrides.find(Filename); + if (I != Overrides.end()) + I->second->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 cd76723d316e..4354df2987e1 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp @@ -100,8 +100,13 @@ bool Transform::isFileModifiable(const SourceManager &SM, bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { assert(Overrides != 0 && "Subclass transform didn't provide InputState"); - Overrides->applyOverrides(CI.getSourceManager()); - CurrentSource = Filename; + CurrentSource = Filename.str(); + + FileOverrides::const_iterator I = Overrides->find(CurrentSource); + if (I != Overrides->end()) + I->second->applyOverrides(CI.getSourceManager()); + + Replace.clear(); if (Options().EnableTiming) { Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord())); @@ -111,7 +116,11 @@ bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { } void Transform::handleEndSource() { - CurrentSource.clear(); + if (!getReplacements().empty()) { + SourceOverrides &SO = Overrides->getOrCreate(CurrentSource); + SO.applyReplacements(getReplacements()); + } + if (Options().EnableTiming) Timings.back().second += llvm::TimeRecord::getCurrentTime(false); } @@ -120,19 +129,6 @@ 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 45e470d64e4a..43082111d544 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 "Core/Refactoring.h" +#include "clang/Tooling/Refactoring.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Registry.h" @@ -52,12 +52,6 @@ class MatchFinder; class FileOverrides; - -// \brief Maps main source file names to a TranslationUnitReplacements -// structure storing replacements for that translation unit. -typedef llvm::StringMap -TUReplacementsMap; - /// \brief To group transforms' options together when printing the help. extern llvm::cl::OptionCategory TransformsOptionsCategory; @@ -105,7 +99,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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) = 0; @@ -178,17 +172,6 @@ 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) { @@ -212,12 +195,16 @@ 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(const FileOverrides &Overrides) { + void setOverrides(FileOverrides &Overrides) { this->Overrides = &Overrides; } @@ -232,8 +219,8 @@ protected: private: const std::string Name; const TransformOptions &GlobalOptions; - const FileOverrides *Overrides; - TUReplacementsMap Replacements; + FileOverrides *Overrides; + clang::tooling::Replacements Replace; 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 0ba49d8ad4f9..da9d7b56557a 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 = ";"; - Owner.addReplacementForCurrentTU(Replacement( - Context->getSourceManager(), - CharSourceRange::getTokenRange(ReplaceRange), ReplacementText)); + Replace->insert(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,9 +830,10 @@ void LoopFixer::doConversion(ASTContext *Context, I != E; ++I) { std::string ReplaceText = I->IsArrow ? VarName + "." : VarName; ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar)); - Owner.addReplacementForCurrentTU( + Replace->insert( Replacement(Context->getSourceManager(), - CharSourceRange::getTokenRange(I->Range), ReplaceText)); + CharSourceRange::getTokenRange(I->Range), + ReplaceText)); } } @@ -861,9 +862,9 @@ void LoopFixer::doConversion(ASTContext *Context, std::string TypeString = AutoRefType.getAsString(); std::string Range = ("(" + TypeString + " " + VarName + " : " + MaybeDereference + ContainerString + ")").str(); - Owner.addReplacementForCurrentTU( - Replacement(Context->getSourceManager(), - CharSourceRange::getTokenRange(ParenRange), Range)); + Replace->insert(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 b72576bde82a..95c1b0215764 100644 --- a/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h +++ b/clang-tools-extra/cpp11-migrate/LoopConvert/LoopActions.h @@ -41,11 +41,12 @@ 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, Transform &Owner) - : ParentFinder(ParentFinder), + RiskLevel MaxRisk, LoopFixerKind FixerKind, const Transform &Owner) + : ParentFinder(ParentFinder), Replace(Replace), GeneratedDecls(GeneratedDecls), ReplacedVarRanges(ReplacedVarRanges), AcceptedChanges(AcceptedChanges), DeferredChanges(DeferredChanges), RejectedChanges(RejectedChanges), MaxRisk(MaxRisk), @@ -56,6 +57,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { private: StmtAncestorASTVisitor *ParentFinder; + clang::tooling::Replacements *Replace; StmtGeneratedVarNameMap *GeneratedDecls; ReplacedVarsMap *ReplacedVarRanges; unsigned *AcceptedChanges; @@ -63,7 +65,7 @@ class LoopFixer : public clang::ast_matchers::MatchFinder::MatchCallback { unsigned *RejectedChanges; RiskLevel MaxRisk; LoopFixerKind FixerKind; - Transform &Owner; + const 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 2dfa45629296..73c2560e796a 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(const FileOverrides &InputStates, +int LoopConvertTransform::apply(FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector &SourcePaths) { ClangTool LoopTool(Database, SourcePaths); @@ -37,20 +37,20 @@ int LoopConvertTransform::apply(const FileOverrides &InputStates, unsigned RejectedChanges = 0; MatchFinder Finder; - LoopFixer ArrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, - &AcceptedChanges, &DeferredChanges, &RejectedChanges, - Options().MaxRiskLevel, LFK_Array, + LoopFixer ArrayLoopFixer(&ParentFinder, &getReplacements(), &GeneratedDecls, + &ReplacedVars, &AcceptedChanges, &DeferredChanges, + &RejectedChanges, Options().MaxRiskLevel, LFK_Array, /*Owner=*/ *this); Finder.addMatcher(makeArrayLoopMatcher(), &ArrayLoopFixer); - LoopFixer IteratorLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, - &AcceptedChanges, &DeferredChanges, - &RejectedChanges, Options().MaxRiskLevel, - LFK_Iterator, /*Owner=*/ *this); + LoopFixer IteratorLoopFixer( + &ParentFinder, &getReplacements(), &GeneratedDecls, &ReplacedVars, + &AcceptedChanges, &DeferredChanges, &RejectedChanges, + Options().MaxRiskLevel, LFK_Iterator, /*Owner=*/ *this); Finder.addMatcher(makeIteratorLoopMatcher(), &IteratorLoopFixer); - LoopFixer PseudoarrrayLoopFixer(&ParentFinder, &GeneratedDecls, &ReplacedVars, - &AcceptedChanges, &DeferredChanges, - &RejectedChanges, Options().MaxRiskLevel, - LFK_PseudoArray, /*Owner=*/ *this); + LoopFixer PseudoarrrayLoopFixer( + &ParentFinder, &getReplacements(), &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 b45d9555b3d1..af2876524854 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp index fbd641233aff..968fb5c8fff2 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValue.cpp @@ -21,14 +21,15 @@ using namespace clang; using namespace clang::tooling; using namespace clang::ast_matchers; -int PassByValueTransform::apply(const FileOverrides &InputStates, - const tooling::CompilationDatabase &Database, - const std::vector &SourcePaths) { +int PassByValueTransform::apply( + FileOverrides &InputStates, const tooling::CompilationDatabase &Database, + const std::vector &SourcePaths) { ClangTool Tool(Database, SourcePaths); unsigned AcceptedChanges = 0; unsigned RejectedChanges = 0; MatchFinder Finder; - ConstructorParamReplacer Replacer(AcceptedChanges, RejectedChanges, + ConstructorParamReplacer Replacer(getReplacements(), 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 6dad5497c994..009495262546 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp index 631892192947..612850a70dbf 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.cpp @@ -151,21 +151,17 @@ void ConstructorParamReplacer::run(const MatchFinder::MatchResult &Result) { const tooling::Replacement &IncludeReplace = IncludeManager->addAngledInclude(STDMoveFile, "utility"); if (IncludeReplace.isApplicable()) { - Owner.addReplacementForCurrentTU(IncludeReplace); + Replaces.insert(IncludeReplace); AcceptedChanges++; } // const-ref params becomes values (const Foo & -> Foo) - for (const Replacement *I = ParamReplaces.begin(), *E = ParamReplaces.end(); - I != E; ++I) { - Owner.addReplacementForCurrentTU(*I); - } + Replaces.insert(ParamReplaces.begin(), ParamReplaces.end()); AcceptedChanges += ParamReplaces.size(); // move the value in the init-list - Owner.addReplacementForCurrentTU(Replacement( + Replaces.insert(Replacement( SM, Initializer->getLParenLoc().getLocWithOffset(1), 0, "std::move(")); - Owner.addReplacementForCurrentTU( - Replacement(SM, Initializer->getRParenLoc(), 0, ")")); + Replaces.insert(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 5aeaae4f9fb2..5564fc54caf5 100644 --- a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueActions.h @@ -51,10 +51,11 @@ class IncludeDirectives; class ConstructorParamReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - ConstructorParamReplacer(unsigned &AcceptedChanges, unsigned &RejectedChanges, - Transform &Owner) - : AcceptedChanges(AcceptedChanges), RejectedChanges(RejectedChanges), - Owner(Owner), IncludeManager(0) {} + ConstructorParamReplacer(clang::tooling::Replacements &Replaces, + unsigned &AcceptedChanges, unsigned &RejectedChanges, + const Transform &Owner) + : Replaces(Replaces), AcceptedChanges(AcceptedChanges), + RejectedChanges(RejectedChanges), Owner(Owner), IncludeManager(0) {} void setIncludeDirectives(IncludeDirectives *Includes) { IncludeManager = Includes; @@ -65,9 +66,10 @@ private: virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) LLVM_OVERRIDE; + clang::tooling::Replacements &Replaces; unsigned &AcceptedChanges; unsigned &RejectedChanges; - Transform &Owner; + const 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 fae7970b4162..47dce8e7c892 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtr.cpp @@ -22,14 +22,16 @@ using namespace clang::tooling; using namespace clang::ast_matchers; int -ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates, +ReplaceAutoPtrTransform::apply(FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector &SourcePaths) { ClangTool Tool(Database, SourcePaths); unsigned AcceptedChanges = 0; MatchFinder Finder; - AutoPtrReplacer Replacer(AcceptedChanges, /*Owner=*/ *this); - OwnershipTransferFixer Fixer(AcceptedChanges, /*Owner=*/ *this); + AutoPtrReplacer Replacer(getReplacements(), AcceptedChanges, + /*Owner=*/*this); + OwnershipTransferFixer Fixer(getReplacements(), 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 c236c99b6c88..2bc711480a36 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.cpp index 2074e3764bb2..f538d94d53a9 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; - Owner.addReplacementForCurrentTU( + Replace.insert( Replacement(SM, IdentifierLoc, strlen("auto_ptr"), "unique_ptr")); ++AcceptedChanges; } @@ -101,8 +101,7 @@ void OwnershipTransferFixer::run(const MatchFinder::MatchResult &Result) { if (!Owner.isFileModifiable(SM, Range.getBegin())) return; - Owner.addReplacementForCurrentTU( - Replacement(SM, Range.getBegin(), 0, "std::move(")); - Owner.addReplacementForCurrentTU(Replacement(SM, Range.getEnd(), 0, ")")); + Replace.insert(Replacement(SM, Range.getBegin(), 0, "std::move(")); + Replace.insert(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 fb805965b010..2cf55a097424 100644 --- a/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h +++ b/clang-tools-extra/cpp11-migrate/ReplaceAutoPtr/ReplaceAutoPtrActions.h @@ -25,8 +25,9 @@ class Transform; /// using declarations. class AutoPtrReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - AutoPtrReplacer(unsigned &AcceptedChanges, Transform &Owner) - : AcceptedChanges(AcceptedChanges), Owner(Owner) {} + AutoPtrReplacer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, const Transform &Owner) + : Replace(Replace), 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) @@ -62,8 +63,9 @@ private: const clang::SourceManager &SM); private: + clang::tooling::Replacements &Replace; unsigned &AcceptedChanges; - Transform &Owner; + const Transform &Owner; }; /// \brief The callback to be used to fix the ownership transfers of @@ -84,16 +86,18 @@ private: class OwnershipTransferFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - OwnershipTransferFixer(unsigned &AcceptedChanges, Transform &Owner) - : AcceptedChanges(AcceptedChanges), Owner(Owner) {} + OwnershipTransferFixer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, const Transform &Owner) + : Replace(Replace), 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; - Transform &Owner; + const 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 72f5ae077f25..ccf49d88c92e 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(const FileOverrides &InputStates, +int UseAutoTransform::apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) { ClangTool UseAutoTool(Database, SourcePaths); @@ -28,11 +28,10 @@ int UseAutoTransform::apply(const FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - ReplacementsVec Replaces; - IteratorReplacer ReplaceIterators(AcceptedChanges, Options().MaxRiskLevel, - /*Owner=*/ *this); - NewReplacer ReplaceNew(AcceptedChanges, Options().MaxRiskLevel, - /*Owner=*/ *this); + IteratorReplacer ReplaceIterators(getReplacements(), AcceptedChanges, + Options().MaxRiskLevel, /*Owner=*/ *this); + NewReplacer ReplaceNew(getReplacements(), 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 26b5e4496f69..71b8dd7dc956 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.cpp index 2a8d5c5935df..643de63069ea 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); - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto")); + Replace.insert(tooling::Replacement(SM, Range, "auto")); ++AcceptedChanges; } @@ -131,9 +131,8 @@ void NewReplacer::run(const MatchFinder::MatchResult &Result) { for (std::vector::iterator I = StarLocations.begin(), E = StarLocations.end(); I != E; ++I) { - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, *I, 1, "")); + Replace.insert(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 @@ -142,6 +141,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'. - Owner.addReplacementForCurrentTU(tooling::Replacement(SM, Range, "auto ")); + Replace.insert(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 0ddb0e0c5afc..403621803c3d 100644 --- a/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h +++ b/clang-tools-extra/cpp11-migrate/UseAuto/UseAutoActions.h @@ -25,32 +25,36 @@ class IteratorReplacer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - IteratorReplacer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner) - : AcceptedChanges(AcceptedChanges), Owner(Owner) {} + IteratorReplacer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, RiskLevel, const Transform &Owner) + : Replace(Replace), 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; - Transform &Owner; + const 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(unsigned &AcceptedChanges, RiskLevel, Transform &Owner) - : AcceptedChanges(AcceptedChanges), Owner(Owner) {} + NewReplacer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, + RiskLevel, const Transform &Owner) + : Replace(Replace), 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; - Transform &Owner; + const 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 23a8fd3a476f..e170801a0343 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(Transform &Owner, SourceManager &SM, +void ReplaceWithNullptr(tooling::Replacements &Replace, SourceManager &SM, SourceLocation StartLoc, SourceLocation EndLoc) { CharSourceRange Range(SourceRange(StartLoc, EndLoc), true); // Add a space if nullptr follows an alphanumeric character. This happens @@ -55,11 +55,9 @@ void ReplaceWithNullptr(Transform &Owner, SourceManager &SM, // parentheses and right beside a return statement. SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1); if (isAlphanumeric(*FullSourceLoc(PreviousLocation, SM).getCharacterData())) - Owner.addReplacementForCurrentTU( - tooling::Replacement(SM, Range, " nullptr")); + Replace.insert(tooling::Replacement(SM, Range, " nullptr")); else - Owner.addReplacementForCurrentTU( - tooling::Replacement(SM, Range, "nullptr")); + Replace.insert(tooling::Replacement(SM, Range, "nullptr")); } /// \brief Returns the name of the outermost macro. @@ -155,9 +153,10 @@ private: /// ambiguities. class CastSequenceVisitor : public RecursiveASTVisitor { public: - CastSequenceVisitor(ASTContext &Context, const UserMacroNames &UserNullMacros, - unsigned &AcceptedChanges, Transform &Owner) - : SM(Context.getSourceManager()), Context(Context), + CastSequenceVisitor(tooling::Replacements &R, ASTContext &Context, + const UserMacroNames &UserNullMacros, + unsigned &AcceptedChanges, const Transform &Owner) + : Replace(R), SM(Context.getSourceManager()), Context(Context), UserNullMacros(UserNullMacros), AcceptedChanges(AcceptedChanges), Owner(Owner), FirstSubExpr(0), PruneSubtree(false) {} @@ -197,7 +196,7 @@ public: FileLocEnd = SM.getFileLoc(EndLoc); if (isReplaceableRange(FileLocStart, FileLocEnd, SM, Owner) && allArgUsesValid(C)) { - ReplaceWithNullptr(Owner, SM, FileLocStart, FileLocEnd); + ReplaceWithNullptr(Replace, SM, FileLocStart, FileLocEnd); ++AcceptedChanges; } return skipSubTree(); @@ -221,7 +220,7 @@ public: if (!isReplaceableRange(StartLoc, EndLoc, SM, Owner)) { return skipSubTree(); } - ReplaceWithNullptr(Owner, SM, StartLoc, EndLoc); + ReplaceWithNullptr(Replace, SM, StartLoc, EndLoc); ++AcceptedChanges; return skipSubTree(); @@ -418,19 +417,21 @@ private: } private: + tooling::Replacements &Replace; SourceManager &SM; ASTContext &Context; const UserMacroNames &UserNullMacros; unsigned &AcceptedChanges; - Transform &Owner; + const Transform &Owner; Expr *FirstSubExpr; bool PruneSubtree; }; } // namespace -NullptrFixer::NullptrFixer(unsigned &AcceptedChanges, RiskLevel, - Transform &Owner) - : AcceptedChanges(AcceptedChanges), Owner(Owner) { +NullptrFixer::NullptrFixer(clang::tooling::Replacements &Replace, + unsigned &AcceptedChanges, RiskLevel, + const Transform &Owner) + : Replace(Replace), AcceptedChanges(AcceptedChanges), Owner(Owner) { if (!UserNullMacroNames.empty()) { llvm::StringRef S = UserNullMacroNames; S.split(UserNullMacros, ","); @@ -444,7 +445,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(*Result.Context, UserNullMacros, AcceptedChanges, - Owner); + CastSequenceVisitor Visitor(Replace, *Result.Context, UserNullMacros, + AcceptedChanges, Owner); Visitor.TraverseStmt(const_cast(NullCast)); } diff --git a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h index 02da6b76db04..f647d8e4d65b 100644 --- a/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h +++ b/clang-tools-extra/cpp11-migrate/UseNullptr/NullptrActions.h @@ -27,15 +27,17 @@ typedef llvm::SmallVector UserMacroNames; /// class NullptrFixer : public clang::ast_matchers::MatchFinder::MatchCallback { public: - NullptrFixer(unsigned &AcceptedChanges, RiskLevel, Transform &Owner); + NullptrFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges, + RiskLevel, const 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; - Transform &Owner; + const 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 e07ee6682eef..afeec4a10af2 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(const FileOverrides &InputStates, +int UseNullptrTransform::apply(FileOverrides &InputStates, const CompilationDatabase &Database, const std::vector &SourcePaths) { ClangTool UseNullptrTool(Database, SourcePaths); @@ -32,7 +32,8 @@ int UseNullptrTransform::apply(const FileOverrides &InputStates, unsigned AcceptedChanges = 0; MatchFinder Finder; - NullptrFixer Fixer(AcceptedChanges, Options().MaxRiskLevel, /*Owner=*/ *this); + NullptrFixer Fixer(getReplacements(), 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 ed90f9a5bbcd..873ffab07026 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(const FileOverrides &InputStates, + virtual int apply(FileOverrides &InputStates, const clang::tooling::CompilationDatabase &Database, const std::vector &SourcePaths) LLVM_OVERRIDE; }; diff --git a/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt b/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt index 8721b5e5c259..a40e0f3e31a0 100644 --- a/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt +++ b/clang-tools-extra/cpp11-migrate/tool/CMakeLists.txt @@ -34,7 +34,6 @@ 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 e75a4754881f..eaaec3c91deb 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp +++ b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp @@ -21,14 +21,9 @@ #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" @@ -127,12 +122,12 @@ static cl::opt EnableHeaderModifications( cl::location(GlobalOptions.EnableHeaderModifications), cl::init(false)); -static cl::opt -SerializeReplacements("serialize-replacements", - cl::Hidden, // Associated with -headers - cl::desc("Serialize translation unit replacements to " - "disk instead of changing files."), - cl::init(false)); +static cl::opt 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)); cl::opt SupportedCompilers( "for-compilers", cl::value_desc("string"), @@ -230,68 +225,6 @@ 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(*I); - } - return !Errors; -} - int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); Transforms TransformManager; @@ -347,15 +280,6 @@ int main(int argc, const char **argv) { TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions); - llvm::IntrusiveRefCntPtr DiagOpts( - new DiagnosticOptions()); - DiagnosticsEngine Diagnostics( - llvm::IntrusiveRefCntPtr(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"; @@ -365,22 +289,21 @@ int main(int argc, const char **argv) { return 1; } - // 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 " + if (std::distance(TransformManager.begin(), TransformManager.end()) > 1 && + YAMLOnly) { + llvm::errs() << "Header change description files requested for multiple " "transforms.\nChanges from only one transform can be " - "serialized.\n"; + "recorded in a change description file.\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(ChangesReformatter); + FileOverrides FileStates(TrackReplacements); SourcePerfData PerfData; - FileOverrides FileStates; + // Apply transforms. for (Transforms::const_iterator I = TransformManager.begin(), E = TransformManager.end(); I != E; ++I) { @@ -403,67 +326,79 @@ int main(int argc, const char **argv) { } llvm::outs() << "\n"; } - - // 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; - } - - // 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; - } - - // 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); + // 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); + } 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(); + } + + 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( + 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(); + } + } + } + // 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 82abe8ab569a..f1780265aa9a 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 clangReplace.a clangTooling.a clangFrontend.a \ +USEDLIBS = migrateCore.a clangFormat.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)/.. -I$(PROJ_SRC_DIR)/../../clang-replace/include +CPP.Flags += -I$(PROJ_SRC_DIR)/.. # 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 diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/Inputs/no_yaml.h b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/Inputs/no_yaml.h deleted file mode 100644 index 8e09412c452b..000000000000 --- a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/Inputs/no_yaml.h +++ /dev/null @@ -1,8 +0,0 @@ -void update(int (&arr)[10]) { - int val = 1; - for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) { - arr[i] = val++; - // CHECK: for (auto & elem : arr) { - // CHECK-NEXT: elem = val++; - } -} diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main_expected.yaml b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml similarity index 87% rename from clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main_expected.yaml rename to clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml index 8702bc17245c..4b1258cae4ae 100644 --- a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main_expected.yaml +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common.h.yaml @@ -1,12 +1,12 @@ --- MainSourceFile: "$(path)/main.cpp" Replacements: - - FilePath: "$(path)/common.h" - Offset: 506 - Length: 2 - ReplacementText: "elem" - FilePath: "$(path)/common.h" Offset: 432 Length: 61 ReplacementText: "(auto & elem : C)" + - FilePath: "$(path)/common.h" + Offset: 506 + Length: 2 + ReplacementText: "elem" ... diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common_expected.yaml b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common_expected.yaml deleted file mode 100644 index 67eb1fb91048..000000000000 --- a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/common_expected.yaml +++ /dev/null @@ -1,20 +0,0 @@ ---- -MainSourceFile: "$(path)/common.cpp" -Replacements: - - FilePath: "$(path)/common.h" - Offset: 506 - Length: 2 - ReplacementText: "elem" - - FilePath: "$(path)/common.h" - Offset: 432 - Length: 61 - ReplacementText: "(auto & elem : C)" - - FilePath: "$(path)/common.cpp" - Offset: 289 - Length: 2 - ReplacementText: "elem" - - FilePath: "$(path)/common.cpp" - Offset: 206 - Length: 63 - ReplacementText: "(auto & elem : C1)" -... diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp index 54cbc92728e2..d59417cf0d69 100644 --- a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp +++ b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/main.cpp @@ -1,30 +1,44 @@ // The following block tests the following: -// - Only 1 file is generated per translation unit +// - Only 1 file is generated per translation unit and header file // - Replacements are written in YAML that matches the expected YAML file -// The test is run in %T/SerializeTest so it's easy to create a clean test -// directory. -// -// RUN: rm -rf %T/SerializeTest -// RUN: mkdir -p %T/SerializeTest -// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %T/SerializeTest -// RUN: cpp11-migrate -loop-convert -headers -serialize-replacements -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp -- -// Check that only 1 file is generated per translation unit -// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=MAIN_CPP -// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=COMMON_CPP +// RUN: rm -rf %t/Test +// RUN: mkdir -p %t/Test +// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test +// RUN: cpp11-migrate -loop-convert -headers -yaml-only -include=%t/Test %t/Test/main.cpp %t/Test/common.cpp -- +// Check that only 1 file is generated per translation unit and header file. +// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=MAIN_CPP +// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=COMMON_CPP +// RUN: cp %S/common.h.yaml %t/Test/main.cpp_common.h.yaml // We need to put the build path to the expected YAML file to diff against the generated one. -// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' %S/main_expected.yaml > %T/SerializeTest/main_expected.yaml -// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/main.cpp_*.yaml -// RUN: diff -b %T/SerializeTest/main_expected.yaml %T/SerializeTest/main.cpp_*.yaml -// RUN: sed -e 's#$(path)#%/T/SerializeTest#g' %S/common_expected.yaml > %T/SerializeTest/common_expected.yaml -// RUN: sed -i -e 's#\\#/#g' %T/SerializeTest/common.cpp_*.yaml -// RUN: diff -b %T/SerializeTest/common_expected.yaml %T/SerializeTest/common.cpp_*.yaml +// RUN: sed -e 's#$(path)#%/t/Test#g' %S/common.h.yaml > %t/Test/main.cpp_common.h.yaml +// RUN: sed -i -e 's#\\#/#g' %t/Test/main.cpp_common.h_*.yaml +// RUN: diff -b %t/Test/main.cpp_common.h.yaml %t/Test/main.cpp_common.h_*.yaml +// RUN: sed -e 's#$(path)#%/t/Test#g' -e 's#main.cpp"#common.cpp"#g' %S/common.h.yaml > %t/Test/common.cpp_common.h.yaml +// RUN: sed -i -e 's#\\#/#g' %t/Test/common.cpp_common.h_*.yaml +// RUN: diff -b %t/Test/common.cpp_common.h.yaml %t/Test/common.cpp_common.h_*.yaml // -// The following are for FileCheck when used on output of 'ls'. See above. -// MAIN_CPP: {{^main.cpp_.*.yaml$}} -// MAIN_CPP-NOT: {{main.cpp_.*.yaml}} +// The following block tests the following: +// - YAML files are written only when -headers is used +// RUN: rm -rf %t/Test +// RUN: mkdir -p %t/Test +// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %t/Test +// RUN: cpp11-migrate -loop-convert -headers -yaml-only -include=%t/Test %t/Test/main.cpp -- +// RUN: cpp11-migrate -loop-convert %t/Test/common.cpp -- +// Check that only one YAML file is generated from main.cpp and common.h and not from common.cpp and common.h since -header is not specified +// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=MAIN_CPP +// RUN: ls -1 %t/Test | FileCheck %s --check-prefix=NO_COMMON +// We need to put the build path to the expected YAML file to diff against the generated one. +// RUN: sed -e 's#$(path)#%/t/Test#g' %S/common.h.yaml > %t/Test/main.cpp_common.h.yaml +// RUN: sed -i -e 's#\\#/#g' %t/Test/main.cpp_common.h_*.yaml +// RUN: diff -b %t/Test/main.cpp_common.h.yaml %t/Test/main.cpp_common.h_*.yaml // -// COMMON_CPP: {{^common.cpp_.*.yaml$}} -// COMMON_CPP-NOT: {{common.cpp_.*.yaml}} +// MAIN_CPP: {{^main.cpp_common.h_.*.yaml$}} +// MAIN_CPP-NOT: {{main.cpp_common.h_.*.yaml}} +// +// COMMON_CPP: {{^common.cpp_common.h_.*.yaml$}} +// COMMON_CPP-NOT: {{common.cpp_common.h_.*.yaml}} +// +// NO_COMMON-NOT: {{common.cpp_common.h_.*.yaml}} #include "common.h" diff --git a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/no_yaml.cpp b/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/no_yaml.cpp deleted file mode 100644 index 880cc1f5a705..000000000000 --- a/clang-tools-extra/test/cpp11-migrate/HeaderReplacements/no_yaml.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Ensure that if -serialize-replacements is not provided, no serialized -// replacement files should be generated and the changes are made directly. -// -// RUN: mkdir -p %T/Inputs -// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp -// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/no_yaml.h > %T/Inputs/no_yaml.h -// RUN: cpp11-migrate -loop-convert %t.cpp -headers -include=%T/Inputs -- -I %T/Inputs/no_yaml.h -// RUN: FileCheck --input-file=%t.cpp %s -// RUN: FileCheck --input-file=%T/Inputs/no_yaml.h %S/Inputs/no_yaml.h -// RUN: ls -1 %T | FileCheck %s --check-prefix=NO_YAML -// -// NO_YAML-NOT: {{no_yaml.cpp_.*.yaml}} -#include "Inputs/no_yaml.h" - -void func() { - int arr[10]; - for (unsigned i = 0; i < sizeof(arr)/sizeof(int); ++i) { - arr[i] = 0; - // CHECK: for (auto & elem : arr) { - // CHECK-NEXT: elem = 0; - } - - update(arr); -} diff --git a/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt b/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt index 228de69b5c72..fcf678d34906 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt +++ b/clang-tools-extra/unittests/cpp11-migrate/CMakeLists.txt @@ -1,31 +1,26 @@ -set(LLVM_LINK_COMPONENTS - support - ) - -get_filename_component(CPP11_MIGRATE_SOURCE_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp11-migrate REALPATH) -get_filename_component(ClangReplaceLocation - "${CMAKE_CURRENT_SOURCE_DIR}/../../clang-replace/include" REALPATH) -include_directories( - ${CPP11_MIGRATE_SOURCE_DIR} - ${ClangReplaceLocation} - ) - -add_extra_unittest(Cpp11MigrateTests - FileOverridesTest.cpp - ReformattingTest.cpp - IncludeExcludeTest.cpp - PerfSupportTest.cpp - TransformTest.cpp - UniqueHeaderNameTest.cpp - IncludeDirectivesTest.cpp - ) - -target_link_libraries(Cpp11MigrateTests - migrateCore - clangFormat - clangTooling - clangBasic - clangASTMatchers - clangRewriteFrontend - ) +set(LLVM_LINK_COMPONENTS + support + ) + +get_filename_component(CPP11_MIGRATE_SOURCE_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/../../cpp11-migrate REALPATH) +include_directories(${CPP11_MIGRATE_SOURCE_DIR}) + +add_extra_unittest(Cpp11MigrateTests + FileOverridesTest.cpp + ReformattingTest.cpp + IncludeExcludeTest.cpp + PerfSupportTest.cpp + TransformTest.cpp + UniqueHeaderNameTest.cpp + IncludeDirectivesTest.cpp + ) + +target_link_libraries(Cpp11MigrateTests + migrateCore + clangFormat + clangTooling + clangBasic + clangASTMatchers + clangRewriteFrontend + ) diff --git a/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp index 5404aeb579d4..fc54474af840 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/FileOverridesTest.cpp @@ -8,34 +8,56 @@ //===----------------------------------------------------------------------===// #include "Core/FileOverrides.h" -#include "Core/Refactoring.h" #include "gtest/gtest.h" #include "VirtualFileHelper.h" -#include "clang/Rewrite/Core/Rewriter.h" using namespace clang; using namespace clang::tooling; -static Replacement makeReplacement(unsigned Offset, unsigned Length, - unsigned ReplacementLength, - llvm::StringRef FilePath) { - return Replacement(FilePath, Offset, Length, - std::string(ReplacementLength, '~')); +TEST(SourceOverridesTest, Interface) { + llvm::StringRef FileName = ""; + VirtualFileHelper VFHelper; + VFHelper.mapFile( + FileName, + "std::vector::const_iterator long_type =\n" + " vec.begin();\n"); + SourceOverrides Overrides(FileName, /*TrackFileChanges=*/false); + + EXPECT_EQ(FileName, Overrides.getMainFileName()); + EXPECT_FALSE(Overrides.isSourceOverriden()); + EXPECT_FALSE(Overrides.isTrackingFileChanges()); + + Replacements Replaces; + unsigned ReplacementLength = + strlen("std::vector::const_iterator"); + Replaces.insert( + Replacement(FileName, 0, ReplacementLength, "auto")); + Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager()); + EXPECT_TRUE(Overrides.isSourceOverriden()); + + std::string ExpectedContent = "auto long_type =\n" + " vec.begin();\n"; + EXPECT_EQ(ExpectedContent, Overrides.getMainFileContent()); +} + +namespace { +Replacement makeReplacement(unsigned Offset, unsigned Length, + unsigned ReplacementLength) { + return Replacement("", Offset, Length, std::string(ReplacementLength, '~')); } // generate a set of replacements containing one element -static ReplacementsVec makeReplacements(unsigned Offset, unsigned Length, - unsigned ReplacementLength, - llvm::StringRef FilePath = "~") { - ReplacementsVec Replaces; - Replaces.push_back( - makeReplacement(Offset, Length, ReplacementLength, FilePath)); +Replacements makeReplacements(unsigned Offset, unsigned Length, + unsigned ReplacementLength) { + Replacements Replaces; + Replaces.insert(makeReplacement(Offset, Length, ReplacementLength)); return Replaces; } -static bool equalRanges(Range A, Range B) { +bool equalRanges(Range A, Range B) { return A.getOffset() == B.getOffset() && A.getLength() == B.getLength(); } +} // end anonymous namespace TEST(ChangedRangesTest, adjustChangedRangesShrink) { ChangedRanges Changes; @@ -117,71 +139,3 @@ TEST(ChangedRangesTest, adjustChangedRangesRangeResized) { EXPECT_TRUE( std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges)); } - -TEST(FileOverridesTest, applyOverrides) { - - // Set up initial state - VirtualFileHelper VFHelper; - - SmallString<128> fileAPath("fileA.cpp"); - ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath)); - SmallString<128> fileBPath("fileB.cpp"); - ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath)); - VFHelper.mapFile(fileAPath, "Content A"); - VFHelper.mapFile(fileBPath, "Content B"); - SourceManager &SM = VFHelper.getNewSourceManager(); - - // Fill a Rewriter with changes - Rewriter Rewrites(SM, LangOptions()); - ReplacementsVec R(1, Replacement(fileAPath, 0, 7, "Stuff")); - ASSERT_TRUE(applyAllReplacements(R, Rewrites)); - - FileOverrides Overrides; - Overrides.updateState(Rewrites); - - const FileOverrides::FileStateMap &State = Overrides.getState(); - - // Ensure state updated - ASSERT_TRUE(State.end() == State.find(fileBPath)); - ASSERT_TRUE(State.begin() == State.find(fileAPath)); - ASSERT_EQ("Stuff A", State.begin()->getValue()); - - Overrides.applyOverrides(SM); - - const FileEntry *EntryA = SM.getFileManager().getFile(fileAPath); - FileID IdA = SM.translateFile(EntryA); - ASSERT_FALSE(IdA.isInvalid()); - - // Ensure the contents of the buffer matches what we'd expect. - const llvm::MemoryBuffer *BufferA = SM.getBuffer(IdA); - ASSERT_FALSE(0 == BufferA); - ASSERT_EQ("Stuff A", BufferA->getBuffer()); -} - -TEST(FileOverridesTest, adjustChangedRanges) { - SmallString<128> fileAPath("fileA.cpp"); - ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath)); - SmallString<128> fileBPath("fileB.cpp"); - ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath)); - - replace::FileToReplacementsMap GroupedReplacements; - GroupedReplacements[fileAPath] = makeReplacements(0, 5, 4, fileAPath); - GroupedReplacements[fileBPath] = makeReplacements(10, 0, 6, fileBPath); - - FileOverrides Overrides; - - const FileOverrides::ChangeMap &Map = Overrides.getChangedRanges(); - - ASSERT_TRUE(Map.empty()); - - Overrides.adjustChangedRanges(GroupedReplacements); - - ASSERT_TRUE(Map.end() != Map.find(fileAPath)); - ASSERT_TRUE(Map.end() != Map.find(fileBPath)); - const Range &RA = *Map.find(fileAPath)->second.begin(); - EXPECT_EQ(0u, RA.getOffset()); - EXPECT_EQ(4u, RA.getLength()); - const Range &RB = *Map.find(fileBPath)->second.begin(); - EXPECT_EQ(10u, RB.getOffset()); - EXPECT_EQ(6u, RB.getLength()); -} diff --git a/clang-tools-extra/unittests/cpp11-migrate/Makefile b/clang-tools-extra/unittests/cpp11-migrate/Makefile index 2f4a59afd070..270c523798b1 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/Makefile +++ b/clang-tools-extra/unittests/cpp11-migrate/Makefile @@ -13,7 +13,7 @@ include $(CLANG_LEVEL)/../../Makefile.config TESTNAME = Cpp11MigrateTests LINK_COMPONENTS := asmparser bitreader support MC MCParser option \ TransformUtils -USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFrontend.a \ +USEDLIBS = migrateCore.a clangFormat.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 \ @@ -21,5 +21,5 @@ USEDLIBS = migrateCore.a clangFormat.a clangReplace.a clangTooling.a clangFronte include $(CLANG_LEVEL)/Makefile MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1 -CPP.Flags += -I$(PROJ_SRC_DIR)/../../cpp11-migrate -I$(PROJ_SRC_DIR)/../../clang-replace/include +CPP.Flags += -I$(PROJ_SRC_DIR)/../../cpp11-migrate include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/clang-tools-extra/unittests/cpp11-migrate/PerfSupportTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/PerfSupportTest.cpp index 81235481bff0..bbfb08e217c7 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/PerfSupportTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/PerfSupportTest.cpp @@ -18,7 +18,7 @@ public: TransformA(const TransformOptions &Options) : Transform("TransformA", Options) {} - virtual int apply(const FileOverrides &, + virtual int apply(FileOverrides &, const tooling::CompilationDatabase &, const std::vector &) { return 0; @@ -34,7 +34,7 @@ public: TransformB(const TransformOptions &Options) : Transform("TransformB", Options) {} - virtual int apply(const FileOverrides &, + virtual int apply(FileOverrides &, const tooling::CompilationDatabase &, const std::vector &) { return 0; diff --git a/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp index b4b9a3654783..fcde6b81db41 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/ReformattingTest.cpp @@ -9,7 +9,6 @@ #include "Core/Reformatting.h" #include "Core/FileOverrides.h" -#include "Core/Refactoring.h" #include "gtest/gtest.h" #include "VirtualFileHelper.h" @@ -20,9 +19,9 @@ namespace { // convenience function to create a ChangedRanges containing one Range ChangedRanges makeChangedRanges(unsigned Offset, unsigned Length) { ChangedRanges Changes; - ReplacementsVec Replaces; + Replacements Replaces; - Replaces.push_back(Replacement("", Offset, 0, std::string(Length, '~'))); + Replaces.insert(Replacement("", Offset, 0, std::string(Length, '~'))); Changes.adjustChangedRanges(Replaces); return Changes; } @@ -36,20 +35,16 @@ TEST(Reformatter, SingleReformat) { Reformatter ChangesReformatter(format::getLLVMStyle()); ChangedRanges Changes = makeChangedRanges(0, 6); - tooling::ReplacementsVec Replaces; - ChangesReformatter.reformatSingleFile( - FileName, Changes, VFHelper.getNewSourceManager(), Replaces); + tooling::Replacements Replaces = ChangesReformatter.reformatSingleFile( + FileName, Changes, VFHelper.getNewSourceManager()); - // We expect the code above to reformatted like so: - // - // int a; - // int b; - // - // This test is slightly fragile since there's more than one Replacement that - // results in the above change. However, testing the result of applying the - // replacement is more trouble than it's worth in this context. - ASSERT_EQ(1u, Replaces.size()); - EXPECT_EQ(3u, Replaces[0].getOffset()); - EXPECT_EQ(2u, Replaces[0].getLength()); - EXPECT_EQ(" ", Replaces[0].getReplacementText()); + SourceOverrides Overrides(FileName, /*TrackChanges=*/false); + Overrides.applyReplacements(Replaces, VFHelper.getNewSourceManager()); + + std::string Expected, Result; + + Expected = "int a;\n" + "int b;\n"; + Result = Overrides.getMainFileContent(); + EXPECT_EQ(Expected, Result); } diff --git a/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp index 75397bf7760a..b8efc9b5840b 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/TransformTest.cpp @@ -26,7 +26,7 @@ public: DummyTransform(llvm::StringRef Name, const TransformOptions &Options) : Transform(Name, Options) {} - virtual int apply(const FileOverrides &, + virtual int apply(FileOverrides &, const tooling::CompilationDatabase &, const std::vector &) { return 0; } @@ -161,7 +161,7 @@ TEST(Transform, Timings) { // Transform's handle* functions require FileOverrides to be set, even if // there aren't any. - FileOverrides Overrides; + FileOverrides Overrides(/*TrackFileChanges=*/false); T.setOverrides(Overrides); Tool.run(clang::tooling::newFrontendActionFactory(&Factory, &Callbacks)); diff --git a/clang-tools-extra/unittests/cpp11-migrate/UniqueHeaderNameTest.cpp b/clang-tools-extra/unittests/cpp11-migrate/UniqueHeaderNameTest.cpp index a2d70e03baa9..0323222c03c5 100644 --- a/clang-tools-extra/unittests/cpp11-migrate/UniqueHeaderNameTest.cpp +++ b/clang-tools-extra/unittests/cpp11-migrate/UniqueHeaderNameTest.cpp @@ -28,31 +28,34 @@ TEST(UniqueHeaderName, testUniqueHeaderName) { append(SourceFile, "project/lib/feature.cpp"); native(SourceFile.str().str(), SourceFile); - llvm::SmallString<128> FullActualPath; + llvm::SmallString<128> HeaderFile(TmpDir); + append(HeaderFile, "project/include/feature.h"); + native(HeaderFile.str().str(), HeaderFile); + + llvm::SmallString<128> ExpectedName("^feature.cpp_feature.h_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}.yaml$"); + + llvm::SmallString<128> ActualName; llvm::SmallString<128> Error; bool Result = - generateReplacementsFileName(SourceFile, FullActualPath, Error); + generateReplacementsFileName(SourceFile, HeaderFile, ActualName, Error); ASSERT_TRUE(Result); EXPECT_TRUE(Error.empty()); // We need to check the directory name and filename separately since on // Windows, the path separator is '\' which is a regex escape character. - llvm::SmallString<128> ExpectedPath = - llvm::sys::path::parent_path(SourceFile); - llvm::SmallString<128> ActualPath = - llvm::sys::path::parent_path(FullActualPath); - llvm::SmallString<128> ActualName = - llvm::sys::path::filename(FullActualPath); + llvm::SmallString<128> ExpectedHeaderPath = + llvm::sys::path::parent_path(HeaderFile); + llvm::SmallString<128> ActualHeaderPath = + llvm::sys::path::parent_path(ActualName); + llvm::SmallString<128> ActualHeaderName = + llvm::sys::path::filename(ActualName); - EXPECT_STREQ(ExpectedPath.c_str(), ActualPath.c_str()); + EXPECT_STREQ(ExpectedHeaderPath.c_str(), ActualHeaderPath.c_str()); - llvm::StringRef ExpectedName = - "^feature.cpp_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[" - "0-9a-f]{2}_[0-9a-f]{2}.yaml$"; llvm::Regex R(ExpectedName); - ASSERT_TRUE(R.match(ActualName)) - << "ExpectedName: " << ExpectedName.data() + ASSERT_TRUE(R.match(ActualHeaderName)) + << "ExpectedName: " << ExpectedName.c_str() << "\nActualName: " << ActualName.c_str(); ASSERT_TRUE(Error.empty()) << "Error: " << Error.c_str(); }