1//===- lib/Tooling/Execution.cpp - Standalone clang action execution. -----===//
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/StandaloneExecution.h"
10#include "clang/Tooling/ToolExecutorPluginRegistry.h"
11
12namespace clang {
13namespace tooling {
14
15static llvm::Error make_string_error(const llvm::Twine &Message) {
16 return llvm::make_error<llvm::StringError>(Args: Message,
17 Args: llvm::inconvertibleErrorCode());
18}
19
20const char *StandaloneToolExecutor::ExecutorName = "StandaloneToolExecutor";
21
22static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
23 return combineAdjusters(
24 First: getClangStripOutputAdjuster(),
25 Second: combineAdjusters(First: getClangSyntaxOnlyAdjuster(),
26 Second: getClangStripDependencyFileAdjuster()));
27}
28
29StandaloneToolExecutor::StandaloneToolExecutor(
30 const CompilationDatabase &Compilations,
31 llvm::ArrayRef<std::string> SourcePaths,
32 IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS,
33 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
34 : Tool(Compilations, SourcePaths, std::move(PCHContainerOps),
35 std::move(BaseFS)),
36 Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
37 // Use self-defined default argument adjusters instead of the default
38 // adjusters that come with the old `ClangTool`.
39 Tool.clearArgumentsAdjusters();
40}
41
42StandaloneToolExecutor::StandaloneToolExecutor(
43 CommonOptionsParser Options,
44 std::shared_ptr<PCHContainerOperations> PCHContainerOps)
45 : OptionsParser(std::move(Options)),
46 Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(),
47 std::move(PCHContainerOps)),
48 Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
49 Tool.clearArgumentsAdjusters();
50}
51
52llvm::Error StandaloneToolExecutor::execute(
53 llvm::ArrayRef<
54 std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
55 Actions) {
56 if (Actions.empty())
57 return make_string_error(Message: "No action to execute.");
58
59 if (Actions.size() != 1)
60 return make_string_error(
61 Message: "Only support executing exactly 1 action at this point.");
62
63 auto &Action = Actions.front();
64 Tool.appendArgumentsAdjuster(Adjuster: Action.second);
65 Tool.appendArgumentsAdjuster(Adjuster: ArgsAdjuster);
66 if (Tool.run(Action: Action.first.get()))
67 return make_string_error(Message: "Failed to run action.");
68
69 return llvm::Error::success();
70}
71
72class StandaloneToolExecutorPlugin : public ToolExecutorPlugin {
73public:
74 llvm::Expected<std::unique_ptr<ToolExecutor>>
75 create(CommonOptionsParser &OptionsParser) override {
76 if (OptionsParser.getSourcePathList().empty())
77 return make_string_error(
78 Message: "[StandaloneToolExecutorPlugin] No positional argument found.");
79 return std::make_unique<StandaloneToolExecutor>(args: std::move(OptionsParser));
80 }
81};
82
83static ToolExecutorPluginRegistry::Add<StandaloneToolExecutorPlugin>
84 X("standalone", "Runs FrontendActions on a set of files provided "
85 "via positional arguments.");
86
87// This anchor is used to force the linker to link in the generated object file
88// and thus register the plugin.
89volatile int StandaloneToolExecutorAnchorSource = 0;
90
91} // end namespace tooling
92} // end namespace clang
93