Hi Maxim, Thanks for the email! I'll look into this right now.
Thanks, Eric On Thu, Oct 26, 2017 at 3:11 PM Maxim Kuvyrkov <maxim.kuvyr...@linaro.org> wrote: > Hi Eric, > > This seems to have broken clang-cmake-thumbv7-a15 buildbot [*]. Would you > please investigate? > > Or did you fix this while I was writing this email in 316661 :-) ? > > Thank you, > > [*] http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-a15/builds/12511 > > -- > Maxim Kuvyrkov > www.linaro.org > > > > > On Oct 26, 2017, at 1:38 PM, Eric Liu via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > > > > Author: ioeric > > Date: Thu Oct 26 03:38:14 2017 > > New Revision: 316653 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=316653&view=rev > > Log: > > [Tooling] A new framework for executing clang frontend actions. > > > > Summary: > > This defines a `clang::tooling::ToolExecutor` interface that can be > extended to support different execution plans including standalone > execution on a given set of TUs or parallel execution on all TUs in a > codebase. > > > > In order to enable multiprocessing execution, tool actions are expected > to output result into a `ToolResults` interface provided by executors. The > `ToolResults` interface abstracts how results are stored e.g. in-memory for > standalone executions or on-disk for large-scale execution. > > > > New executors can be registered as `ToolExecutorPlugin`s via the > `ToolExecutorPluginRegistry`. CLI tools can use > `createExecutorFromCommandLineArgs` to create a specific registered > executor according to the command-line arguments. > > > > This patch also implements `StandaloneToolExecutor` which has the same > behavior as the current `ClangTool` interface, i.e. execute frontend > actions on a given set of TUs. At this point, it's simply a wrapper around > `ClangTool` at this point. > > > > This is still experimental but expected to replace the existing > `ClangTool` interface so that specific tools would not need to worry about > execution. > > > > Reviewers: klimek, arphaman, hokein, sammccall > > > > Reviewed By: klimek > > > > Subscribers: cfe-commits, djasper, mgorny, omtcyfz > > > > Differential Revision: https://reviews.llvm.org/D34272 > > > > Added: > > cfe/trunk/include/clang/Tooling/Execution.h > > cfe/trunk/include/clang/Tooling/StandaloneExecution.h > > cfe/trunk/include/clang/Tooling/ToolExecutorPluginRegistry.h > > cfe/trunk/lib/Tooling/Execution.cpp > > cfe/trunk/lib/Tooling/StandaloneExecution.cpp > > cfe/trunk/unittests/Tooling/ExecutionTest.cpp > > Modified: > > cfe/trunk/include/clang/Tooling/CommonOptionsParser.h > > cfe/trunk/include/clang/Tooling/Tooling.h > > cfe/trunk/lib/Tooling/ArgumentsAdjusters.cpp > > cfe/trunk/lib/Tooling/CMakeLists.txt > > cfe/trunk/lib/Tooling/CommonOptionsParser.cpp > > cfe/trunk/lib/Tooling/Tooling.cpp > > cfe/trunk/unittests/Tooling/CMakeLists.txt > > > > Modified: cfe/trunk/include/clang/Tooling/CommonOptionsParser.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/CommonOptionsParser.h?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/include/clang/Tooling/CommonOptionsParser.h (original) > > +++ cfe/trunk/include/clang/Tooling/CommonOptionsParser.h Thu Oct 26 > 03:38:14 2017 > > @@ -109,6 +109,10 @@ public: > > return SourcePathList; > > } > > > > + /// Returns the argument adjuster calculated from "--extra-arg" and > > + //"--extra-arg-before" options. > > + ArgumentsAdjuster getArgumentsAdjuster() { return Adjuster; } > > + > > static const char *const HelpMessage; > > > > private: > > @@ -121,6 +125,7 @@ private: > > > > std::unique_ptr<CompilationDatabase> Compilations; > > std::vector<std::string> SourcePathList; > > + ArgumentsAdjuster Adjuster; > > }; > > > > class ArgumentsAdjustingCompilations : public CompilationDatabase { > > > > Added: cfe/trunk/include/clang/Tooling/Execution.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Execution.h?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/include/clang/Tooling/Execution.h (added) > > +++ cfe/trunk/include/clang/Tooling/Execution.h Thu Oct 26 03:38:14 2017 > > @@ -0,0 +1,168 @@ > > +//===--- Execution.h - Executing clang frontend actions -*- C++ > ---------*-===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > +// > > +// This file defines framework for executing clang frontend actions. > > +// > > +// The framework can be extended to support different execution plans > including > > +// standalone execution on the given TUs or parallel execution on all > TUs in > > +// the codebase. > > +// > > +// In order to enable multiprocessing execution, tool actions are > expected to > > +// output result into the ToolResults provided by the executor. The > > +// `ToolResults` is an interface that abstracts how results are stored > e.g. > > +// in-memory for standalone execution or on-disk for large-scale > execution. > > +// > > +// New executors can be registered as ToolExecutorPlugins via the > > +// `ToolExecutorPluginRegistry`. CLI tools can use > > +// `createExecutorFromCommandLineArgs` to create a specific registered > executor > > +// according to the command-line arguments. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#ifndef LLVM_CLANG_TOOLING_EXECUTION_H > > +#define LLVM_CLANG_TOOLING_EXECUTION_H > > + > > +#include "clang/Tooling/CommonOptionsParser.h" > > +#include "clang/Tooling/Tooling.h" > > +#include "llvm/Support/Error.h" > > +#include "llvm/Support/Registry.h" > > + > > +namespace clang { > > +namespace tooling { > > + > > +/// \brief An abstraction for the result of a tool execution. For > example, the > > +/// underlying result can be in-memory or on-disk. > > +/// > > +/// Results should be string key-value pairs. For example, a > refactoring tool > > +/// can use source location as key and a replacement in YAML format as > value. > > +class ToolResults { > > +public: > > + virtual ~ToolResults() = default; > > + virtual void addResult(StringRef Key, StringRef Value) = 0; > > + virtual std::vector<std::pair<std::string, std::string>> > AllKVResults() = 0; > > + virtual void forEachResult( > > + llvm::function_ref<void(StringRef Key, StringRef Value)> > Callback) = 0; > > +}; > > + > > +class InMemoryToolResults : public ToolResults { > > +public: > > + void addResult(StringRef Key, StringRef Value) override; > > + std::vector<std::pair<std::string, std::string>> AllKVResults() > override; > > + void forEachResult(llvm::function_ref<void(StringRef Key, StringRef > Value)> > > + Callback) override; > > + > > +private: > > + std::vector<std::pair<std::string, std::string>> KVResults; > > +}; > > + > > +/// \brief The context of an execution, including the information about > > +/// compilation and results. > > +class ExecutionContext { > > +public: > > + virtual ~ExecutionContext() {} > > + > > + /// \brief Initializes a context. This does not take ownership of > `Results`. > > + explicit ExecutionContext(ToolResults *Results) : Results(Results) {} > > + > > + /// \brief Adds a KV pair to the result container of this execution. > > + void reportResult(StringRef Key, StringRef Value); > > + > > + // Returns the source control system's revision number if applicable. > > + // Otherwise returns an empty string. > > + virtual std::string getRevision() { return ""; } > > + > > + // Returns the corpus being analyzed, e.g. "llvm" for the LLVM > codebase, if > > + // applicable. > > + virtual std::string getCorpus() { return ""; } > > + > > + // Returns the currently processed compilation unit if available. > > + virtual std::string getCurrentCompilationUnit() { return ""; } > > + > > +private: > > + ToolResults *Results; > > +}; > > + > > +/// \brief Interface for executing clang frontend actions. > > +/// > > +/// This can be extended to support running tool actions in different > > +/// execution mode, e.g. on a specific set of TUs or many TUs in > parallel. > > +/// > > +/// New executors can be registered as ToolExecutorPlugins via the > > +/// `ToolExecutorPluginRegistry`. CLI tools can use > > +/// `createExecutorFromCommandLineArgs` to create a specific registered > > +/// executor according to the command-line arguments. > > +class ToolExecutor { > > +public: > > + virtual ~ToolExecutor() {} > > + > > + /// \brief Returns the name of a specific executor. > > + virtual StringRef getExecutorName() const = 0; > > + > > + /// \brief Executes each action with a corresponding arguments > adjuster. > > + virtual llvm::Error > > + execute(llvm::ArrayRef< > > + std::pair<std::unique_ptr<FrontendActionFactory>, > ArgumentsAdjuster>> > > + Actions) = 0; > > + > > + /// \brief Convenient functions for the above `execute`. > > + llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action); > > + /// Executes an action with an argument adjuster. > > + llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action, > > + ArgumentsAdjuster Adjuster); > > + > > + /// \brief Returns a reference to the execution context. > > + /// > > + /// This should be passed to tool callbacks, and tool callbacks > should report > > + /// results via the returned context. > > + virtual ExecutionContext *getExecutionContext() = 0; > > + > > + /// \brief Returns a reference to the result container. > > + /// > > + /// NOTE: This should only be used after the execution finishes. Tool > > + /// callbacks should report results via `ExecutionContext` instead. > > + virtual ToolResults *getToolResults() = 0; > > + > > + /// \brief Map a virtual file to be used while running the tool. > > + /// > > + /// \param FilePath The path at which the content will be mapped. > > + /// \param Content A buffer of the file's content. > > + virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = > 0; > > +}; > > + > > +/// \brief Interface for factories that create specific executors. This > is also > > +/// used as a plugin to be registered into ToolExecutorPluginRegistry. > > +class ToolExecutorPlugin { > > +public: > > + virtual ~ToolExecutorPlugin() {} > > + > > + /// \brief Create an `ToolExecutor`. > > + /// > > + /// `OptionsParser` can be consumed (e.g. moved) if the creation > succeeds. > > + virtual llvm::Expected<std::unique_ptr<ToolExecutor>> > > + create(CommonOptionsParser &OptionsParser) = 0; > > +}; > > + > > +/// \brief This creates a ToolExecutor that is in the global registry > based on > > +/// commandline arguments. > > +/// > > +/// This picks the right executor based on the `--executor` option. > This parses > > +/// the commandline arguments with `CommonOptionsParser`, so caller > does not > > +/// need to parse again. > > +/// > > +/// By default, this creates a `StandaloneToolExecutor` ("standalone") > if > > +/// `--executor` is not provided. > > +llvm::Expected<std::unique_ptr<ToolExecutor>> > > +createExecutorFromCommandLineArgs(int &argc, const char **argv, > > + llvm::cl::OptionCategory &Category, > > + const char *Overview = nullptr); > > + > > +} // end namespace tooling > > +} // end namespace clang > > + > > +#endif // LLVM_CLANG_TOOLING_EXECUTION_H > > > > Added: cfe/trunk/include/clang/Tooling/StandaloneExecution.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/StandaloneExecution.h?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/include/clang/Tooling/StandaloneExecution.h (added) > > +++ cfe/trunk/include/clang/Tooling/StandaloneExecution.h Thu Oct 26 > 03:38:14 2017 > > @@ -0,0 +1,97 @@ > > +//===--- StandaloneExecution.h - Standalone execution. -*- C++ > ----------*-===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > +// > > +// This file defines standalone execution of clang tools. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#ifndef LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H > > +#define LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H > > + > > +#include "clang/Tooling/ArgumentsAdjusters.h" > > +#include "clang/Tooling/Execution.h" > > + > > +namespace clang { > > +namespace tooling { > > + > > +/// \brief A standalone executor that runs FrontendActions on a given > set of > > +/// TUs in sequence. > > +/// > > +/// By default, this executor uses the following arguments adjusters > (as defined > > +/// in `clang/Tooling/ArgumentsAdjusters.h`): > > +/// - `getClangStripOutputAdjuster()` > > +/// - `getClangSyntaxOnlyAdjuster()` > > +/// - `getClangStripDependencyFileAdjuster()` > > +class StandaloneToolExecutor : public ToolExecutor { > > +public: > > + static const char *ExecutorName; > > + > > + /// \brief Init with \p CompilationDatabase and the paths of all > files to be > > + /// proccessed. > > + StandaloneToolExecutor( > > + const CompilationDatabase &Compilations, > > + llvm::ArrayRef<std::string> SourcePaths, > > + std::shared_ptr<PCHContainerOperations> PCHContainerOps = > > + std::make_shared<PCHContainerOperations>()); > > + > > + /// \brief Init with \p CommonOptionsParser. This is expected to be > used by > > + /// `createExecutorFromCommandLineArgs` based on commandline options. > > + /// > > + /// The executor takes ownership of \p Options. > > + StandaloneToolExecutor( > > + CommonOptionsParser Options, > > + std::shared_ptr<PCHContainerOperations> PCHContainerOps = > > + std::make_shared<PCHContainerOperations>()); > > + > > + StringRef getExecutorName() const override { return ExecutorName; } > > + > > + using ToolExecutor::execute; > > + > > + llvm::Error > > + execute(llvm::ArrayRef< > > + std::pair<std::unique_ptr<FrontendActionFactory>, > ArgumentsAdjuster>> > > + Actions) override; > > + > > + /// \brief Set a \c DiagnosticConsumer to use during parsing. > > + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { > > + Tool.setDiagnosticConsumer(DiagConsumer); > > + } > > + > > + ExecutionContext *getExecutionContext() override { return &Context; }; > > + > > + ToolResults *getToolResults() override { return &Results; } > > + > > + llvm::ArrayRef<std::string> getSourcePaths() const { > > + return Tool.getSourcePaths(); > > + } > > + > > + void mapVirtualFile(StringRef FilePath, StringRef Content) override { > > + Tool.mapVirtualFile(FilePath, Content); > > + } > > + > > + /// \brief Returns the file manager used in the tool. > > + /// > > + /// The file manager is shared between all translation units. > > + FileManager &getFiles() { return Tool.getFiles(); } > > + > > +private: > > + // Used to store the parser when the executor is initialized with > parser. > > + llvm::Optional<CommonOptionsParser> OptionsParser; > > + // FIXME: The standalone executor is currently just a wrapper of > `ClangTool`. > > + // Merge `ClangTool` implementation into the this. > > + ClangTool Tool; > > + ExecutionContext Context; > > + InMemoryToolResults Results; > > + ArgumentsAdjuster ArgsAdjuster; > > +}; > > + > > +} // end namespace tooling > > +} // end namespace clang > > + > > +#endif // LLVM_CLANG_TOOLING_STANDALONEEXECUTION_H > > > > Added: cfe/trunk/include/clang/Tooling/ToolExecutorPluginRegistry.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/ToolExecutorPluginRegistry.h?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/include/clang/Tooling/ToolExecutorPluginRegistry.h (added) > > +++ cfe/trunk/include/clang/Tooling/ToolExecutorPluginRegistry.h Thu Oct > 26 03:38:14 2017 > > @@ -0,0 +1,24 @@ > > +//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ > -*-===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H > > +#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H > > + > > +#include "clang/Tooling/Execution.h" > > +#include "llvm/Support/Registry.h" > > + > > +namespace clang { > > +namespace tooling { > > + > > +typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry; > > + > > +} // end namespace tooling > > +} // end namespace clang > > + > > +#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H > > > > Modified: cfe/trunk/include/clang/Tooling/Tooling.h > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Tooling.h?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/include/clang/Tooling/Tooling.h (original) > > +++ cfe/trunk/include/clang/Tooling/Tooling.h Thu Oct 26 03:38:14 2017 > > @@ -31,12 +31,12 @@ > > #define LLVM_CLANG_TOOLING_TOOLING_H > > > > #include "clang/AST/ASTConsumer.h" > > -#include "clang/Frontend/PCHContainerOperations.h" > > #include "clang/Basic/Diagnostic.h" > > #include "clang/Basic/FileManager.h" > > #include "clang/Basic/LLVM.h" > > #include "clang/Driver/Util.h" > > #include "clang/Frontend/FrontendAction.h" > > +#include "clang/Frontend/PCHContainerOperations.h" > > #include "clang/Lex/ModuleLoader.h" > > #include "clang/Tooling/ArgumentsAdjusters.h" > > #include "clang/Tooling/CompilationDatabase.h" > > @@ -337,7 +337,9 @@ class ClangTool { > > /// The file manager is shared between all translation units. > > FileManager &getFiles() { return *Files; } > > > > - private: > > + llvm::ArrayRef<std::string> getSourcePaths() const { return > SourcePaths; } > > + > > +private: > > const CompilationDatabase &Compilations; > > std::vector<std::string> SourcePaths; > > std::shared_ptr<PCHContainerOperations> PCHContainerOps; > > > > Modified: cfe/trunk/lib/Tooling/ArgumentsAdjusters.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/ArgumentsAdjusters.cpp?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/ArgumentsAdjusters.cpp (original) > > +++ cfe/trunk/lib/Tooling/ArgumentsAdjusters.cpp Thu Oct 26 03:38:14 2017 > > @@ -96,6 +96,10 @@ ArgumentsAdjuster getInsertArgumentAdjus > > > > ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, > > ArgumentsAdjuster Second) { > > + if (!First) > > + return Second; > > + if (!Second) > > + return First; > > return [First, Second](const CommandLineArguments &Args, StringRef > File) { > > return Second(First(Args, File), File); > > }; > > > > Modified: cfe/trunk/lib/Tooling/CMakeLists.txt > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CMakeLists.txt?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/CMakeLists.txt (original) > > +++ cfe/trunk/lib/Tooling/CMakeLists.txt Thu Oct 26 03:38:14 2017 > > @@ -11,11 +11,13 @@ add_clang_library(clangTooling > > ArgumentsAdjusters.cpp > > CommonOptionsParser.cpp > > CompilationDatabase.cpp > > + Execution.cpp > > FileMatchTrie.cpp > > FixIt.cpp > > JSONCompilationDatabase.cpp > > Refactoring.cpp > > RefactoringCallbacks.cpp > > + StandaloneExecution.cpp > > Tooling.cpp > > > > DEPENDS > > > > Modified: cfe/trunk/lib/Tooling/CommonOptionsParser.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CommonOptionsParser.cpp?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/CommonOptionsParser.cpp (original) > > +++ cfe/trunk/lib/Tooling/CommonOptionsParser.cpp Thu Oct 26 03:38:14 > 2017 > > @@ -147,10 +147,12 @@ llvm::Error CommonOptionsParser::init( > > auto AdjustingCompilations = > > llvm::make_unique<ArgumentsAdjustingCompilations>( > > std::move(Compilations)); > > - AdjustingCompilations->appendArgumentsAdjuster( > > - getInsertArgumentAdjuster(ArgsBefore, > ArgumentInsertPosition::BEGIN)); > > - AdjustingCompilations->appendArgumentsAdjuster( > > + Adjuster = > > + getInsertArgumentAdjuster(ArgsBefore, > ArgumentInsertPosition::BEGIN); > > + Adjuster = combineAdjusters( > > + std::move(Adjuster), > > getInsertArgumentAdjuster(ArgsAfter, ArgumentInsertPosition::END)); > > + AdjustingCompilations->appendArgumentsAdjuster(Adjuster); > > Compilations = std::move(AdjustingCompilations); > > return llvm::Error::success(); > > } > > > > Added: cfe/trunk/lib/Tooling/Execution.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Execution.cpp?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/Execution.cpp (added) > > +++ cfe/trunk/lib/Tooling/Execution.cpp Thu Oct 26 03:38:14 2017 > > @@ -0,0 +1,89 @@ > > +//===- lib/Tooling/Execution.cpp - Implements tool execution framework. > ---===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#include "clang/Tooling/Execution.h" > > +#include "clang/Tooling/ToolExecutorPluginRegistry.h" > > +#include "clang/Tooling/Tooling.h" > > + > > +LLVM_INSTANTIATE_REGISTRY(clang::tooling::ToolExecutorPluginRegistry) > > + > > +namespace clang { > > +namespace tooling { > > + > > +static llvm::cl::opt<std::string> > > + ExecutorName("executor", llvm::cl::desc("The name of the executor > to use."), > > + llvm::cl::init("standalone")); > > + > > +void InMemoryToolResults::addResult(StringRef Key, StringRef Value) { > > + KVResults.push_back({Key.str(), Value.str()}); > > +} > > + > > +std::vector<std::pair<std::string, std::string>> > > +InMemoryToolResults::AllKVResults() { > > + return KVResults; > > +} > > + > > +void InMemoryToolResults::forEachResult( > > + llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) { > > + for (const auto &KV : KVResults) { > > + Callback(KV.first, KV.second); > > + } > > +} > > + > > +void ExecutionContext::reportResult(StringRef Key, StringRef Value) { > > + Results->addResult(Key, Value); > > +} > > + > > +llvm::Error > > +ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action) { > > + return execute(std::move(Action), ArgumentsAdjuster()); > > +} > > + > > +llvm::Error > ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action, > > + ArgumentsAdjuster Adjuster) { > > + std::vector< > > + std::pair<std::unique_ptr<FrontendActionFactory>, > ArgumentsAdjuster>> > > + Actions; > > + Actions.emplace_back(std::move(Action), std::move(Adjuster)); > > + return execute(Actions); > > +} > > + > > +llvm::Expected<std::unique_ptr<ToolExecutor>> > > +createExecutorFromCommandLineArgs(int &argc, const char **argv, > > + llvm::cl::OptionCategory &Category, > > + const char *Overview) { > > + auto OptionsParser = > > + CommonOptionsParser::create(argc, argv, Category, > llvm::cl::ZeroOrMore, > > + /*Overview=*/nullptr); > > + if (!OptionsParser) > > + return OptionsParser.takeError(); > > + for (auto I = ToolExecutorPluginRegistry::begin(), > > + E = ToolExecutorPluginRegistry::end(); > > + I != E; ++I) { > > + if (I->getName() != ExecutorName) { > > + continue; > > + } > > + std::unique_ptr<ToolExecutorPlugin> Plugin(I->instantiate()); > > + llvm::Expected<std::unique_ptr<ToolExecutor>> Executor = > > + Plugin->create(*OptionsParser); > > + if (!Executor) { > > + return llvm::make_error<llvm::StringError>( > > + llvm::Twine("Failed to create '") + I->getName() + > > + "': " + llvm::toString(Executor.takeError()) + "\n", > > + llvm::inconvertibleErrorCode()); > > + } > > + return std::move(*Executor); > > + } > > + return llvm::make_error<llvm::StringError>( > > + llvm::Twine("Executor \"") + ExecutorName + "\" is not > registered.", > > + llvm::inconvertibleErrorCode()); > > +} > > + > > +} // end namespace tooling > > +} // end namespace clang > > > > Added: cfe/trunk/lib/Tooling/StandaloneExecution.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/StandaloneExecution.cpp?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/StandaloneExecution.cpp (added) > > +++ cfe/trunk/lib/Tooling/StandaloneExecution.cpp Thu Oct 26 03:38:14 > 2017 > > @@ -0,0 +1,91 @@ > > +//===- lib/Tooling/Execution.cpp - Standalone clang action execution. > -----===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#include "clang/Tooling/StandaloneExecution.h" > > +#include "clang/Tooling/ToolExecutorPluginRegistry.h" > > + > > +namespace clang { > > +namespace tooling { > > + > > +static llvm::Error make_string_error(const llvm::Twine &Message) { > > + return llvm::make_error<llvm::StringError>(Message, > > + > llvm::inconvertibleErrorCode()); > > +} > > + > > +const char *StandaloneToolExecutor::ExecutorName = > "StandaloneToolExecutor"; > > + > > +static ArgumentsAdjuster getDefaultArgumentsAdjusters() { > > + return combineAdjusters( > > + getClangStripOutputAdjuster(), > > + combineAdjusters(getClangSyntaxOnlyAdjuster(), > > + getClangStripDependencyFileAdjuster())); > > +} > > + > > +StandaloneToolExecutor::StandaloneToolExecutor( > > + const CompilationDatabase &Compilations, > > + llvm::ArrayRef<std::string> SourcePaths, > > + std::shared_ptr<PCHContainerOperations> PCHContainerOps) > > + : Tool(Compilations, SourcePaths), Context(&Results), > > + ArgsAdjuster(getDefaultArgumentsAdjusters()) { > > + // Use self-defined default argument adjusters instead of the default > > + // adjusters that come with the old `ClangTool`. > > + Tool.clearArgumentsAdjusters(); > > +} > > + > > +StandaloneToolExecutor::StandaloneToolExecutor( > > + CommonOptionsParser Options, > > + std::shared_ptr<PCHContainerOperations> PCHContainerOps) > > + : OptionsParser(std::move(Options)), > > + Tool(OptionsParser->getCompilations(), > OptionsParser->getSourcePathList(), > > + PCHContainerOps), > > + Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) { > > + Tool.clearArgumentsAdjusters(); > > +} > > + > > +llvm::Error StandaloneToolExecutor::execute( > > + llvm::ArrayRef< > > + std::pair<std::unique_ptr<FrontendActionFactory>, > ArgumentsAdjuster>> > > + Actions) { > > + if (Actions.empty()) > > + return make_string_error("No action to execute."); > > + > > + if (Actions.size() != 1) > > + return make_string_error( > > + "Only support executing exactly 1 action at this point."); > > + > > + auto &Action = Actions.front(); > > + Tool.appendArgumentsAdjuster(Action.second); > > + Tool.appendArgumentsAdjuster(ArgsAdjuster); > > + if (int Ret = Tool.run(Action.first.get())) > > + return make_string_error("Failed to run action."); > > + > > + return llvm::Error::success(); > > +} > > + > > +class StandaloneToolExecutorPlugin : public ToolExecutorPlugin { > > +public: > > + llvm::Expected<std::unique_ptr<ToolExecutor>> > > + create(CommonOptionsParser &OptionsParser) override { > > + if (OptionsParser.getSourcePathList().empty()) > > + return make_string_error( > > + "[StandaloneToolExecutorPlugin] No positional argument > found."); > > + return > llvm::make_unique<StandaloneToolExecutor>(std::move(OptionsParser)); > > + } > > +}; > > + > > +// This anchor is used to force the linker to link in the generated > object file > > +// and thus register the plugin. > > +volatile int ToolExecutorPluginAnchorSource = 0; > > + > > +static ToolExecutorPluginRegistry::Add<StandaloneToolExecutorPlugin> > > + X("standalone", "Runs FrontendActions on a set of files provided " > > + "via positional arguments."); > > + > > +} // end namespace tooling > > +} // end namespace clang > > > > Modified: cfe/trunk/lib/Tooling/Tooling.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Tooling.cpp?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/lib/Tooling/Tooling.cpp (original) > > +++ cfe/trunk/lib/Tooling/Tooling.cpp Thu Oct 26 03:38:14 2017 > > @@ -29,6 +29,7 @@ > > #include "llvm/Config/llvm-config.h" > > #include "llvm/Option/ArgList.h" > > #include "llvm/Option/Option.h" > > +#include "llvm/Support/CommandLine.h" > > #include "llvm/Support/Debug.h" > > #include "llvm/Support/FileSystem.h" > > #include "llvm/Support/Host.h" > > @@ -347,11 +348,7 @@ void ClangTool::mapVirtualFile(StringRef > > } > > > > void ClangTool::appendArgumentsAdjuster(ArgumentsAdjuster Adjuster) { > > - if (ArgsAdjuster) > > - ArgsAdjuster = > > - combineAdjusters(std::move(ArgsAdjuster), std::move(Adjuster)); > > - else > > - ArgsAdjuster = std::move(Adjuster); > > + ArgsAdjuster = combineAdjusters(std::move(ArgsAdjuster), > std::move(Adjuster)); > > } > > > > void ClangTool::clearArgumentsAdjusters() { > > > > Modified: cfe/trunk/unittests/Tooling/CMakeLists.txt > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CMakeLists.txt?rev=316653&r1=316652&r2=316653&view=diff > > > ============================================================================== > > --- cfe/trunk/unittests/Tooling/CMakeLists.txt (original) > > +++ cfe/trunk/unittests/Tooling/CMakeLists.txt Thu Oct 26 03:38:14 2017 > > @@ -16,6 +16,7 @@ add_clang_unittest(ToolingTests > > CommentHandlerTest.cpp > > CompilationDatabaseTest.cpp > > DiagnosticsYamlTest.cpp > > + ExecutionTest.cpp > > FixItTest.cpp > > LexicallyOrderedRecursiveASTVisitorTest.cpp > > LookupTest.cpp > > > > Added: cfe/trunk/unittests/Tooling/ExecutionTest.cpp > > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/ExecutionTest.cpp?rev=316653&view=auto > > > ============================================================================== > > --- cfe/trunk/unittests/Tooling/ExecutionTest.cpp (added) > > +++ cfe/trunk/unittests/Tooling/ExecutionTest.cpp Thu Oct 26 03:38:14 > 2017 > > @@ -0,0 +1,228 @@ > > +//===- unittest/Tooling/ExecutionTest.cpp - Tool execution tests. > --------===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#include "clang/AST/ASTConsumer.h" > > +#include "clang/AST/DeclCXX.h" > > +#include "clang/AST/RecursiveASTVisitor.h" > > +#include "clang/Frontend/ASTUnit.h" > > +#include "clang/Frontend/FrontendAction.h" > > +#include "clang/Frontend/FrontendActions.h" > > +#include "clang/Tooling/CompilationDatabase.h" > > +#include "clang/Tooling/Execution.h" > > +#include "clang/Tooling/StandaloneExecution.h" > > +#include "clang/Tooling/ToolExecutorPluginRegistry.h" > > +#include "clang/Tooling/Tooling.h" > > +#include "gtest/gtest.h" > > +#include <algorithm> > > +#include <string> > > + > > +namespace clang { > > +namespace tooling { > > + > > +namespace { > > + > > +// This traverses the AST and outputs function name as key and "1" as > value for > > +// each function declaration. > > +class ASTConsumerWithResult > > + : public ASTConsumer, > > + public RecursiveASTVisitor<ASTConsumerWithResult> { > > +public: > > + using ASTVisitor = RecursiveASTVisitor<ASTConsumerWithResult>; > > + > > + explicit ASTConsumerWithResult(ExecutionContext *Context) : > Context(Context) { > > + assert(Context != nullptr); > > + } > > + > > + void HandleTranslationUnit(clang::ASTContext &Context) override { > > + TraverseDecl(Context.getTranslationUnitDecl()); > > + } > > + > > + bool TraverseFunctionDecl(clang::FunctionDecl *Decl) { > > + Context->reportResult(Decl->getNameAsString(), "1"); > > + return ASTVisitor::TraverseFunctionDecl(Decl); > > + } > > + > > +private: > > + ExecutionContext *const Context; > > +}; > > + > > +class ReportResultAction : public ASTFrontendAction { > > +public: > > + explicit ReportResultAction(ExecutionContext *Context) : > Context(Context) { > > + assert(Context != nullptr); > > + } > > + > > +protected: > > + std::unique_ptr<clang::ASTConsumer> > > + CreateASTConsumer(clang::CompilerInstance &compiler, > > + StringRef /* dummy */) override { > > + std::unique_ptr<clang::ASTConsumer> ast_consumer{ > > + new ASTConsumerWithResult(Context)}; > > + return ast_consumer; > > + } > > + > > +private: > > + ExecutionContext *const Context; > > +}; > > + > > +class ReportResultActionFactory : public FrontendActionFactory { > > +public: > > + ReportResultActionFactory(ExecutionContext *Context) : > Context(Context) {} > > + FrontendAction *create() override { return new > ReportResultAction(Context); } > > + > > +private: > > + ExecutionContext *const Context; > > +}; > > + > > +} // namespace > > + > > +class TestToolExecutor : public ToolExecutor { > > +public: > > + static const char *ExecutorName; > > + > > + TestToolExecutor(CommonOptionsParser Options) > > + : OptionsParser(std::move(Options)) {} > > + > > + StringRef getExecutorName() const override { return ExecutorName; } > > + > > + llvm::Error > > + > execute(llvm::ArrayRef<std::pair<std::unique_ptr<FrontendActionFactory>, > > + ArgumentsAdjuster>>) override { > > + return llvm::Error::success(); > > + } > > + > > + ExecutionContext *getExecutionContext() override { return nullptr; }; > > + > > + ToolResults *getToolResults() override { return nullptr; } > > + > > + llvm::ArrayRef<std::string> getSourcePaths() const { > > + return OptionsParser.getSourcePathList(); > > + } > > + > > + void mapVirtualFile(StringRef FilePath, StringRef Content) override { > > + VFS[FilePath] = Content; > > + } > > + > > +private: > > + CommonOptionsParser OptionsParser; > > + std::string SourcePaths; > > + std::map<std::string, std::string> VFS; > > +}; > > + > > +const char *TestToolExecutor::ExecutorName = "test-executor"; > > + > > +class TestToolExecutorPlugin : public ToolExecutorPlugin { > > +public: > > + llvm::Expected<std::unique_ptr<ToolExecutor>> > > + create(CommonOptionsParser &OptionsParser) override { > > + return > llvm::make_unique<TestToolExecutor>(std::move(OptionsParser)); > > + } > > +}; > > + > > +// This anchor is used to force the linker to link in the generated > object file > > +// and thus register the plugin. > > +extern volatile int ToolExecutorPluginAnchorSource; > > + > > +static int LLVM_ATTRIBUTE_UNUSED TestToolExecutorPluginAnchorDest = > > + ToolExecutorPluginAnchorSource; > > + > > +static ToolExecutorPluginRegistry::Add<TestToolExecutorPlugin> > > + X("test-executor", "Plugin for TestToolExecutor."); > > + > > +llvm::cl::OptionCategory TestCategory("execution-test options"); > > + > > +TEST(CreateToolExecutorTest, FailedCreateExecutorUndefinedFlag) { > > + std::vector<const char *> argv = {"prog", "--fake_flag_no_no_no", > "f"}; > > + int argc = argv.size(); > > + auto Executor = > > + createExecutorFromCommandLineArgs(argc, &argv[0], TestCategory); > > + ASSERT_FALSE((bool)Executor); > > + llvm::consumeError(Executor.takeError()); > > +} > > + > > +TEST(CreateToolExecutorTest, RegisterFlagsBeforeReset) { > > + llvm::cl::opt<std::string> BeforeReset( > > + "before_reset", llvm::cl::desc("Defined before reset."), > > + llvm::cl::init("")); > > + > > + llvm::cl::ResetAllOptionOccurrences(); > > + > > + std::vector<const char *> argv = {"prog", "--before_reset=set", "f"}; > > + int argc = argv.size(); > > + auto Executor = > > + createExecutorFromCommandLineArgs(argc, &argv[0], TestCategory); > > + ASSERT_TRUE((bool)Executor); > > + EXPECT_EQ(BeforeReset, "set"); > > + BeforeReset.removeArgument(); > > +} > > + > > +TEST(CreateToolExecutorTest, CreateStandaloneToolExecutor) { > > + std::vector<const char *> argv = {"prog", "standalone.cpp"}; > > + int argc = argv.size(); > > + auto Executor = > > + createExecutorFromCommandLineArgs(argc, &argv[0], TestCategory); > > + ASSERT_TRUE((bool)Executor); > > + EXPECT_EQ(Executor->get()->getExecutorName(), > > + StandaloneToolExecutor::ExecutorName); > > +} > > + > > +TEST(CreateToolExecutorTest, CreateTestToolExecutor) { > > + std::vector<const char *> argv = {"prog", "test.cpp", > > + "--executor=test-executor"}; > > + int argc = argv.size(); > > + auto Executor = > > + createExecutorFromCommandLineArgs(argc, &argv[0], TestCategory); > > + ASSERT_TRUE((bool)Executor); > > + EXPECT_EQ(Executor->get()->getExecutorName(), > TestToolExecutor::ExecutorName); > > +} > > + > > +TEST(StandaloneToolTest, SynctaxOnlyActionOnSimpleCode) { > > + FixedCompilationDatabase Compilations("/", > std::vector<std::string>()); > > + StandaloneToolExecutor Executor(Compilations, > > + std::vector<std::string>(1, "/a.cc")); > > + Executor.mapVirtualFile("/a.cc", "int x = 0;"); > > + > > + auto Err = > Executor.execute(newFrontendActionFactory<SyntaxOnlyAction>(), > > + getClangSyntaxOnlyAdjuster()); > > + ASSERT_TRUE(!Err); > > +} > > + > > +TEST(StandaloneToolTest, SimpleAction) { > > + FixedCompilationDatabase Compilations("/", > std::vector<std::string>()); > > + StandaloneToolExecutor Executor(Compilations, > > + std::vector<std::string>(1, "/a.cc")); > > + Executor.mapVirtualFile("/a.cc", "int x = 0;"); > > + > > + auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>( > > + new ReportResultActionFactory(Executor.getExecutionContext()))); > > + ASSERT_TRUE(!Err); > > + auto KVs = Executor.getToolResults()->AllKVResults(); > > + ASSERT_EQ(KVs.size(), 0u); > > +} > > + > > +TEST(StandaloneToolTest, SimpleActionWithResult) { > > + FixedCompilationDatabase Compilations("/", > std::vector<std::string>()); > > + StandaloneToolExecutor Executor(Compilations, > > + std::vector<std::string>(1, "/a.cc")); > > + Executor.mapVirtualFile("/a.cc", "int x = 0; void f() {}"); > > + > > + auto Err = Executor.execute(std::unique_ptr<FrontendActionFactory>( > > + new ReportResultActionFactory(Executor.getExecutionContext()))); > > + ASSERT_TRUE(!Err); > > + auto KVs = Executor.getToolResults()->AllKVResults(); > > + ASSERT_EQ(KVs.size(), 1u); > > + EXPECT_EQ("f", KVs[0].first); > > + EXPECT_EQ("1", KVs[0].second); > > + > > + Executor.getToolResults()->forEachResult( > > + [](StringRef, StringRef Value) { EXPECT_EQ("1", Value); }); > > +} > > + > > +} // end namespace tooling > > +} // end namespace clang > > > > > > _______________________________________________ > > cfe-commits mailing list > > cfe-commits@lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits