diff options
Diffstat (limited to 'clang-tools-extra/cpp11-migrate')
-rw-r--r-- | clang-tools-extra/cpp11-migrate/Core/CMakeLists.txt | 26 | ||||
-rw-r--r-- | clang-tools-extra/cpp11-migrate/Core/PerfSupport.cpp | 202 | ||||
-rw-r--r-- | clang-tools-extra/cpp11-migrate/Core/PerfSupport.h | 112 | ||||
-rw-r--r-- | clang-tools-extra/cpp11-migrate/Core/Transform.cpp | 114 | ||||
-rw-r--r-- | clang-tools-extra/cpp11-migrate/Core/Transform.h | 452 | ||||
-rw-r--r-- | clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp | 392 |
6 files changed, 649 insertions, 649 deletions
diff --git a/clang-tools-extra/cpp11-migrate/Core/CMakeLists.txt b/clang-tools-extra/cpp11-migrate/Core/CMakeLists.txt index e092eee5c86..1cd42f0b237 100644 --- a/clang-tools-extra/cpp11-migrate/Core/CMakeLists.txt +++ b/clang-tools-extra/cpp11-migrate/Core/CMakeLists.txt @@ -1,13 +1,13 @@ -set(LLVM_LINK_COMPONENTS support)
-
-add_clang_library(migrateCore
- Transforms.cpp
- Transform.cpp
- IncludeExcludeInfo.cpp
- PerfSupport.cpp
- )
-target_link_libraries(migrateCore
- clangTooling
- clangBasic
- clangASTMatchers
- )
+set(LLVM_LINK_COMPONENTS support) + +add_clang_library(migrateCore + Transforms.cpp + Transform.cpp + IncludeExcludeInfo.cpp + PerfSupport.cpp + ) +target_link_libraries(migrateCore + clangTooling + clangBasic + clangASTMatchers + ) diff --git a/clang-tools-extra/cpp11-migrate/Core/PerfSupport.cpp b/clang-tools-extra/cpp11-migrate/Core/PerfSupport.cpp index 0680747ae36..82d6558f365 100644 --- a/clang-tools-extra/cpp11-migrate/Core/PerfSupport.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/PerfSupport.cpp @@ -1,101 +1,101 @@ -//===-- cpp11-migrate/Cpp11Migrate.cpp - Main file C++11 migration tool ---===//
-//
-// 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 implementations for performance measuring helpers.
-///
-//===----------------------------------------------------------------------===//
-
-#include "PerfSupport.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Path.h"
-
-void collectSourcePerfData(const Transform &T, SourcePerfData &Data) {
- for (Transform::TimingVec::const_iterator I = T.timing_begin(),
- E = T.timing_end();
- I != E; ++I) {
- SourcePerfData::iterator DataI = Data.insert(
- SourcePerfData::value_type(I->first, std::vector<PerfItem>())).first;
- DataI->second
- .push_back(PerfItem(T.getName(), I->second.getProcessTime() * 1000.0));
- }
-}
-
-void writePerfDataJSON(
- const llvm::StringRef DirectoryName,
- const SourcePerfData &TimingResults) {
- // Create directory path if it doesn't exist
- llvm::sys::Path P(DirectoryName);
- P.createDirectoryOnDisk(true);
-
- // Get PID and current time.
- // FIXME: id_type on Windows is NOT a process id despite the function name.
- // Need to call GetProcessId() providing it what get_id() returns. For now
- // disabling PID-based file names until this is fixed properly.
- //llvm::sys::self_process *SP = llvm::sys::process::get_self();
- //id_type Pid = SP->get_id();
- unsigned Pid = 0;
- llvm::TimeRecord T = llvm::TimeRecord::getCurrentTime();
-
- std::string FileName;
- llvm::raw_string_ostream SS(FileName);
- SS << P.str() << "/" << static_cast<int>(T.getWallTime()) << "_" << Pid
- << ".json";
-
- std::string ErrorInfo;
- llvm::raw_fd_ostream FileStream(SS.str().c_str(), ErrorInfo);
- FileStream << "{\n";
- FileStream << " \"Sources\" : [\n";
- for (SourcePerfData::const_iterator I = TimingResults.begin(),
- E = TimingResults.end();
- I != E; ++I) {
- // Terminate the last source with a comma before continuing to the next one.
- if (I != TimingResults.begin())
- FileStream << ",\n";
-
- FileStream << " {\n";
- FileStream << " \"Source \" : \"" << I->first << "\",\n";
- FileStream << " \"Data\" : [\n";
- for (std::vector<PerfItem>::const_iterator IE = I->second.begin(),
- EE = I->second.end();
- IE != EE; ++IE) {
- // Terminate the last perf item with a comma before continuing to the next
- // one.
- if (IE != I->second.begin())
- FileStream << ",\n";
-
- FileStream << " {\n";
- FileStream << " \"TimerId\" : \"" << IE->Label << "\",\n";
- FileStream << " \"Time\" : " << llvm::format("%.2f", IE->Duration)
- << "\n";
-
- FileStream << " }";
-
- }
- FileStream << "\n ]\n";
- FileStream << " }";
- }
- FileStream << "\n ]\n";
- FileStream << "}";
-}
-
-void dumpPerfData(const SourcePerfData &Data) {
- for (SourcePerfData::const_iterator I = Data.begin(), E = Data.end(); I != E;
- ++I) {
- llvm::errs() << I->first << ":\n";
- for (std::vector<PerfItem>::const_iterator VecI = I->second.begin(),
- VecE = I->second.end();
- VecI != VecE; ++VecI) {
- llvm::errs() << " " << VecI->Label << ": "
- << llvm::format("%.1f", VecI->Duration) << "ms\n";
- }
- }
-}
+//===-- cpp11-migrate/Cpp11Migrate.cpp - Main file C++11 migration tool ---===// +// +// 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 implementations for performance measuring helpers. +/// +//===----------------------------------------------------------------------===// + +#include "PerfSupport.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Path.h" + +void collectSourcePerfData(const Transform &T, SourcePerfData &Data) { + for (Transform::TimingVec::const_iterator I = T.timing_begin(), + E = T.timing_end(); + I != E; ++I) { + SourcePerfData::iterator DataI = Data.insert( + SourcePerfData::value_type(I->first, std::vector<PerfItem>())).first; + DataI->second + .push_back(PerfItem(T.getName(), I->second.getProcessTime() * 1000.0)); + } +} + +void writePerfDataJSON( + const llvm::StringRef DirectoryName, + const SourcePerfData &TimingResults) { + // Create directory path if it doesn't exist + llvm::sys::Path P(DirectoryName); + P.createDirectoryOnDisk(true); + + // Get PID and current time. + // FIXME: id_type on Windows is NOT a process id despite the function name. + // Need to call GetProcessId() providing it what get_id() returns. For now + // disabling PID-based file names until this is fixed properly. + //llvm::sys::self_process *SP = llvm::sys::process::get_self(); + //id_type Pid = SP->get_id(); + unsigned Pid = 0; + llvm::TimeRecord T = llvm::TimeRecord::getCurrentTime(); + + std::string FileName; + llvm::raw_string_ostream SS(FileName); + SS << P.str() << "/" << static_cast<int>(T.getWallTime()) << "_" << Pid + << ".json"; + + std::string ErrorInfo; + llvm::raw_fd_ostream FileStream(SS.str().c_str(), ErrorInfo); + FileStream << "{\n"; + FileStream << " \"Sources\" : [\n"; + for (SourcePerfData::const_iterator I = TimingResults.begin(), + E = TimingResults.end(); + I != E; ++I) { + // Terminate the last source with a comma before continuing to the next one. + if (I != TimingResults.begin()) + FileStream << ",\n"; + + FileStream << " {\n"; + FileStream << " \"Source \" : \"" << I->first << "\",\n"; + FileStream << " \"Data\" : [\n"; + for (std::vector<PerfItem>::const_iterator IE = I->second.begin(), + EE = I->second.end(); + IE != EE; ++IE) { + // Terminate the last perf item with a comma before continuing to the next + // one. + if (IE != I->second.begin()) + FileStream << ",\n"; + + FileStream << " {\n"; + FileStream << " \"TimerId\" : \"" << IE->Label << "\",\n"; + FileStream << " \"Time\" : " << llvm::format("%.2f", IE->Duration) + << "\n"; + + FileStream << " }"; + + } + FileStream << "\n ]\n"; + FileStream << " }"; + } + FileStream << "\n ]\n"; + FileStream << "}"; +} + +void dumpPerfData(const SourcePerfData &Data) { + for (SourcePerfData::const_iterator I = Data.begin(), E = Data.end(); I != E; + ++I) { + llvm::errs() << I->first << ":\n"; + for (std::vector<PerfItem>::const_iterator VecI = I->second.begin(), + VecE = I->second.end(); + VecI != VecE; ++VecI) { + llvm::errs() << " " << VecI->Label << ": " + << llvm::format("%.1f", VecI->Duration) << "ms\n"; + } + } +} diff --git a/clang-tools-extra/cpp11-migrate/Core/PerfSupport.h b/clang-tools-extra/cpp11-migrate/Core/PerfSupport.h index 1596ee9c80c..7858e9e9d5c 100644 --- a/clang-tools-extra/cpp11-migrate/Core/PerfSupport.h +++ b/clang-tools-extra/cpp11-migrate/Core/PerfSupport.h @@ -1,56 +1,56 @@ -//===-- cpp11-migrate/PerfSupport.h - Perf measurement helpers --*- 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 helper functionality for measuring performance and
-/// recording data to file.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef CPP11_MIGRATE_PERFSUPPORT_H
-#define CPP11_MIGRATE_PERFSUPPORT_H
-
-#include <map>
-#include <vector>
-#include "Transform.h"
-#include "llvm/ADT/StringRef.h"
-
-/// \brief A single piece of performance data: a duration in milliseconds and a
-/// label for that duration.
-struct PerfItem {
- PerfItem(const llvm::StringRef Label, float Duration)
- : Label(Label), Duration(Duration) {}
-
- /// Label for this performance measurement.
- std::string Label;
-
- /// Duration in milliseconds.
- float Duration;
-};
-
-/// Maps source file names to a vector of durations/labels.
-typedef std::map<std::string, std::vector<PerfItem> > SourcePerfData;
-
-/// Extracts durations collected by a Transform for all sources and adds them
-/// to a SourcePerfData map where data is organized by source file.
-extern void collectSourcePerfData(const Transform &T, SourcePerfData &Data);
-
-/// Write timing results to a JSON formatted file.
-///
-/// File is placed in the directory given by \p DirectoryName. File is named in
-/// a unique way with time and process ID to avoid naming collisions with
-/// existing files or files being generated by other migrator processes.
-void writePerfDataJSON(
- const llvm::StringRef DirectoryName,
- const SourcePerfData &TimingResults);
-
-/// Dump a SourcePerfData map to llvm::errs().
-extern void dumpPerfData(const SourcePerfData &Data);
-
-#endif // CPP11_MIGRATE_PERFSUPPORT_H
+//===-- cpp11-migrate/PerfSupport.h - Perf measurement helpers --*- 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 helper functionality for measuring performance and +/// recording data to file. +/// +//===----------------------------------------------------------------------===// + +#ifndef CPP11_MIGRATE_PERFSUPPORT_H +#define CPP11_MIGRATE_PERFSUPPORT_H + +#include <map> +#include <vector> +#include "Transform.h" +#include "llvm/ADT/StringRef.h" + +/// \brief A single piece of performance data: a duration in milliseconds and a +/// label for that duration. +struct PerfItem { + PerfItem(const llvm::StringRef Label, float Duration) + : Label(Label), Duration(Duration) {} + + /// Label for this performance measurement. + std::string Label; + + /// Duration in milliseconds. + float Duration; +}; + +/// Maps source file names to a vector of durations/labels. +typedef std::map<std::string, std::vector<PerfItem> > SourcePerfData; + +/// Extracts durations collected by a Transform for all sources and adds them +/// to a SourcePerfData map where data is organized by source file. +extern void collectSourcePerfData(const Transform &T, SourcePerfData &Data); + +/// Write timing results to a JSON formatted file. +/// +/// File is placed in the directory given by \p DirectoryName. File is named in +/// a unique way with time and process ID to avoid naming collisions with +/// existing files or files being generated by other migrator processes. +void writePerfDataJSON( + const llvm::StringRef DirectoryName, + const SourcePerfData &TimingResults); + +/// Dump a SourcePerfData map to llvm::errs(). +extern void dumpPerfData(const SourcePerfData &Data); + +#endif // CPP11_MIGRATE_PERFSUPPORT_H diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp index f615867f89d..cfb316bb0b0 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.cpp +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.cpp @@ -1,57 +1,57 @@ -#include "Core/Transform.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace clang;
-
-void collectResults(clang::Rewriter &Rewrite,
- const FileContentsByPath &InputStates,
- FileContentsByPath &Results) {
- // Copy the contents of InputStates to be modified.
- Results = InputStates;
-
- for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(),
- E = Rewrite.buffer_end();
- I != E; ++I) {
- const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
- assert(Entry != 0 && "Expected a FileEntry");
- assert(Entry->getName() != 0 &&
- "Unexpected NULL return from FileEntry::getName()");
-
- std::string ResultBuf;
-
- // Get a copy of the rewritten buffer from the Rewriter.
- llvm::raw_string_ostream StringStream(ResultBuf);
- I->second.write(StringStream);
-
- // Cause results to be written to ResultBuf.
- StringStream.str();
-
- // FIXME: Use move semantics to avoid copies of the buffer contents if
- // benchmarking shows the copies are expensive, especially for large source
- // files.
- Results[Entry->getName()] = ResultBuf;
- }
-}
-
-bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
- if (!EnableTiming)
- return true;
-
- Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
- Timings.back().second -= llvm::TimeRecord::getCurrentTime(true);
- return true;
-}
-
-void Transform::handleEndSource() {
- if (!EnableTiming)
- return;
-
- Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
-}
-
-void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) {
- Timings.push_back(std::make_pair(Label.str(), Duration));
-}
+#include "Core/Transform.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; + +void collectResults(clang::Rewriter &Rewrite, + const FileContentsByPath &InputStates, + FileContentsByPath &Results) { + // Copy the contents of InputStates to be modified. + Results = InputStates; + + for (Rewriter::buffer_iterator I = Rewrite.buffer_begin(), + E = Rewrite.buffer_end(); + I != E; ++I) { + const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first); + assert(Entry != 0 && "Expected a FileEntry"); + assert(Entry->getName() != 0 && + "Unexpected NULL return from FileEntry::getName()"); + + std::string ResultBuf; + + // Get a copy of the rewritten buffer from the Rewriter. + llvm::raw_string_ostream StringStream(ResultBuf); + I->second.write(StringStream); + + // Cause results to be written to ResultBuf. + StringStream.str(); + + // FIXME: Use move semantics to avoid copies of the buffer contents if + // benchmarking shows the copies are expensive, especially for large source + // files. + Results[Entry->getName()] = ResultBuf; + } +} + +bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) { + if (!EnableTiming) + return true; + + Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord())); + Timings.back().second -= llvm::TimeRecord::getCurrentTime(true); + return true; +} + +void Transform::handleEndSource() { + if (!EnableTiming) + return; + + Timings.back().second += llvm::TimeRecord::getCurrentTime(false); +} + +void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) { + Timings.push_back(std::make_pair(Label.str(), Duration)); +} diff --git a/clang-tools-extra/cpp11-migrate/Core/Transform.h b/clang-tools-extra/cpp11-migrate/Core/Transform.h index 44d4d0559b6..1297ec1becd 100644 --- a/clang-tools-extra/cpp11-migrate/Core/Transform.h +++ b/clang-tools-extra/cpp11-migrate/Core/Transform.h @@ -1,226 +1,226 @@ -//===-- cpp11-migrate/Transform.h - Transform Base Class Def'n --*- 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 definition for the base Transform class from
-/// which all transforms must subclass.
-///
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H
-#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H
-
-#include <string>
-#include <vector>
-#include "clang/Tooling/Tooling.h"
-#include "llvm/Support/Timer.h"
-
-// For RewriterContainer
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Basic/SourceManager.h"
-#include "llvm/Support/raw_ostream.h"
-////
-
-
-/// \brief Description of the riskiness of actions that can be taken by
-/// transforms.
-enum RiskLevel {
- /// Transformations that will not change semantics.
- RL_Safe,
-
- /// Transformations that might change semantics.
- RL_Reasonable,
-
- /// Transformations that are likely to change semantics.
- RL_Risky
-};
-
-// Forward declarations
-namespace clang {
-namespace tooling {
-class CompilationDatabase;
-} // namespace tooling
-} // namespace clang
-
-/// \brief The key is the path of a file, which is mapped to a
-/// buffer with the possibly modified contents of that file.
-typedef std::map<std::string, std::string> FileContentsByPath;
-
-/// \brief In \p Results place copies of the buffers resulting from applying
-/// all rewrites represented by \p Rewrite.
-///
-/// \p Results is made up of pairs {filename, buffer contents}. Pairs are
-/// simply appended to \p Results.
-void collectResults(clang::Rewriter &Rewrite,
- const FileContentsByPath &InputStates,
- FileContentsByPath &Results);
-
-/// \brief Class for containing a Rewriter instance and all of
-/// its lifetime dependencies.
-///
-/// Subclasses of Transform using RefactoringTools will need to create
-/// Rewriters in order to apply Replacements and get the resulting buffer.
-/// Rewriter requires some objects to exist at least as long as it does so this
-/// class contains instances of those objects.
-///
-/// FIXME: These objects should really come from somewhere more global instead
-/// of being recreated for every Transform subclass, especially diagnostics.
-class RewriterContainer {
-public:
- RewriterContainer(clang::FileManager &Files,
- const FileContentsByPath &InputStates)
- : DiagOpts(new clang::DiagnosticOptions()),
- DiagnosticPrinter(llvm::errs(), DiagOpts.getPtr()),
- Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>(
- new clang::DiagnosticIDs()),
- DiagOpts.getPtr(), &DiagnosticPrinter, false),
- Sources(Diagnostics, Files),
- Rewrite(Sources, DefaultLangOptions) {
-
- // Overwrite source manager's file contents with data from InputStates
- for (FileContentsByPath::const_iterator I = InputStates.begin(),
- E = InputStates.end();
- I != E; ++I) {
- Sources.overrideFileContents(Files.getFile(I->first),
- llvm::MemoryBuffer::getMemBuffer(I->second));
- }
- }
-
- clang::Rewriter &getRewriter() { return Rewrite; }
-
-private:
- clang::LangOptions DefaultLangOptions;
- llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts;
- clang::TextDiagnosticPrinter DiagnosticPrinter;
- clang::DiagnosticsEngine Diagnostics;
- clang::SourceManager Sources;
- clang::Rewriter Rewrite;
-};
-
-/// \brief Abstract base class for all C++11 migration transforms.
-///
-/// Per-source performance timing is handled by the callbacks
-/// handleBeginSource() and handleEndSource() if timing is enabled. See
-/// clang::tooling::newFrontendActionFactory() for how to register
-/// a Transform object for callbacks.
-class Transform : public clang::tooling::SourceFileCallbacks {
-public:
- /// \brief Constructor
- /// \param Name Name of the transform for human-readable purposes (e.g. -help
- /// text)
- /// \param EnableTiming Enable the timing of the duration between calls to
- /// handleBeginSource() and handleEndSource(). When a Transform object is
- /// registered for FrontendAction source file callbacks, this behaviour can
- /// be used to time the application of a MatchFinder by subclasses. Durations
- /// are automatically stored in a TimingVec.
- Transform(llvm::StringRef Name, bool EnableTiming)
- : Name(Name), EnableTiming(EnableTiming) {
- Reset();
- }
-
- virtual ~Transform() {}
-
- /// \brief Apply a transform to all files listed in \p SourcePaths.
- ///
- /// \p Database must contain information for how to compile all files in \p
- /// SourcePaths. \p InputStates contains the file contents of files in \p
- /// 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 FileContentsByPath &InputStates,
- RiskLevel MaxRiskLevel,
- const clang::tooling::CompilationDatabase &Database,
- const std::vector<std::string> &SourcePaths,
- FileContentsByPath &ResultStates) = 0;
-
- /// \brief Query if changes were made during the last call to apply().
- bool getChangesMade() const { return AcceptedChanges > 0; }
-
- /// \brief Query if changes were not made due to conflicts with other changes
- /// made during the last call to apply() or if changes were too risky for the
- /// requested risk level.
- bool getChangesNotMade() const {
- return RejectedChanges > 0 || DeferredChanges > 0;
- }
-
- /// \brief Query the number of accepted changes.
- unsigned getAcceptedChanges() const { return AcceptedChanges; }
- /// \brief Query the number of changes considered too risky.
- unsigned getRejectedChanges() const { return RejectedChanges; }
- /// \brief Query the number of changes not made because they conflicted with
- /// early changes.
- unsigned getDeferredChanges() const { return DeferredChanges; }
-
- /// \brief Query transform name.
- llvm::StringRef getName() const { return Name; }
-
- /// \brief Reset internal state of the transform.
- ///
- /// Useful if calling apply() several times with one instantiation of a
- /// transform.
- void Reset() {
- AcceptedChanges = 0;
- RejectedChanges = 0;
- DeferredChanges = 0;
- }
-
- /// \brief Callback for notification of the start of processing of a source
- /// file by a FrontendAction. Starts a performance timer if timing was
- /// enabled.
- virtual bool handleBeginSource(clang::CompilerInstance &CI,
- llvm::StringRef Filename) LLVM_OVERRIDE;
-
- /// \brief Callback for notification of the end of processing of a source
- /// file by a FrontendAction. Stops a performance timer if timing was enabled
- /// and records the elapsed time. For a given source, handleBeginSource() and
- /// handleEndSource() are expected to be called in pairs.
- virtual void handleEndSource() LLVM_OVERRIDE;
-
- /// \brief Performance timing data is stored as a vector of pairs. Pairs are
- /// formed of:
- /// \li Name of source file.
- /// \li Elapsed time.
- typedef std::vector<std::pair<std::string, llvm::TimeRecord> > TimingVec;
-
- /// \brief Return an iterator to the start of collected timing data.
- TimingVec::const_iterator timing_begin() const { return Timings.begin(); }
- /// \brief Return an iterator to the start of collected timing data.
- TimingVec::const_iterator timing_end() const { return Timings.end(); }
-
-protected:
-
- void setAcceptedChanges(unsigned Changes) {
- AcceptedChanges = Changes;
- }
- void setRejectedChanges(unsigned Changes) {
- RejectedChanges = Changes;
- }
- void setDeferredChanges(unsigned Changes) {
- DeferredChanges = Changes;
- }
-
- /// \brief Allows subclasses to manually add performance timer data.
- ///
- /// \p Label should probably include the source file name somehow as the
- /// duration info is simply added to the vector of timing data which holds
- /// data for all sources processed by this transform.
- void addTiming(llvm::StringRef Label, llvm::TimeRecord Duration);
-
-private:
- const std::string Name;
- bool EnableTiming;
- TimingVec Timings;
- unsigned AcceptedChanges;
- unsigned RejectedChanges;
- unsigned DeferredChanges;
-};
-
-#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H
+//===-- cpp11-migrate/Transform.h - Transform Base Class Def'n --*- 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 definition for the base Transform class from +/// which all transforms must subclass. +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H +#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H + +#include <string> +#include <vector> +#include "clang/Tooling/Tooling.h" +#include "llvm/Support/Timer.h" + +// For RewriterContainer +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/raw_ostream.h" +//// + + +/// \brief Description of the riskiness of actions that can be taken by +/// transforms. +enum RiskLevel { + /// Transformations that will not change semantics. + RL_Safe, + + /// Transformations that might change semantics. + RL_Reasonable, + + /// Transformations that are likely to change semantics. + RL_Risky +}; + +// Forward declarations +namespace clang { +namespace tooling { +class CompilationDatabase; +} // namespace tooling +} // namespace clang + +/// \brief The key is the path of a file, which is mapped to a +/// buffer with the possibly modified contents of that file. +typedef std::map<std::string, std::string> FileContentsByPath; + +/// \brief In \p Results place copies of the buffers resulting from applying +/// all rewrites represented by \p Rewrite. +/// +/// \p Results is made up of pairs {filename, buffer contents}. Pairs are +/// simply appended to \p Results. +void collectResults(clang::Rewriter &Rewrite, + const FileContentsByPath &InputStates, + FileContentsByPath &Results); + +/// \brief Class for containing a Rewriter instance and all of +/// its lifetime dependencies. +/// +/// Subclasses of Transform using RefactoringTools will need to create +/// Rewriters in order to apply Replacements and get the resulting buffer. +/// Rewriter requires some objects to exist at least as long as it does so this +/// class contains instances of those objects. +/// +/// FIXME: These objects should really come from somewhere more global instead +/// of being recreated for every Transform subclass, especially diagnostics. +class RewriterContainer { +public: + RewriterContainer(clang::FileManager &Files, + const FileContentsByPath &InputStates) + : DiagOpts(new clang::DiagnosticOptions()), + DiagnosticPrinter(llvm::errs(), DiagOpts.getPtr()), + Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>( + new clang::DiagnosticIDs()), + DiagOpts.getPtr(), &DiagnosticPrinter, false), + Sources(Diagnostics, Files), + Rewrite(Sources, DefaultLangOptions) { + + // Overwrite source manager's file contents with data from InputStates + for (FileContentsByPath::const_iterator I = InputStates.begin(), + E = InputStates.end(); + I != E; ++I) { + Sources.overrideFileContents(Files.getFile(I->first), + llvm::MemoryBuffer::getMemBuffer(I->second)); + } + } + + clang::Rewriter &getRewriter() { return Rewrite; } + +private: + clang::LangOptions DefaultLangOptions; + llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts; + clang::TextDiagnosticPrinter DiagnosticPrinter; + clang::DiagnosticsEngine Diagnostics; + clang::SourceManager Sources; + clang::Rewriter Rewrite; +}; + +/// \brief Abstract base class for all C++11 migration transforms. +/// +/// Per-source performance timing is handled by the callbacks +/// handleBeginSource() and handleEndSource() if timing is enabled. See +/// clang::tooling::newFrontendActionFactory() for how to register +/// a Transform object for callbacks. +class Transform : public clang::tooling::SourceFileCallbacks { +public: + /// \brief Constructor + /// \param Name Name of the transform for human-readable purposes (e.g. -help + /// text) + /// \param EnableTiming Enable the timing of the duration between calls to + /// handleBeginSource() and handleEndSource(). When a Transform object is + /// registered for FrontendAction source file callbacks, this behaviour can + /// be used to time the application of a MatchFinder by subclasses. Durations + /// are automatically stored in a TimingVec. + Transform(llvm::StringRef Name, bool EnableTiming) + : Name(Name), EnableTiming(EnableTiming) { + Reset(); + } + + virtual ~Transform() {} + + /// \brief Apply a transform to all files listed in \p SourcePaths. + /// + /// \p Database must contain information for how to compile all files in \p + /// SourcePaths. \p InputStates contains the file contents of files in \p + /// 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 FileContentsByPath &InputStates, + RiskLevel MaxRiskLevel, + const clang::tooling::CompilationDatabase &Database, + const std::vector<std::string> &SourcePaths, + FileContentsByPath &ResultStates) = 0; + + /// \brief Query if changes were made during the last call to apply(). + bool getChangesMade() const { return AcceptedChanges > 0; } + + /// \brief Query if changes were not made due to conflicts with other changes + /// made during the last call to apply() or if changes were too risky for the + /// requested risk level. + bool getChangesNotMade() const { + return RejectedChanges > 0 || DeferredChanges > 0; + } + + /// \brief Query the number of accepted changes. + unsigned getAcceptedChanges() const { return AcceptedChanges; } + /// \brief Query the number of changes considered too risky. + unsigned getRejectedChanges() const { return RejectedChanges; } + /// \brief Query the number of changes not made because they conflicted with + /// early changes. + unsigned getDeferredChanges() const { return DeferredChanges; } + + /// \brief Query transform name. + llvm::StringRef getName() const { return Name; } + + /// \brief Reset internal state of the transform. + /// + /// Useful if calling apply() several times with one instantiation of a + /// transform. + void Reset() { + AcceptedChanges = 0; + RejectedChanges = 0; + DeferredChanges = 0; + } + + /// \brief Callback for notification of the start of processing of a source + /// file by a FrontendAction. Starts a performance timer if timing was + /// enabled. + virtual bool handleBeginSource(clang::CompilerInstance &CI, + llvm::StringRef Filename) LLVM_OVERRIDE; + + /// \brief Callback for notification of the end of processing of a source + /// file by a FrontendAction. Stops a performance timer if timing was enabled + /// and records the elapsed time. For a given source, handleBeginSource() and + /// handleEndSource() are expected to be called in pairs. + virtual void handleEndSource() LLVM_OVERRIDE; + + /// \brief Performance timing data is stored as a vector of pairs. Pairs are + /// formed of: + /// \li Name of source file. + /// \li Elapsed time. + typedef std::vector<std::pair<std::string, llvm::TimeRecord> > TimingVec; + + /// \brief Return an iterator to the start of collected timing data. + TimingVec::const_iterator timing_begin() const { return Timings.begin(); } + /// \brief Return an iterator to the start of collected timing data. + TimingVec::const_iterator timing_end() const { return Timings.end(); } + +protected: + + void setAcceptedChanges(unsigned Changes) { + AcceptedChanges = Changes; + } + void setRejectedChanges(unsigned Changes) { + RejectedChanges = Changes; + } + void setDeferredChanges(unsigned Changes) { + DeferredChanges = Changes; + } + + /// \brief Allows subclasses to manually add performance timer data. + /// + /// \p Label should probably include the source file name somehow as the + /// duration info is simply added to the vector of timing data which holds + /// data for all sources processed by this transform. + void addTiming(llvm::StringRef Label, llvm::TimeRecord Duration); + +private: + const std::string Name; + bool EnableTiming; + TimingVec Timings; + unsigned AcceptedChanges; + unsigned RejectedChanges; + unsigned DeferredChanges; +}; + +#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_TRANSFORM_H diff --git a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp index 3a263fccc4c..27ffafa603d 100644 --- a/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp +++ b/clang-tools-extra/cpp11-migrate/tool/Cpp11Migrate.cpp @@ -1,196 +1,196 @@ -//===-- cpp11-migrate/Cpp11Migrate.cpp - Main file C++11 migration tool ---===//
-//
-// 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 implements the C++11 feature migration tool main function
-/// and transformation framework.
-///
-/// See user documentation for usage instructions.
-///
-//===----------------------------------------------------------------------===//
-
-#include "Core/Transforms.h"
-#include "Core/Transform.h"
-#include "Core/PerfSupport.h"
-#include "LoopConvert/LoopConvert.h"
-#include "UseNullptr/UseNullptr.h"
-#include "UseAuto/UseAuto.h"
-#include "AddOverride/AddOverride.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/Support/Signals.h"
-
-namespace cl = llvm::cl;
-using namespace clang::tooling;
-
-static cl::opt<RiskLevel> MaxRiskLevel(
- "risk", cl::desc("Select a maximum risk level:"),
- cl::values(clEnumValN(RL_Safe, "safe", "Only safe transformations"),
- clEnumValN(RL_Reasonable, "reasonable",
- "Enable transformations that might change "
- "semantics (default)"),
- clEnumValN(RL_Risky, "risky",
- "Enable transformations that are likely to "
- "change semantics"),
- clEnumValEnd),
- cl::init(RL_Reasonable));
-
-static cl::opt<bool> FinalSyntaxCheck(
- "final-syntax-check",
- cl::desc("Check for correct syntax after applying transformations"),
- cl::init(false));
-
-static cl::opt<bool>
-SummaryMode("summary", cl::desc("Print transform summary"),
- cl::init(false));
-
-const char NoTiming[] = "no_timing";
-static cl::opt<std::string> TimingDirectoryName(
- "perf", cl::desc("Capture performance data and output to specified "
- "directory. Default: ./migrate_perf"),
- cl::init(NoTiming), cl::ValueOptional, cl::value_desc("directory name"));
-
-// TODO: Remove cl::Hidden when functionality for acknowledging include/exclude
-// options are implemented in the tool.
-static cl::opt<std::string>
-IncludePaths("include", cl::Hidden,
- cl::desc("Comma seperated list of paths to consider to be "
- "transformed"));
-static cl::opt<std::string>
-ExcludePaths("exclude", cl::Hidden,
- cl::desc("Comma seperated list of paths that can not "
- "be transformed"));
-static cl::opt<std::string>
-IncludeFromFile("include-from", cl::Hidden, cl::value_desc("filename"),
- cl::desc("File containing a list of paths to consider to "
- "be transformed"));
-static cl::opt<std::string>
-ExcludeFromFile("exclude-from", cl::Hidden, cl::value_desc("filename"),
- cl::desc("File containing a list of paths that can not be "
- "transforms"));
-
-class EndSyntaxArgumentsAdjuster : public ArgumentsAdjuster {
- CommandLineArguments Adjust(const CommandLineArguments &Args) {
- CommandLineArguments AdjustedArgs = Args;
- AdjustedArgs.push_back("-fsyntax-only");
- AdjustedArgs.push_back("-std=c++11");
- return AdjustedArgs;
- }
-};
-
-int main(int argc, const char **argv) {
- llvm::sys::PrintStackTraceOnErrorSignal();
- Transforms TransformManager;
-
- TransformManager.registerTransform(
- "loop-convert", "Make use of range-based for loops where possible",
- &ConstructTransform<LoopConvertTransform>);
- TransformManager.registerTransform(
- "use-nullptr", "Make use of nullptr keyword where possible",
- &ConstructTransform<UseNullptrTransform>);
- TransformManager.registerTransform(
- "use-auto", "Use of 'auto' type specifier",
- &ConstructTransform<UseAutoTransform>);
- TransformManager.registerTransform(
- "add-override", "Make use of override specifier where possible",
- &ConstructTransform<AddOverrideTransform>);
- // Add more transform options here.
-
- // This causes options to be parsed.
- CommonOptionsParser OptionsParser(argc, argv);
-
- // Since ExecutionTimeDirectoryName could be an empty string we compare
- // against the default value when the command line option is not specified.
- bool EnableTiming = (TimingDirectoryName != NoTiming);
- TransformManager.createSelectedTransforms(EnableTiming);
-
- if (TransformManager.begin() == TransformManager.end()) {
- llvm::errs() << "No selected transforms\n";
- return 1;
- }
-
- FileContentsByPath FileStates1, FileStates2,
- *InputFileStates = &FileStates1, *OutputFileStates = &FileStates2;
-
- SourcePerfData PerfData;
-
- // Apply transforms.
- for (Transforms::const_iterator I = TransformManager.begin(),
- E = TransformManager.end();
- I != E; ++I) {
- if ((*I)->apply(*InputFileStates, MaxRiskLevel,
- OptionsParser.getCompilations(),
- OptionsParser.getSourcePathList(), *OutputFileStates) !=
- 0) {
- // FIXME: Improve ClangTool to not abort if just one file fails.
- return 1;
- }
-
- if (EnableTiming)
- collectSourcePerfData(**I, PerfData);
-
- if (SummaryMode) {
- llvm::outs() << "Transform: " << (*I)->getName()
- << " - Accepted: "
- << (*I)->getAcceptedChanges();
- if ((*I)->getChangesNotMade()) {
- llvm::outs() << " - Rejected: "
- << (*I)->getRejectedChanges()
- << " - Deferred: "
- << (*I)->getDeferredChanges();
- }
- llvm::outs() << "\n";
- }
- std::swap(InputFileStates, OutputFileStates);
- OutputFileStates->clear();
- }
-
- // Final state of files is pointed at by InputFileStates.
-
- if (FinalSyntaxCheck) {
- ClangTool EndSyntaxTool(OptionsParser.getCompilations(),
- OptionsParser.getSourcePathList());
-
- // Add c++11 support to clang.
- EndSyntaxTool.setArgumentsAdjuster(new EndSyntaxArgumentsAdjuster);
-
- for (FileContentsByPath::const_iterator I = InputFileStates->begin(),
- E = InputFileStates->end();
- I != E; ++I) {
- EndSyntaxTool.mapVirtualFile(I->first, I->second);
- }
-
- if (EndSyntaxTool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>())
- != 0) {
- return 1;
- }
- }
-
- // Write results to file.
- for (FileContentsByPath::const_iterator I = InputFileStates->begin(),
- E = InputFileStates->end();
- I != E; ++I) {
- std::string ErrorInfo;
- llvm::raw_fd_ostream FileStream(I->first.c_str(), ErrorInfo,
- llvm::raw_fd_ostream::F_Binary);
- FileStream << I->second;
- }
-
- // Report execution times.
- if (EnableTiming && !PerfData.empty()) {
- std::string DirectoryName = TimingDirectoryName;
- // Use default directory name.
- if (DirectoryName.empty())
- DirectoryName = "./migrate_perf";
- writePerfDataJSON(DirectoryName, PerfData);
- }
-
- return 0;
-}
+//===-- cpp11-migrate/Cpp11Migrate.cpp - Main file C++11 migration tool ---===// +// +// 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 implements the C++11 feature migration tool main function +/// and transformation framework. +/// +/// See user documentation for usage instructions. +/// +//===----------------------------------------------------------------------===// + +#include "Core/Transforms.h" +#include "Core/Transform.h" +#include "Core/PerfSupport.h" +#include "LoopConvert/LoopConvert.h" +#include "UseNullptr/UseNullptr.h" +#include "UseAuto/UseAuto.h" +#include "AddOverride/AddOverride.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/Support/Signals.h" + +namespace cl = llvm::cl; +using namespace clang::tooling; + +static cl::opt<RiskLevel> MaxRiskLevel( + "risk", cl::desc("Select a maximum risk level:"), + cl::values(clEnumValN(RL_Safe, "safe", "Only safe transformations"), + clEnumValN(RL_Reasonable, "reasonable", + "Enable transformations that might change " + "semantics (default)"), + clEnumValN(RL_Risky, "risky", + "Enable transformations that are likely to " + "change semantics"), + clEnumValEnd), + cl::init(RL_Reasonable)); + +static cl::opt<bool> FinalSyntaxCheck( + "final-syntax-check", + cl::desc("Check for correct syntax after applying transformations"), + cl::init(false)); + +static cl::opt<bool> +SummaryMode("summary", cl::desc("Print transform summary"), + cl::init(false)); + +const char NoTiming[] = "no_timing"; +static cl::opt<std::string> TimingDirectoryName( + "perf", cl::desc("Capture performance data and output to specified " + "directory. Default: ./migrate_perf"), + cl::init(NoTiming), cl::ValueOptional, cl::value_desc("directory name")); + +// TODO: Remove cl::Hidden when functionality for acknowledging include/exclude +// options are implemented in the tool. +static cl::opt<std::string> +IncludePaths("include", cl::Hidden, + cl::desc("Comma seperated list of paths to consider to be " + "transformed")); +static cl::opt<std::string> +ExcludePaths("exclude", cl::Hidden, + cl::desc("Comma seperated list of paths that can not " + "be transformed")); +static cl::opt<std::string> +IncludeFromFile("include-from", cl::Hidden, cl::value_desc("filename"), + cl::desc("File containing a list of paths to consider to " + "be transformed")); +static cl::opt<std::string> +ExcludeFromFile("exclude-from", cl::Hidden, cl::value_desc("filename"), + cl::desc("File containing a list of paths that can not be " + "transforms")); + +class EndSyntaxArgumentsAdjuster : public ArgumentsAdjuster { + CommandLineArguments Adjust(const CommandLineArguments &Args) { + CommandLineArguments AdjustedArgs = Args; + AdjustedArgs.push_back("-fsyntax-only"); + AdjustedArgs.push_back("-std=c++11"); + return AdjustedArgs; + } +}; + +int main(int argc, const char **argv) { + llvm::sys::PrintStackTraceOnErrorSignal(); + Transforms TransformManager; + + TransformManager.registerTransform( + "loop-convert", "Make use of range-based for loops where possible", + &ConstructTransform<LoopConvertTransform>); + TransformManager.registerTransform( + "use-nullptr", "Make use of nullptr keyword where possible", + &ConstructTransform<UseNullptrTransform>); + TransformManager.registerTransform( + "use-auto", "Use of 'auto' type specifier", + &ConstructTransform<UseAutoTransform>); + TransformManager.registerTransform( + "add-override", "Make use of override specifier where possible", + &ConstructTransform<AddOverrideTransform>); + // Add more transform options here. + + // This causes options to be parsed. + CommonOptionsParser OptionsParser(argc, argv); + + // Since ExecutionTimeDirectoryName could be an empty string we compare + // against the default value when the command line option is not specified. + bool EnableTiming = (TimingDirectoryName != NoTiming); + TransformManager.createSelectedTransforms(EnableTiming); + + if (TransformManager.begin() == TransformManager.end()) { + llvm::errs() << "No selected transforms\n"; + return 1; + } + + FileContentsByPath FileStates1, FileStates2, + *InputFileStates = &FileStates1, *OutputFileStates = &FileStates2; + + SourcePerfData PerfData; + + // Apply transforms. + for (Transforms::const_iterator I = TransformManager.begin(), + E = TransformManager.end(); + I != E; ++I) { + if ((*I)->apply(*InputFileStates, MaxRiskLevel, + OptionsParser.getCompilations(), + OptionsParser.getSourcePathList(), *OutputFileStates) != + 0) { + // FIXME: Improve ClangTool to not abort if just one file fails. + return 1; + } + + if (EnableTiming) + collectSourcePerfData(**I, PerfData); + + if (SummaryMode) { + llvm::outs() << "Transform: " << (*I)->getName() + << " - Accepted: " + << (*I)->getAcceptedChanges(); + if ((*I)->getChangesNotMade()) { + llvm::outs() << " - Rejected: " + << (*I)->getRejectedChanges() + << " - Deferred: " + << (*I)->getDeferredChanges(); + } + llvm::outs() << "\n"; + } + std::swap(InputFileStates, OutputFileStates); + OutputFileStates->clear(); + } + + // Final state of files is pointed at by InputFileStates. + + if (FinalSyntaxCheck) { + ClangTool EndSyntaxTool(OptionsParser.getCompilations(), + OptionsParser.getSourcePathList()); + + // Add c++11 support to clang. + EndSyntaxTool.setArgumentsAdjuster(new EndSyntaxArgumentsAdjuster); + + for (FileContentsByPath::const_iterator I = InputFileStates->begin(), + E = InputFileStates->end(); + I != E; ++I) { + EndSyntaxTool.mapVirtualFile(I->first, I->second); + } + + if (EndSyntaxTool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>()) + != 0) { + return 1; + } + } + + // Write results to file. + for (FileContentsByPath::const_iterator I = InputFileStates->begin(), + E = InputFileStates->end(); + I != E; ++I) { + std::string ErrorInfo; + llvm::raw_fd_ostream FileStream(I->first.c_str(), ErrorInfo, + llvm::raw_fd_ostream::F_Binary); + FileStream << I->second; + } + + // Report execution times. + if (EnableTiming && !PerfData.empty()) { + std::string DirectoryName = TimingDirectoryName; + // Use default directory name. + if (DirectoryName.empty()) + DirectoryName = "./migrate_perf"; + writePerfDataJSON(DirectoryName, PerfData); + } + + return 0; +} |