/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ExecuteCompilerInvocation.cpp ------------------------------------===// |
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 | | // This file holds ExecuteCompilerInvocation(). It is split into its own file to |
10 | | // minimize the impact of pulling in essentially everything else in Clang. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/ARCMigrate/ARCMTActions.h" |
15 | | #include "clang/CodeGen/CodeGenAction.h" |
16 | | #include "clang/Config/config.h" |
17 | | #include "clang/Driver/Options.h" |
18 | | #include "clang/Frontend/CompilerInstance.h" |
19 | | #include "clang/Frontend/CompilerInvocation.h" |
20 | | #include "clang/Frontend/FrontendActions.h" |
21 | | #include "clang/Frontend/FrontendDiagnostic.h" |
22 | | #include "clang/Frontend/FrontendPluginRegistry.h" |
23 | | #include "clang/Frontend/Utils.h" |
24 | | #include "clang/FrontendTool/Utils.h" |
25 | | #include "clang/Rewrite/Frontend/FrontendActions.h" |
26 | | #include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h" |
27 | | #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" |
28 | | #include "llvm/Option/OptTable.h" |
29 | | #include "llvm/Option/Option.h" |
30 | | #include "llvm/Support/BuryPointer.h" |
31 | | #include "llvm/Support/DynamicLibrary.h" |
32 | | #include "llvm/Support/ErrorHandling.h" |
33 | | using namespace clang; |
34 | | using namespace llvm::opt; |
35 | | |
36 | | namespace clang { |
37 | | |
38 | | static std::unique_ptr<FrontendAction> |
39 | 40.0k | CreateFrontendBaseAction(CompilerInstance &CI) { |
40 | 40.0k | using namespace clang::frontend; |
41 | 40.0k | StringRef Action("unknown"); |
42 | 40.0k | (void)Action; |
43 | | |
44 | 40.0k | switch (CI.getFrontendOpts().ProgramAction) { |
45 | 0 | case ASTDeclList: return std::make_unique<ASTDeclListAction>(); |
46 | 408 | case ASTDump: return std::make_unique<ASTDumpAction>(); |
47 | 532 | case ASTPrint: return std::make_unique<ASTPrintAction>(); |
48 | 0 | case ASTView: return std::make_unique<ASTViewAction>(); |
49 | 3 | case DumpCompilerOptions: |
50 | 3 | return std::make_unique<DumpCompilerOptionsAction>(); |
51 | 0 | case DumpRawTokens: return std::make_unique<DumpRawTokensAction>(); |
52 | 3 | case DumpTokens: return std::make_unique<DumpTokensAction>(); |
53 | 587 | case EmitAssembly: return std::make_unique<EmitAssemblyAction>(); |
54 | 570 | case EmitBC: return std::make_unique<EmitBCAction>(); |
55 | 3 | case EmitHTML: return std::make_unique<HTMLPrintAction>(); |
56 | 13.1k | case EmitLLVM: return std::make_unique<EmitLLVMAction>(); |
57 | 243 | case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>(); |
58 | 3 | case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>(); |
59 | 3.42k | case EmitObj: return std::make_unique<EmitObjAction>(); |
60 | 63 | case FixIt: return std::make_unique<FixItAction>(); |
61 | 201 | case GenerateModule: |
62 | 201 | return std::make_unique<GenerateModuleFromModuleMapAction>(); |
63 | 49 | case GenerateModuleInterface: |
64 | 49 | return std::make_unique<GenerateModuleInterfaceAction>(); |
65 | 6 | case GenerateHeaderModule: |
66 | 6 | return std::make_unique<GenerateHeaderModuleAction>(); |
67 | 3.10k | case GeneratePCH: return std::make_unique<GeneratePCHAction>(); |
68 | 70 | case GenerateInterfaceStubs: |
69 | 70 | return std::make_unique<GenerateInterfaceStubsAction>(); |
70 | 0 | case InitOnly: return std::make_unique<InitOnlyAction>(); |
71 | 11.1k | case ParseSyntaxOnly: return std::make_unique<SyntaxOnlyAction>(); |
72 | 5 | case ModuleFileInfo: return std::make_unique<DumpModuleInfoAction>(); |
73 | 7 | case VerifyPCH: return std::make_unique<VerifyPCHAction>(); |
74 | 11 | case TemplightDump: return std::make_unique<TemplightDumpAction>(); |
75 | | |
76 | 1 | case PluginAction: { |
77 | 1 | for (const FrontendPluginRegistry::entry &Plugin : |
78 | 0 | FrontendPluginRegistry::entries()) { |
79 | 0 | if (Plugin.getName() == CI.getFrontendOpts().ActionName) { |
80 | 0 | std::unique_ptr<PluginASTAction> P(Plugin.instantiate()); |
81 | 0 | if ((P->getActionType() != PluginASTAction::ReplaceAction && |
82 | 0 | P->getActionType() != PluginASTAction::Cmdline) || |
83 | 0 | !P->ParseArgs( |
84 | 0 | CI, |
85 | 0 | CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())])) |
86 | 0 | return nullptr; |
87 | 0 | return std::move(P); |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | 1 | CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) |
92 | 1 | << CI.getFrontendOpts().ActionName; |
93 | 1 | return nullptr; |
94 | 1 | } |
95 | | |
96 | 2 | case PrintPreamble: return std::make_unique<PrintPreambleAction>(); |
97 | 2.02k | case PrintPreprocessedInput: { |
98 | 2.02k | if (CI.getPreprocessorOutputOpts().RewriteIncludes || |
99 | 1.98k | CI.getPreprocessorOutputOpts().RewriteImports) |
100 | 50 | return std::make_unique<RewriteIncludesAction>(); |
101 | 1.97k | return std::make_unique<PrintPreprocessedAction>(); |
102 | 1.97k | } |
103 | | |
104 | 1 | case RewriteMacros: return std::make_unique<RewriteMacrosAction>(); |
105 | 0 | case RewriteTest: return std::make_unique<RewriteTestAction>(); |
106 | 1.97k | #if CLANG_ENABLE_OBJC_REWRITER |
107 | 164 | case RewriteObjC: return std::make_unique<RewriteObjCAction>(); |
108 | | #else |
109 | | case RewriteObjC: Action = "RewriteObjC"; break; |
110 | | #endif |
111 | 1.97k | #if CLANG_ENABLE_ARCMT |
112 | 8 | case MigrateSource: |
113 | 8 | return std::make_unique<arcmt::MigrateSourceAction>(); |
114 | | #else |
115 | | case MigrateSource: Action = "MigrateSource"; break; |
116 | | #endif |
117 | 1.97k | #if CLANG_ENABLE_STATIC_ANALYZER |
118 | 1.31k | case RunAnalysis: return std::make_unique<ento::AnalysisAction>(); |
119 | | #else |
120 | | case RunAnalysis: Action = "RunAnalysis"; break; |
121 | | #endif |
122 | 2.95k | case RunPreprocessorOnly: return std::make_unique<PreprocessOnlyAction>(); |
123 | 7 | case PrintDependencyDirectivesSourceMinimizerOutput: |
124 | 7 | return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>(); |
125 | 0 | } |
126 | | |
127 | | #if !CLANG_ENABLE_ARCMT || !CLANG_ENABLE_STATIC_ANALYZER \ |
128 | | || !CLANG_ENABLE_OBJC_REWRITER |
129 | | CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; |
130 | | return 0; |
131 | | #else |
132 | 0 | llvm_unreachable("Invalid program action!"); |
133 | 0 | #endif |
134 | 0 | } |
135 | | |
136 | | std::unique_ptr<FrontendAction> |
137 | 40.0k | CreateFrontendAction(CompilerInstance &CI) { |
138 | | // Create the underlying action. |
139 | 40.0k | std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI); |
140 | 40.0k | if (!Act) |
141 | 1 | return nullptr; |
142 | | |
143 | 40.0k | const FrontendOptions &FEOpts = CI.getFrontendOpts(); |
144 | | |
145 | 40.0k | if (FEOpts.FixAndRecompile) { |
146 | 3 | Act = std::make_unique<FixItRecompile>(std::move(Act)); |
147 | 3 | } |
148 | | |
149 | 40.0k | #if CLANG_ENABLE_ARCMT |
150 | 40.0k | if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource && |
151 | 40.0k | CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) { |
152 | | // Potentially wrap the base FE action in an ARC Migrate Tool action. |
153 | 36.9k | switch (FEOpts.ARCMTAction) { |
154 | 36.9k | case FrontendOptions::ARCMT_None: |
155 | 36.9k | break; |
156 | 15 | case FrontendOptions::ARCMT_Check: |
157 | 15 | Act = std::make_unique<arcmt::CheckAction>(std::move(Act)); |
158 | 15 | break; |
159 | 2 | case FrontendOptions::ARCMT_Modify: |
160 | 2 | Act = std::make_unique<arcmt::ModifyAction>(std::move(Act)); |
161 | 2 | break; |
162 | 8 | case FrontendOptions::ARCMT_Migrate: |
163 | 8 | Act = std::make_unique<arcmt::MigrateAction>(std::move(Act), |
164 | 8 | FEOpts.MTMigrateDir, |
165 | 8 | FEOpts.ARCMTMigrateReportOut, |
166 | 8 | FEOpts.ARCMTMigrateEmitARCErrors); |
167 | 8 | break; |
168 | 36.9k | } |
169 | | |
170 | 36.9k | if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) { |
171 | 21 | Act = std::make_unique<arcmt::ObjCMigrateAction>(std::move(Act), |
172 | 21 | FEOpts.MTMigrateDir, |
173 | 21 | FEOpts.ObjCMTAction); |
174 | 21 | } |
175 | 36.9k | } |
176 | 40.0k | #endif |
177 | | |
178 | | // If there are any AST files to merge, create a frontend action |
179 | | // adaptor to perform the merge. |
180 | 40.0k | if (!FEOpts.ASTMergeFiles.empty()) |
181 | 33 | Act = std::make_unique<ASTMergeAction>(std::move(Act), |
182 | 33 | FEOpts.ASTMergeFiles); |
183 | | |
184 | 40.0k | return Act; |
185 | 40.0k | } |
186 | | |
187 | 40.1k | bool ExecuteCompilerInvocation(CompilerInstance *Clang) { |
188 | | // Honor -help. |
189 | 40.1k | if (Clang->getFrontendOpts().ShowHelp) { |
190 | 1 | driver::getDriverOptTable().PrintHelp( |
191 | 1 | llvm::outs(), "clang -cc1 [options] file...", |
192 | 1 | "LLVM 'Clang' Compiler: http://clang.llvm.org", |
193 | 1 | /*Include=*/driver::options::CC1Option, |
194 | 1 | /*Exclude=*/0, /*ShowAllAliases=*/false); |
195 | 1 | return true; |
196 | 1 | } |
197 | | |
198 | | // Honor -version. |
199 | | // |
200 | | // FIXME: Use a better -version message? |
201 | 40.1k | if (Clang->getFrontendOpts().ShowVersion) { |
202 | 1 | llvm::cl::PrintVersionMessage(); |
203 | 1 | return true; |
204 | 1 | } |
205 | | |
206 | | // Load any requested plugins. |
207 | 40.1k | for (const std::string &Path : Clang->getFrontendOpts().Plugins) { |
208 | 0 | std::string Error; |
209 | 0 | if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) |
210 | 0 | Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) |
211 | 0 | << Path << Error; |
212 | 0 | } |
213 | | |
214 | | // Check if any of the loaded plugins replaces the main AST action |
215 | 40.1k | for (const FrontendPluginRegistry::entry &Plugin : |
216 | 0 | FrontendPluginRegistry::entries()) { |
217 | 0 | std::unique_ptr<PluginASTAction> P(Plugin.instantiate()); |
218 | 0 | if (P->getActionType() == PluginASTAction::ReplaceAction) { |
219 | 0 | Clang->getFrontendOpts().ProgramAction = clang::frontend::PluginAction; |
220 | 0 | Clang->getFrontendOpts().ActionName = Plugin.getName().str(); |
221 | 0 | break; |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | | // Honor -mllvm. |
226 | | // |
227 | | // FIXME: Remove this, one day. |
228 | | // This should happen AFTER plugins have been loaded! |
229 | 40.1k | if (!Clang->getFrontendOpts().LLVMArgs.empty()) { |
230 | 345 | unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); |
231 | 345 | auto Args = std::make_unique<const char*[]>(NumArgs + 2); |
232 | 345 | Args[0] = "clang (LLVM option parsing)"; |
233 | 714 | for (unsigned i = 0; i != NumArgs; ++i369 ) |
234 | 369 | Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); |
235 | 345 | Args[NumArgs + 1] = nullptr; |
236 | 345 | llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); |
237 | 345 | } |
238 | | |
239 | 40.1k | #if CLANG_ENABLE_STATIC_ANALYZER |
240 | | // These should happen AFTER plugins have been loaded! |
241 | | |
242 | 40.1k | AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts(); |
243 | | |
244 | | // Honor -analyzer-checker-help and -analyzer-checker-help-hidden. |
245 | 40.1k | if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha40.1k || |
246 | 40.1k | AnOpts.ShowCheckerHelpDeveloper) { |
247 | 9 | ento::printCheckerHelp(llvm::outs(), *Clang); |
248 | 9 | return true; |
249 | 9 | } |
250 | | |
251 | | // Honor -analyzer-checker-option-help. |
252 | 40.1k | if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList40.1k || |
253 | 40.1k | AnOpts.ShowCheckerOptionDeveloperList) { |
254 | 7 | ento::printCheckerConfigList(llvm::outs(), *Clang); |
255 | 7 | return true; |
256 | 7 | } |
257 | | |
258 | | // Honor -analyzer-list-enabled-checkers. |
259 | 40.1k | if (AnOpts.ShowEnabledCheckerList) { |
260 | 4 | ento::printEnabledCheckerList(llvm::outs(), *Clang); |
261 | 4 | return true; |
262 | 4 | } |
263 | | |
264 | | // Honor -analyzer-config-help. |
265 | 40.1k | if (AnOpts.ShowConfigOptionsList) { |
266 | 1 | ento::printAnalyzerConfigList(llvm::outs()); |
267 | 1 | return true; |
268 | 1 | } |
269 | 40.1k | #endif |
270 | | |
271 | | // If there were errors in processing arguments, don't do anything else. |
272 | 40.1k | if (Clang->getDiagnostics().hasErrorOccurred()) |
273 | 66 | return false; |
274 | | // Create and execute the frontend action. |
275 | 40.0k | std::unique_ptr<FrontendAction> Act(CreateFrontendAction(*Clang)); |
276 | 40.0k | if (!Act) |
277 | 1 | return false; |
278 | 40.0k | bool Success = Clang->ExecuteAction(*Act); |
279 | 40.0k | if (Clang->getFrontendOpts().DisableFree) |
280 | 8.31k | llvm::BuryPointer(std::move(Act)); |
281 | 40.0k | return Success; |
282 | 40.0k | } |
283 | | |
284 | | } // namespace clang |