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     IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
34     std::shared_ptr<PCHContainerOperations> PCHContainerOps)
35     : Tool(Compilations, SourcePaths, std::move(PCHContainerOps),
36            std::move(BaseFS)),
37       Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
38   // Use self-defined default argument adjusters instead of the default
39   // adjusters that come with the old `ClangTool`.
40   Tool.clearArgumentsAdjusters();
41 }
42 
43 StandaloneToolExecutor::StandaloneToolExecutor(
44     CommonOptionsParser Options,
45     std::shared_ptr<PCHContainerOperations> PCHContainerOps)
46     : OptionsParser(std::move(Options)),
47       Tool(OptionsParser->getCompilations(), OptionsParser->getSourcePathList(),
48            std::move(PCHContainerOps)),
49       Context(&Results), ArgsAdjuster(getDefaultArgumentsAdjusters()) {
50   Tool.clearArgumentsAdjusters();
51 }
52 
53 llvm::Error StandaloneToolExecutor::execute(
54     llvm::ArrayRef<
55         std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
56         Actions) {
57   if (Actions.empty())
58     return make_string_error("No action to execute.");
59 
60   if (Actions.size() != 1)
61     return make_string_error(
62         "Only support executing exactly 1 action at this point.");
63 
64   auto &Action = Actions.front();
65   Tool.appendArgumentsAdjuster(Action.second);
66   Tool.appendArgumentsAdjuster(ArgsAdjuster);
67   if (Tool.run(Action.first.get()))
68     return make_string_error("Failed to run action.");
69 
70   return llvm::Error::success();
71 }
72 
73 class StandaloneToolExecutorPlugin : public ToolExecutorPlugin {
74 public:
75   llvm::Expected<std::unique_ptr<ToolExecutor>>
76   create(CommonOptionsParser &OptionsParser) override {
77     if (OptionsParser.getSourcePathList().empty())
78       return make_string_error(
79           "[StandaloneToolExecutorPlugin] No positional argument found.");
80     return llvm::make_unique<StandaloneToolExecutor>(std::move(OptionsParser));
81   }
82 };
83 
84 static ToolExecutorPluginRegistry::Add<StandaloneToolExecutorPlugin>
85     X("standalone", "Runs FrontendActions on a set of files provided "
86                     "via positional arguments.");
87 
88 // This anchor is used to force the linker to link in the generated object file
89 // and thus register the plugin.
90 volatile int StandaloneToolExecutorAnchorSource = 0;
91 
92 } // end namespace tooling
93 } // end namespace clang
94