I submitted a patch that will hopefully fix this problem: r187153. > -----Original Message----- > From: Galina Kistanova [mailto:[email protected]] > Sent: Wednesday, July 24, 2013 5:14 PM > To: Vane, Edwin > Cc: llvm cfe > Subject: Re: [clang-tools-extra] r186938 - cp11-migrate: Integration with > LibFormat > > Hello Edwin, > > >Added: > > clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.cpp > > clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.h > > clang-tools-extra/trunk/test/cpp11-migrate/Core/Reformatting.cpp > > clang-tools-extra/trunk/unittests/cpp11-migrate/ReformattingTest.cpp > > cpp11-migrate/Core/Reformatting.cpp fails on one of the builders: > http://lab.llvm.org:8011/builders/clang-X86_64-freebsd > Please have a look at this? > > Thanks > > Galina > > > > > On Tue, Jul 23, 2013 at 5:50 AM, Edwin Vane <[email protected]> wrote: > > > Author: revane > Date: Tue Jul 23 07:50:03 2013 > New Revision: 186938 > > URL: http://llvm.org/viewvc/llvm-project?rev=186938&view=rev > Log: > cp11-migrate: Integration with LibFormat > > Adding a feature to optionally reformat code changed by the migrator. > Like > LibFormat, can choose between built-in styles (LLVM, Mozilla, Google, > Chromium) > or use a YAML-format config file. > > Now with no dependency on iostream by the Reformatting.cpp LIT test. > > Author: Guillaume Papin <[email protected]> > > > Added: > clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.cpp > clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.h > clang-tools-extra/trunk/test/cpp11-migrate/Core/Reformatting.cpp > clang-tools-extra/trunk/unittests/cpp11- > migrate/ReformattingTest.cpp > Modified: > clang-tools-extra/trunk/cpp11-migrate/Core/CMakeLists.txt > clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.cpp > clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.h > clang-tools-extra/trunk/cpp11-migrate/tool/Cpp11Migrate.cpp > clang-tools-extra/trunk/cpp11-migrate/tool/Makefile > clang-tools-extra/trunk/docs/MigratorUsage.rst > clang-tools-extra/trunk/unittests/cpp11-migrate/CMakeLists.txt > clang-tools-extra/trunk/unittests/cpp11- > migrate/FileOverridesTest.cpp > clang-tools-extra/trunk/unittests/cpp11-migrate/Makefile > clang-tools-extra/trunk/unittests/cpp11-migrate/TransformTest.cpp > > Modified: clang-tools-extra/trunk/cpp11-migrate/Core/CMakeLists.txt > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11- > migrate/Core/CMakeLists.txt?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/Core/CMakeLists.txt > (original) > +++ clang-tools-extra/trunk/cpp11-migrate/Core/CMakeLists.txt Tue Jul > 23 07:50:03 2013 > @@ -7,9 +7,12 @@ add_clang_library(migrateCore > Transform.cpp > IncludeExcludeInfo.cpp > PerfSupport.cpp > + Reformatting.cpp > ) > target_link_libraries(migrateCore > + clangFormat > clangTooling > clangBasic > clangASTMatchers > + clangRewriteFrontend > ) > > Modified: clang-tools-extra/trunk/cpp11- > migrate/Core/FileOverrides.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11- > migrate/Core/FileOverrides.cpp?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.cpp > (original) > +++ clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.cpp Tue > Jul 23 07:50:03 2013 > @@ -17,8 +17,6 @@ > #include "clang/Basic/Diagnostic.h" > #include "clang/Basic/DiagnosticOptions.h" > #include "clang/Basic/SourceManager.h" > -#include "clang/Format/Format.h" > -#include "clang/Lex/Lexer.h" > #include "clang/Rewrite/Core/Rewriter.h" > #include "clang/Tooling/Tooling.h" > #include "llvm/Support/FileSystem.h" > @@ -29,10 +27,11 @@ > using namespace clang; > using namespace clang::tooling; > > -SourceOverrides::SourceOverrides(llvm::StringRef MainFileName) > - : MainFileName(MainFileName) {} > +SourceOverrides::SourceOverrides(llvm::StringRef MainFileName, > + bool TrackChanges) > + : MainFileName(MainFileName), TrackChanges(TrackChanges) {} > > -void SourceOverrides::applyReplacements(tooling::Replacements > &Replaces) { > +void SourceOverrides::applyReplacements(Replacements &Replaces) { > llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( > new DiagnosticOptions()); > DiagnosticsEngine Diagnostics( > @@ -57,6 +56,8 @@ void SourceOverrides::applyReplacements( > llvm::errs() << "error: failed to apply some replacements."; > > applyRewrites(Rewrites); > + if (TrackChanges) > + adjustChangedRanges(Replaces); > } > > void SourceOverrides::applyRewrites(Rewriter &Rewrites) { > @@ -96,6 +97,30 @@ void SourceOverrides::applyRewrites(Rewr > } > } > > +void SourceOverrides::adjustChangedRanges(const Replacements > &Replaces) { > + // Start by grouping replacements by file name > + Replacements MainFileReplaces; > + llvm::StringMap<Replacements> HeadersReplaces; > + > + for (Replacements::iterator I = Replaces.begin(), E = > Replaces.end(); I > != E; > + ++I) { > + llvm::StringRef ReplacementFileName = I->getFilePath(); > + > + if (ReplacementFileName == MainFileName) > + MainFileReplaces.insert(*I); > + else > + HeadersReplaces[ReplacementFileName].insert(*I); > + } > + > + // Then adjust the changed ranges for each individual file > + MainFileChanges.adjustChangedRanges(Replaces); > + for (llvm::StringMap<Replacements>::iterator I = > HeadersReplaces.begin(), > + E = > HeadersReplaces.end(); > + I != E; ++I) { > + Headers[I->getKey()].Changes.adjustChangedRanges(I->getValue()); > + } > +} > + > void SourceOverrides::applyOverrides(SourceManager &SM) const { > FileManager &FM = SM.getFileManager(); > > @@ -154,6 +179,109 @@ SourceOverrides &FileOverrides::getOrCre > SourceOverrides *&Override = Overrides[Filename]; > > if (Override == NULL) > - Override = new SourceOverrides(Filename); > + Override = new SourceOverrides(Filename, TrackChanges); > return *Override; > } > + > +namespace { > + > +/// \brief Comparator to be able to order tooling::Range based on > their offset. > +bool rangeLess(clang::tooling::Range A, clang::tooling::Range B) { > + if (A.getOffset() == B.getOffset()) > + return A.getLength() < B.getLength(); > + return A.getOffset() < B.getOffset(); > +} > + > +/// \brief Functor that returns the given range without its overlaps > with > the > +/// replacement given in the constructor. > +struct RangeReplacedAdjuster { > + RangeReplacedAdjuster(const tooling::Replacement &Replace) > + : Replace(Replace.getOffset(), Replace.getLength()), > + ReplaceNewSize(Replace.getReplacementText().size()) {} > + > + tooling::Range operator()(clang::tooling::Range Range) const { > + if (!Range.overlapsWith(Replace)) > + return Range; > + // range inside replacement -> make the range length null > + if (Replace.contains(Range)) > + return tooling::Range(Range.getOffset(), 0); > + // replacement inside range -> resize the range > + if (Range.contains(Replace)) { > + int Difference = ReplaceNewSize - Replace.getLength(); > + return tooling::Range(Range.getOffset(), Range.getLength() + > Difference); > + } > + // beginning of the range replaced -> truncate range beginning > + if (Range.getOffset() > Replace.getOffset()) { > + unsigned ReplaceEnd = Replace.getOffset() + Replace.getLength(); > + unsigned RangeEnd = Range.getOffset() + Range.getLength(); > + return tooling::Range(ReplaceEnd, RangeEnd - ReplaceEnd); > + } > + // end of the range replaced -> truncate range end > + if (Range.getOffset() < Replace.getOffset()) > + return tooling::Range(Range.getOffset(), > + Replace.getOffset() - Range.getOffset()); > + llvm_unreachable("conditions not handled properly"); > + } > + > + const tooling::Range Replace; > + const unsigned ReplaceNewSize; > +}; > + > +} // end anonymous namespace > + > +void ChangedRanges::adjustChangedRanges(const > tooling::Replacements &Replaces) { > + // first adjust existing ranges in case they overlap with the > replacements > + 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(), > + RangeReplacedAdjuster(Replace)); > + } > + > + // then shift existing ranges to reflect the new positions > + for (RangeVec::iterator I = Ranges.begin(), E = Ranges.end(); I != E; > ++I) { > + unsigned ShiftedOffset = > + tooling::shiftedCodePosition(Replaces, I->getOffset()); > + *I = tooling::Range(ShiftedOffset, I->getLength()); > + } > + > + // then generate the new ranges from the replacements > + 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(); > + > + Ranges.push_back(tooling::Range(Offset, Length)); > + } > + > + // cleanups unecessary ranges to finish > + coalesceRanges(); > +} > + > +void ChangedRanges::coalesceRanges() { > + // sort the ranges by offset and then for each group of > adjacent/overlapping > + // ranges the first one in the group is extended to cover the whole > group. > + std::sort(Ranges.begin(), Ranges.end(), &rangeLess); > + RangeVec::iterator FirstInGroup = Ranges.begin(); > + assert(!Ranges.empty() && "unexpected empty vector"); > + for (RangeVec::iterator I = Ranges.begin() + 1, E = Ranges.end(); I > != E; > + ++I) { > + unsigned GroupEnd = FirstInGroup->getOffset() + FirstInGroup- > >getLength(); > + > + // no contact > + if (I->getOffset() > GroupEnd) > + FirstInGroup = I; > + else { > + unsigned GrpBegin = FirstInGroup->getOffset(); > + unsigned GrpEnd = std::max(GroupEnd, I->getOffset() + I- > >getLength()); > + *FirstInGroup = tooling::Range(GrpBegin, GrpEnd - GrpBegin); > + } > + } > + > + // remove the ranges that are covered by the first member of the > group > + Ranges.erase(std::unique(Ranges.begin(), Ranges.end(), > + std::mem_fun_ref(&Range::contains)), > + Ranges.end()); > +} > > Modified: clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.h > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11- > migrate/Core/FileOverrides.h?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.h > (original) > +++ clang-tools-extra/trunk/cpp11-migrate/Core/FileOverrides.h Tue Jul > 23 07:50:03 2013 > @@ -29,6 +29,34 @@ class SourceManager; > class Rewriter; > } // namespace clang > > +/// \brief Class encapsulating a list of \c tooling::Range with some > +/// convenience methods. > +/// > +/// The ranges stored are used to keep track of the overriden parts of > a > file. > +class ChangedRanges { > + typedef std::vector<clang::tooling::Range> RangeVec; > + > +public: > + typedef RangeVec::const_iterator const_iterator; > + > + /// \brief Create new ranges from the replacements and adjust > existing one > + /// to remove replaced parts. > + /// > + /// Note that all replacements should come from the same file. > + 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(); > + > + RangeVec Ranges; > +}; > + > /// \brief Container for storing override information for a single > headers. > struct HeaderOverride { > HeaderOverride() {} > @@ -36,6 +64,7 @@ struct HeaderOverride { > > std::string FileName; > std::string FileOverride; > + ChangedRanges Changes; > }; > > /// \brief Container mapping header file names to override information. > @@ -46,12 +75,18 @@ typedef llvm::StringMap<HeaderOverride> > /// which changes have been made. > class SourceOverrides { > public: > - SourceOverrides(llvm::StringRef MainFileName); > + 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. > @@ -87,8 +122,14 @@ private: > /// 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 std::string MainFileName; > std::string MainFileOverride; > + const bool TrackChanges; > + ChangedRanges MainFileChanges; > HeaderOverrides Headers; > }; > > @@ -98,7 +139,11 @@ public: > typedef llvm::StringMap<SourceOverrides *> SourceOverridesMap; > typedef SourceOverridesMap::const_iterator const_iterator; > > - FileOverrides() {} > + /// \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 { > @@ -120,6 +165,7 @@ private: > FileOverrides &operator=(const FileOverrides &) > LLVM_DELETED_FUNCTION; > > SourceOverridesMap Overrides; > + const bool TrackChanges; > }; > > /// \brief Generate a unique filename to store the replacements. > > Added: clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11-migrate/Core/Reformatting.cpp?rev=186938&view=auto > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.cpp > (added) > +++ clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.cpp Tue > Jul 23 07:50:03 2013 > @@ -0,0 +1,76 @@ > +//===-- Core/Reformatting.cpp - LibFormat integration > ------------------- > --===// > +// > +// 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 provides the LibFormat integration used to > reformat > +/// migrated code. > +/// > > +//===----------------------------------------------------------------------===// > + > +#include "Core/Reformatting.h" > +#include "Core/FileOverrides.h" > +#include "clang/Basic/Diagnostic.h" > +#include "clang/Basic/DiagnosticOptions.h" > +#include "clang/Basic/SourceManager.h" > +#include "clang/Lex/Lexer.h" > + > +using namespace clang; > + > +void Reformatter::reformatChanges(SourceOverrides &Overrides) { > + llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( > + new DiagnosticOptions()); > + DiagnosticsEngine Diagnostics( > + llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), > + DiagOpts.getPtr()); > + FileManager Files((FileSystemOptions())); > + SourceManager SM(Diagnostics, Files); > + > + reformatChanges(Overrides, SM); > +} > + > +void Reformatter::reformatChanges(SourceOverrides &Overrides, > + clang::SourceManager &SM) { > + tooling::Replacements Replaces; > + Overrides.applyOverrides(SM); > + if (Overrides.isSourceOverriden()) > + Replaces = reformatSingleFile(Overrides.getMainFileName(), > + Overrides.getChangedRanges(), SM); > + > + for (HeaderOverrides::const_iterator I = Overrides.headers_begin(), > + E = Overrides.headers_end(); > + I != E; ++I) { > + const HeaderOverride &Header = I->getValue(); > + const tooling::Replacements &HeaderReplaces = > + reformatSingleFile(Header.FileName, Header.Changes, 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"); > + > + FileID ID = SM.translateFile(Entry); > + if (ID.isInvalid()) > + ID = SM.createFileID(Entry, SourceLocation(), > clang::SrcMgr::C_User); > + > + std::vector<CharSourceRange> ReformatRanges; > + SourceLocation StartOfFile = SM.getLocForStartOfFile(ID); > + for (ChangedRanges::const_iterator I = Changes.begin(), E = > Changes.end(); > + I != E; ++I) { > + SourceLocation Start = > StartOfFile.getLocWithOffset(I->getOffset()); > + SourceLocation End = Start.getLocWithOffset(I->getLength()); > + ReformatRanges.push_back(CharSourceRange::getCharRange(Start, > End)); > + } > + > + Lexer Lex(ID, SM.getBuffer(ID), SM, > getFormattingLangOpts(Style.Standard)); > + return format::reformat(Style, Lex, SM, ReformatRanges); > +} > > Added: clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.h > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11-migrate/Core/Reformatting.h?rev=186938&view=auto > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.h (added) > +++ clang-tools-extra/trunk/cpp11-migrate/Core/Reformatting.h Tue > Jul 23 07:50:03 2013 > @@ -0,0 +1,59 @@ > +//===-- Core/Reformatting.h - LibFormat integration -------------*- 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 provides the LibFormat integration used to > reformat > +/// migrated code. > +/// > > +//===----------------------------------------------------------------------===// > + > +#ifndef CPP11_MIGRATE_REFORMATTING_H > +#define CPP11_MIGRATE_REFORMATTING_H > + > +#include "clang/Format/Format.h" > + > +class SourceOverrides; > +class ChangedRanges; > + > +class Reformatter { > +public: > + Reformatter(const clang::format::FormatStyle &Style) : Style(Style) > {} > + > + /// \brief Reformat the changes made to the file overrides. > + /// > + /// \param Overrides Overriden source files to reformat. Note that > since only > + /// the changes are reformatted, file change tracking has to be > enabled. > + /// \param SM A SourceManager where the overridens files can be > found. > + /// > + /// \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 > applies > + /// on the ranges are identical: > + /// > + /// <blockquote> 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()</blockquote> > + clang::tooling::Replacements reformatSingleFile(llvm::StringRef > FileName, > + const ChangedRanges > &Changes, > + clang::SourceManager > &SM); > + > +private: > + clang::format::FormatStyle Style; > +}; > + > +#endif // CPP11_MIGRATE_REFORMATTING_H > > Modified: clang-tools-extra/trunk/cpp11- > migrate/tool/Cpp11Migrate.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11- > migrate/tool/Cpp11Migrate.cpp?rev=186938&r1=186937&r2=186938&view=dif > f > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/tool/Cpp11Migrate.cpp > (original) > +++ clang-tools-extra/trunk/cpp11-migrate/tool/Cpp11Migrate.cpp Tue > Jul 23 07:50:03 2013 > @@ -20,6 +20,7 @@ > #include "Core/SyntaxCheck.h" > #include "Core/Transform.h" > #include "Core/Transforms.h" > +#include "Core/Reformatting.h" > #include "LoopConvert/LoopConvert.h" > #include "UseNullptr/UseNullptr.h" > #include "UseAuto/UseAuto.h" > @@ -28,6 +29,7 @@ > #include "clang/Frontend/FrontendActions.h" > #include "clang/Tooling/CommonOptionsParser.h" > #include "clang/Tooling/Tooling.h" > +#include "llvm/Support/MemoryBuffer.h" > #include "llvm/Support/Signals.h" > > namespace cl = llvm::cl; > @@ -43,9 +45,9 @@ static cl::extrahelp MoreHelp( > " cpp11-migrate -use-auto path/to/file.cpp -- > -Ipath/to/include/\n" > "\n" > "Convert for loops to the new ranged-based for loops on all files > in a > " > - "subtree:\n\n" > + "subtree\nand reformat the code automatically using the LLVM > style:\n\n" > " find path/in/subtree -name '*.cpp' -exec \\\n" > - " cpp11-migrate -p build/path -loop-convert {} ';'\n" > + " cpp11-migrate -p build/path -format-style=LLVM -loop-convert > {} > ';'\n" > "\n" > "Make use of both nullptr and the override specifier, using git ls- > files:\n" > "\n" > @@ -70,6 +72,14 @@ static cl::opt<bool> FinalSyntaxCheck( > cl::desc("Check for correct syntax after applying > transformations"), > cl::init(false)); > > +static cl::opt<std::string> FormatStyleOpt( > + "format-style", > + cl::desc("Coding style to use on the replacements, either a builtin > style\n" > + "or a YAML config file (see: clang-format > -dump-config).\n" > + "Currently supports 4 builtins style:\n" > + " LLVM, Google, Chromium, Mozilla.\n"), > + cl::value_desc("string")); > + > static cl::opt<bool> > SummaryMode("summary", cl::desc("Print transform summary"), > cl::init(false)); > @@ -108,6 +118,40 @@ static cl::opt<bool, /*ExternalStorage=* > cl::location(GlobalOptions.EnableHeaderModifications), > cl::init(false)); > > +/// \brief Creates the Reformatter if the format style option is > provided, > +/// return a null pointer otherwise. > +/// > +/// \param ProgName The name of the program, \c argv[0], used to > print errors. > +/// \param Error If the \c -format-style is provided but with wrong > parameters > +/// this is parameter is set to \c true, left untouched otherwise. An > error > +/// message is printed with an explanation. > +static Reformatter *handleFormatStyle(const char *ProgName, bool > &Error) { > + if (FormatStyleOpt.getNumOccurrences() > 0) { > + format::FormatStyle Style; > + if (!format::getPredefinedStyle(FormatStyleOpt, &Style)) { > + llvm::StringRef ConfigFilePath = FormatStyleOpt; > + llvm::OwningPtr<llvm::MemoryBuffer> Text; > + llvm::error_code ec; > + > + ec = llvm::MemoryBuffer::getFile(ConfigFilePath, Text); > + if (!ec) > + ec = parseConfiguration(Text->getBuffer(), &Style); > + > + if (ec) { > + llvm::errs() << ProgName << ": invalid format style " << > FormatStyleOpt > + << ": " << ec.message() << "\n"; > + Error = true; > + return 0; > + } > + } > + > + // force mode to C++11 > + Style.Standard = clang::format::FormatStyle::LS_Cpp11; > + return new Reformatter(Style); > + } > + return 0; > +} > + > int main(int argc, const char **argv) { > llvm::sys::PrintStackTraceOnErrorSignal(); > Transforms TransformManager; > @@ -137,6 +181,13 @@ int main(int argc, const char **argv) { > // against the default value when the command line option is not > specified. > GlobalOptions.EnableTiming = (TimingDirectoryName != NoTiming); > > + // Check the reformatting style option > + bool BadStyle = false; > + llvm::OwningPtr<Reformatter> ChangesReformatter( > + handleFormatStyle(argv[0], BadStyle)); > + if (BadStyle) > + return 1; > + > // Populate the ModifiableHeaders structure if header modifications > are > // enabled. > if (GlobalOptions.EnableHeaderModifications) { > @@ -153,7 +204,10 @@ int main(int argc, const char **argv) { > return 1; > } > > - FileOverrides FileStates; > + // if reformatting is enabled we wants to track file changes so that > it's > + // possible to reformat them. > + bool TrackReplacements = static_cast<bool>(ChangesReformatter); > + FileOverrides FileStates(TrackReplacements); > SourcePerfData PerfData; > > // Apply transforms. > @@ -183,6 +237,15 @@ int main(int argc, const char **argv) { > } > } > > + // 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(OptionsParser.getCompilations(), > OptionsParser.getSourcePathList(), FileStates)) > > Modified: clang-tools-extra/trunk/cpp11-migrate/tool/Makefile > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/cpp11- > migrate/tool/Makefile?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/cpp11-migrate/tool/Makefile (original) > +++ clang-tools-extra/trunk/cpp11-migrate/tool/Makefile Tue Jul 23 > 07:50:03 2013 > @@ -34,10 +34,10 @@ SOURCES += $(addprefix ../ReplaceAutoPtr > BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir > > LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader > support mc mcparser option > -USEDLIBS = migrateCore.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 > +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 > > > Modified: clang-tools-extra/trunk/docs/MigratorUsage.rst > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/docs/MigratorUsage.rst?rev=186938&r1=186937&r2=186938&view > =diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/docs/MigratorUsage.rst (original) > +++ clang-tools-extra/trunk/docs/MigratorUsage.rst Tue Jul 23 > 07:50:03 2013 > @@ -66,6 +66,43 @@ General Command Line Options > earlier transforms are already caught when subsequent transforms > parse the > file. > > +.. option:: -format-style=<string> > + > + After all transformations have been applied, reformat the changes > using the > + style ``string`` given as argument to the option. The style can be a > builtin > + style, one of LLVM, Google, Chromium, Mozilla; or a YAML > configuration file. > + > + If you want a place to start for using your own custom configuration > file, > + ClangFormat_ can generate a file with ``clang-format -dump-config``. > + > + Example: > + > + .. code-block:: c++ > + :emphasize-lines: 10-12,18 > + > + // file.cpp > + for (std::vector<int>::const_iterator I = my_container.begin(), > + E = my_container.end(); > + I != E; ++I) { > + std::cout << *I << std::endl; > + } > + > + // No reformatting: > + // cpp11-migrate -use-auto file.cpp -- > + for (auto I = my_container.begin(), > + E = my_container.end(); > + I != E; ++I) { > + std::cout << *I << std::endl; > + } > + > + // With reformatting enabled: > + // cpp11-migrate -format-style=LLVM -use-auto file.cpp -- > + for (auto I = my_container.begin(), E = my_container.end(); I != > E; > ++I) { > + std::cout << *I << std::endl; > + } > + > +.. _ClangFormat: http://clang.llvm.org/docs/ClangFormat.html > + > .. option:: -summary > > Displays a summary of the number of changes each transform made or > could have > > Added: clang-tools-extra/trunk/test/cpp11- > migrate/Core/Reformatting.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/test/cpp11- > migrate/Core/Reformatting.cpp?rev=186938&view=auto > ========================================================== > ==================== > --- clang-tools-extra/trunk/test/cpp11-migrate/Core/Reformatting.cpp > (added) > +++ clang-tools-extra/trunk/test/cpp11- > migrate/Core/Reformatting.cpp Tue Jul 23 07:50:03 2013 > @@ -0,0 +1,15 @@ > +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp > +// RUN: not cpp11-migrate -format-style=FOO -use-auto %t.cpp -- - > std=c++11 > +// RUN: not cpp11-migrate -format-style=/tmp/ -use-auto %t.cpp -- - > std=c++11 > +// RUN: cpp11-migrate -format-style=LLVM -use-auto %t.cpp -- - > std=c++11 > +// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s > + > +class MyType012345678901234567890123456789 {}; > + > +int f() { > + MyType012345678901234567890123456789 *a = > + new MyType012345678901234567890123456789(); > + // CHECK: {{^\ \ auto\ a\ \=\ new\ > MyType012345678901234567890123456789\(\);}} > + > + delete a; > +} > > Modified: clang-tools-extra/trunk/unittests/cpp11- > migrate/CMakeLists.txt > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/unittests/cpp11- > migrate/CMakeLists.txt?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/unittests/cpp11-migrate/CMakeLists.txt > (original) > +++ clang-tools-extra/trunk/unittests/cpp11-migrate/CMakeLists.txt > Tue Jul 23 07:50:03 2013 > @@ -8,6 +8,7 @@ include_directories(${CPP11_MIGRATE_SOUR > > add_extra_unittest(Cpp11MigrateTests > FileOverridesTest.cpp > + ReformattingTest.cpp > IncludeExcludeTest.cpp > PerfSupportTest.cpp > TransformTest.cpp > @@ -16,7 +17,9 @@ add_extra_unittest(Cpp11MigrateTests > > target_link_libraries(Cpp11MigrateTests > migrateCore > + clangFormat > clangTooling > clangBasic > clangASTMatchers > + clangRewriteFrontend > ) > > Modified: clang-tools-extra/trunk/unittests/cpp11- > migrate/FileOverridesTest.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/unittests/cpp11- > migrate/FileOverridesTest.cpp?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/unittests/cpp11- > migrate/FileOverridesTest.cpp (original) > +++ clang-tools-extra/trunk/unittests/cpp11- > migrate/FileOverridesTest.cpp Tue Jul 23 07:50:03 2013 > @@ -21,10 +21,11 @@ TEST(SourceOverridesTest, Interface) { > FileName, > "std::vector<such_a_long_name_for_a_type>::const_iterator > long_type =\n" > " vec.begin();\n"); > - SourceOverrides Overrides(FileName); > + SourceOverrides Overrides(FileName, /*TrackFileChanges=*/false); > > EXPECT_EQ(FileName, Overrides.getMainFileName()); > EXPECT_FALSE(Overrides.isSourceOverriden()); > + EXPECT_FALSE(Overrides.isTrackingFileChanges()); > > Replacements Replaces; > unsigned ReplacementLength = > @@ -37,3 +38,103 @@ TEST(SourceOverridesTest, Interface) { > " 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 > +Replacements makeReplacements(unsigned Offset, unsigned Length, > + unsigned ReplacementLength) { > + Replacements Replaces; > + Replaces.insert(makeReplacement(Offset, Length, > ReplacementLength)); > + return Replaces; > +} > + > +bool equalRanges(Range A, Range B) { > + return A.getOffset() == B.getOffset() && A.getLength() == > B.getLength(); > +} > +} // end anonymous namespace > + > +TEST(ChangedRangesTest, adjustChangedRangesShrink) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(0, 0, 4)); > + EXPECT_NE(Changes.begin(), Changes.end()); > + EXPECT_TRUE(equalRanges(Range(0, 4), *Changes.begin())); > + // create a replacement that cuts the end of the last insertion > + Changes.adjustChangedRanges(makeReplacements(2, 4, 0)); > + Range ExpectedChanges[] = { Range(0, 2) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesExtend) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(1, 0, 4)); > + // cut the old one by a bigger one > + Changes.adjustChangedRanges(makeReplacements(3, 4, 6)); > + Range ExpectedChanges[] = { Range(1, 8) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesNoOverlap) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(0, 0, 4)); > + Changes.adjustChangedRanges(makeReplacements(6, 0, 4)); > + Range ExpectedChanges[] = { Range(0, 4), Range(6, 4) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesNullRange) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(0, 4, 0)); > + Range ExpectedChanges[] = { Range(0, 0) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesExtendExisting) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(0, 0, 3)); > + Changes.adjustChangedRanges(makeReplacements(2, 5, 8)); > + Range ExpectedChanges[] = { Range(0, 10) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesSplit) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(0, 0, 3)); > + Changes.adjustChangedRanges(makeReplacements(1, 1, 0)); > + Range ExpectedChanges[] = { Range(0, 2) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesRangeContained) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(3, 0, 2)); > + Changes.adjustChangedRanges(makeReplacements(1, 4, 5)); > + Range ExpectedChanges[] = { Range(1, 5) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > + > +TEST(ChangedRangesTest, adjustChangedRangesRangeResized) { > + ChangedRanges Changes; > + Changes.adjustChangedRanges(makeReplacements(2, 0, 5)); > + // first make the range bigger > + Changes.adjustChangedRanges(makeReplacements(4, 1, 3)); > + Range ExpectedChanges[] = { Range(2, 7) }; > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > + // then smaller > + Changes.adjustChangedRanges(makeReplacements(3, 3, 1)); > + ExpectedChanges[0] = Range(2, 5); > + EXPECT_TRUE( > + std::equal(Changes.begin(), Changes.end(), ExpectedChanges, > equalRanges)); > +} > > Modified: clang-tools-extra/trunk/unittests/cpp11-migrate/Makefile > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/unittests/cpp11- > migrate/Makefile?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/unittests/cpp11-migrate/Makefile (original) > +++ clang-tools-extra/trunk/unittests/cpp11-migrate/Makefile Tue Jul > 23 07:50:03 2013 > @@ -12,10 +12,11 @@ include $(CLANG_LEVEL)/../../Makefile.co > > TESTNAME = Cpp11MigrateTests > LINK_COMPONENTS := asmparser bitreader support MC MCParser > option > -USEDLIBS = migrateCore.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 > +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 > MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1 > > Added: clang-tools-extra/trunk/unittests/cpp11- > migrate/ReformattingTest.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/unittests/cpp11- > migrate/ReformattingTest.cpp?rev=186938&view=auto > ========================================================== > ==================== > --- clang-tools-extra/trunk/unittests/cpp11- > migrate/ReformattingTest.cpp (added) > +++ clang-tools-extra/trunk/unittests/cpp11- > migrate/ReformattingTest.cpp Tue Jul 23 07:50:03 2013 > @@ -0,0 +1,50 @@ > +//===- cpp11-migrate/ReformattingTest.cpp - Reformatting unit tests - > ------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open > Source > +// License. See LICENSE.TXT for details. > +// > > +//===----------------------------------------------------------------------===// > + > +#include "Core/Reformatting.h" > +#include "Core/FileOverrides.h" > +#include "gtest/gtest.h" > +#include "VirtualFileHelper.h" > + > +using namespace clang; > +using namespace clang::tooling; > + > +namespace { > +// convenience function to create a ChangedRanges containing one > Range > +ChangedRanges makeChangedRanges(unsigned Offset, unsigned > Length) { > + ChangedRanges Changes; > + Replacements Replaces; > + > + Replaces.insert(Replacement("", Offset, 0, std::string(Length, > '~'))); > + Changes.adjustChangedRanges(Replaces); > + return Changes; > +} > +} // end anonymous namespace > + > +TEST(Reformatter, SingleReformat) { > + VirtualFileHelper VFHelper; > + llvm::StringRef FileName = "<test>"; > + VFHelper.mapFile(FileName, "int a;\n" > + "int b;\n"); > + > + Reformatter ChangesReformatter(format::getLLVMStyle()); > + ChangedRanges Changes = makeChangedRanges(0, 6); > + tooling::Replacements Replaces = > ChangesReformatter.reformatSingleFile( > + FileName, Changes, VFHelper.getNewSourceManager()); > + > + 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); > +} > > Modified: clang-tools-extra/trunk/unittests/cpp11- > migrate/TransformTest.cpp > URL: http://llvm.org/viewvc/llvm-project/clang-tools- > extra/trunk/unittests/cpp11- > migrate/TransformTest.cpp?rev=186938&r1=186937&r2=186938&view=diff > ========================================================== > ==================== > --- clang-tools-extra/trunk/unittests/cpp11-migrate/TransformTest.cpp > (original) > +++ clang-tools-extra/trunk/unittests/cpp11- > migrate/TransformTest.cpp Tue Jul 23 07:50:03 2013 > @@ -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)); > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
