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 
12 namespace clang {
13 namespace tooling {
14 
15 static llvm::Error make_string_error(const llvm::Twine &Message) {
16   return llvm::make_error<llvm::StringError>(Message,
17                                              llvm::inconvertibleErrorCode());
18 }
19 
20 const char *StandaloneToolExecutor::ExecutorName = "StandaloneToolExecutor";
21 
22 static ArgumentsAdjuster getDefaultArgumentsAdjusters() {
23   return combineAdjusters(
24       getClangStripOutputAdjuster(),
25       combineAdjusters(getClangSyntaxOnlyAdjuster(),
26                        getClangStripDependencyFileAdjuster()));
27 }
28 
29 StandaloneToolExecutor::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 
42 StandaloneToolExecutor::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 
52 llvm::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("No action to execute.");
58 
59   if (Actions.size() != 1)
60     return make_string_error(
61         "Only support executing exactly 1 action at this point.");
62 
63   auto &Action = Actions.front();
64   Tool.appendArgumentsAdjuster(Action.second);
65   Tool.appendArgumentsAdjuster(ArgsAdjuster);
66   if (Tool.run(Action.first.get()))
67     return make_string_error("Failed to run action.");
68 
69   return llvm::Error::success();
70 }
71 
72 class StandaloneToolExecutorPlugin : public ToolExecutorPlugin {
73 public:
74   llvm::Expected<std::unique_ptr<ToolExecutor>>
75   create(CommonOptionsParser &OptionsParser) override {
76     if (OptionsParser.getSourcePathList().empty())
77       return make_string_error(
78           "[StandaloneToolExecutorPlugin] No positional argument found.");
79     return std::make_unique<StandaloneToolExecutor>(std::move(OptionsParser));
80   }
81 };
82 
83 static 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.
89 volatile int StandaloneToolExecutorAnchorSource = 0;
90 
91 } // end namespace tooling
92 } // end namespace clang
93