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