1//===- lib/Tooling/Execution.cpp - Implements tool execution framework. ---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Tooling/Execution.h"
10#include "clang/Support/Compiler.h"
11#include "clang/Tooling/ToolExecutorPluginRegistry.h"
12#include "clang/Tooling/Tooling.h"
13
14LLVM_INSTANTIATE_REGISTRY_EX(CLANG_ABI_EXPORT,
15 clang::tooling::ToolExecutorPluginRegistry)
16
17namespace clang {
18namespace tooling {
19
20llvm::cl::opt<std::string>
21 ExecutorName("executor", llvm::cl::desc("The name of the executor to use."),
22 llvm::cl::init(Val: "standalone"));
23
24void InMemoryToolResults::addResult(StringRef Key, StringRef Value) {
25 KVResults.push_back(x: {Strings.save(S: Key), Strings.save(S: Value)});
26}
27
28std::vector<std::pair<llvm::StringRef, llvm::StringRef>>
29InMemoryToolResults::AllKVResults() {
30 return KVResults;
31}
32
33void InMemoryToolResults::forEachResult(
34 llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) {
35 for (const auto &KV : KVResults) {
36 Callback(KV.first, KV.second);
37 }
38}
39
40void ExecutionContext::reportResult(StringRef Key, StringRef Value) {
41 Results->addResult(Key, Value);
42}
43
44llvm::Error
45ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action) {
46 return execute(Action: std::move(Action), Adjuster: ArgumentsAdjuster());
47}
48
49llvm::Error ToolExecutor::execute(std::unique_ptr<FrontendActionFactory> Action,
50 ArgumentsAdjuster Adjuster) {
51 std::vector<
52 std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
53 Actions;
54 Actions.emplace_back(args: std::move(Action), args: std::move(Adjuster));
55 return execute(Actions);
56}
57
58namespace internal {
59llvm::Expected<std::unique_ptr<ToolExecutor>>
60createExecutorFromCommandLineArgsImpl(int &argc, const char **argv,
61 llvm::cl::OptionCategory &Category,
62 const char *Overview) {
63 auto OptionsParser =
64 CommonOptionsParser::create(argc, argv, Category, OccurrencesFlag: llvm::cl::ZeroOrMore,
65 /*Overview=*/Overview);
66 if (!OptionsParser)
67 return OptionsParser.takeError();
68 for (const auto &TEPlugin : ToolExecutorPluginRegistry::entries()) {
69 if (TEPlugin.getName() != ExecutorName) {
70 continue;
71 }
72 std::unique_ptr<ToolExecutorPlugin> Plugin(TEPlugin.instantiate());
73 llvm::Expected<std::unique_ptr<ToolExecutor>> Executor =
74 Plugin->create(OptionsParser&: *OptionsParser);
75 if (!Executor) {
76 return llvm::make_error<llvm::StringError>(
77 Args: llvm::Twine("Failed to create '") + TEPlugin.getName() +
78 "': " + llvm::toString(E: Executor.takeError()) + "\n",
79 Args: llvm::inconvertibleErrorCode());
80 }
81 return std::move(*Executor);
82 }
83 return llvm::make_error<llvm::StringError>(
84 Args: llvm::Twine("Executor \"") + ExecutorName + "\" is not registered.",
85 Args: llvm::inconvertibleErrorCode());
86}
87} // end namespace internal
88
89llvm::Expected<std::unique_ptr<ToolExecutor>>
90createExecutorFromCommandLineArgs(int &argc, const char **argv,
91 llvm::cl::OptionCategory &Category,
92 const char *Overview) {
93 return internal::createExecutorFromCommandLineArgsImpl(argc, argv, Category,
94 Overview);
95}
96
97// This anchor is used to force the linker to link in the generated object file
98// and thus register the StandaloneToolExecutorPlugin etc.
99extern volatile int StandaloneToolExecutorAnchorSource;
100extern volatile int AllTUsToolExecutorAnchorSource;
101[[maybe_unused]] static int StandaloneToolExecutorAnchorDest =
102 StandaloneToolExecutorAnchorSource;
103[[maybe_unused]] static int AllTUsToolExecutorAnchorDest =
104 AllTUsToolExecutorAnchorSource;
105
106} // end namespace tooling
107} // end namespace clang
108