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/Basic/DiagnosticFrontend.h"
15#include "clang/CodeGen/CodeGenAction.h"
16#include "clang/Config/config.h"
17#include "clang/ExtractAPI/FrontendActions.h"
18#include "clang/Frontend/CompilerInstance.h"
19#include "clang/Frontend/CompilerInvocation.h"
20#include "clang/Frontend/FrontendActions.h"
21#include "clang/Frontend/FrontendPluginRegistry.h"
22#include "clang/Frontend/SSAFOptions.h"
23#include "clang/Frontend/Utils.h"
24#include "clang/FrontendTool/Utils.h"
25#include "clang/Options/Options.h"
26#include "clang/Rewrite/Frontend/FrontendActions.h"
27#include "clang/ScalableStaticAnalysis/Frontend/SourceTransformationFrontendAction.h"
28#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
29#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
30#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
31#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
32#include "llvm/Option/OptTable.h"
33#include "llvm/Support/BuryPointer.h"
34#include "llvm/Support/DynamicLibrary.h"
35#include "llvm/Support/ErrorHandling.h"
36
37#if CLANG_ENABLE_CIR
38#include "mlir/IR/AsmState.h"
39#include "mlir/IR/MLIRContext.h"
40#include "mlir/Pass/PassManager.h"
41#include "clang/CIR/Dialect/Passes.h"
42#include "clang/CIR/FrontendAction/CIRGenAction.h"
43#endif
44
45using namespace clang;
46using namespace llvm::opt;
47
48namespace clang {
49
50static std::unique_ptr<FrontendAction>
51CreateFrontendBaseAction(CompilerInstance &CI) {
52 using namespace clang::frontend;
53 StringRef Action("unknown");
54 (void)Action;
55
56 unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
57 frontend::ActionKind Act = CI.getFrontendOpts().ProgramAction;
58 bool EmitsCIR = Act == EmitCIR;
59
60 if (!UseCIR && EmitsCIR)
61 llvm::report_fatal_error(reason: "-emit-cir and only valid when using -fclangir");
62
63 switch (CI.getFrontendOpts().ProgramAction) {
64 case ASTDeclList: return std::make_unique<ASTDeclListAction>();
65 case ASTDump: return std::make_unique<ASTDumpAction>();
66 case ASTPrint: return std::make_unique<ASTPrintAction>();
67 case ASTView: return std::make_unique<ASTViewAction>();
68 case DumpCompilerOptions:
69 return std::make_unique<DumpCompilerOptionsAction>();
70 case DumpRawTokens: return std::make_unique<DumpRawTokensAction>();
71 case DumpTokens: return std::make_unique<DumpTokensAction>();
72 case EmitAssembly:
73#if CLANG_ENABLE_CIR
74 if (UseCIR)
75 return std::make_unique<cir::EmitAssemblyAction>();
76#endif
77 return std::make_unique<EmitAssemblyAction>();
78 case EmitBC:
79#if CLANG_ENABLE_CIR
80 if (UseCIR)
81 return std::make_unique<cir::EmitBCAction>();
82#endif
83 return std::make_unique<EmitBCAction>();
84 case EmitCIR:
85#if CLANG_ENABLE_CIR
86 return std::make_unique<cir::EmitCIRAction>();
87#else
88 CI.getDiagnostics().Report(DiagID: diag::err_fe_cir_not_built);
89 return nullptr;
90#endif
91 case EmitHTML: return std::make_unique<HTMLPrintAction>();
92 case EmitLLVM: {
93#if CLANG_ENABLE_CIR
94 if (UseCIR)
95 return std::make_unique<cir::EmitLLVMAction>();
96#endif
97 return std::make_unique<EmitLLVMAction>();
98 }
99 case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>();
100 case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>();
101 case EmitObj:
102#if CLANG_ENABLE_CIR
103 if (UseCIR)
104 return std::make_unique<cir::EmitObjAction>();
105#endif
106 return std::make_unique<EmitObjAction>();
107 case ExtractAPI:
108 return std::make_unique<ExtractAPIAction>();
109 case FixIt: return std::make_unique<FixItAction>();
110 case GenerateModule:
111 return std::make_unique<GenerateModuleFromModuleMapAction>();
112 case GenerateModuleInterface:
113 return std::make_unique<GenerateModuleInterfaceAction>();
114 case GenerateReducedModuleInterface:
115 return std::make_unique<GenerateReducedModuleInterfaceAction>();
116 case GenerateHeaderUnit:
117 return std::make_unique<GenerateHeaderUnitAction>();
118 case GeneratePCH: return std::make_unique<GeneratePCHAction>();
119 case GenerateInterfaceStubs:
120 return std::make_unique<GenerateInterfaceStubsAction>();
121 case InitOnly: return std::make_unique<InitOnlyAction>();
122 case ParseSyntaxOnly: return std::make_unique<SyntaxOnlyAction>();
123 case ModuleFileInfo: return std::make_unique<DumpModuleInfoAction>();
124 case VerifyPCH:
125 return std::make_unique<VerifyPCHAction>();
126
127 case PluginAction: {
128 for (const FrontendPluginRegistry::entry &Plugin :
129 FrontendPluginRegistry::entries()) {
130 if (Plugin.getName() == CI.getFrontendOpts().ActionName) {
131 std::unique_ptr<PluginASTAction> P(Plugin.instantiate());
132 if ((P->getActionType() != PluginASTAction::ReplaceAction &&
133 P->getActionType() != PluginASTAction::CmdlineAfterMainAction) ||
134 !P->ParseArgs(
135 CI,
136 arg: CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))
137 return nullptr;
138 return std::move(P);
139 }
140 }
141
142 CI.getDiagnostics().Report(DiagID: diag::err_fe_invalid_plugin_name)
143 << CI.getFrontendOpts().ActionName;
144 return nullptr;
145 }
146
147 case PrintPreamble: return std::make_unique<PrintPreambleAction>();
148 case PrintPreprocessedInput: {
149 if (CI.getPreprocessorOutputOpts().RewriteIncludes ||
150 CI.getPreprocessorOutputOpts().RewriteImports)
151 return std::make_unique<RewriteIncludesAction>();
152 return std::make_unique<PrintPreprocessedAction>();
153 }
154
155 case RewriteMacros: return std::make_unique<RewriteMacrosAction>();
156 case RewriteTest: return std::make_unique<RewriteTestAction>();
157#if CLANG_ENABLE_OBJC_REWRITER
158 case RewriteObjC: return std::make_unique<RewriteObjCAction>();
159#else
160 case RewriteObjC: Action = "RewriteObjC"; break;
161#endif
162#if CLANG_ENABLE_STATIC_ANALYZER
163 case RunAnalysis: return std::make_unique<ento::AnalysisAction>();
164#else
165 case RunAnalysis: Action = "RunAnalysis"; break;
166#endif
167 case RunPreprocessorOnly: return std::make_unique<PreprocessOnlyAction>();
168 case PrintDependencyDirectivesSourceMinimizerOutput:
169 return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>();
170 }
171
172#if !CLANG_ENABLE_STATIC_ANALYZER || !CLANG_ENABLE_OBJC_REWRITER
173 CI.getDiagnostics().Report(DiagID: diag::err_fe_action_not_available) << Action;
174 return 0;
175#else
176 llvm_unreachable("Invalid program action!");
177#endif
178}
179
180std::unique_ptr<FrontendAction>
181CreateFrontendAction(CompilerInstance &CI) {
182 // Create the underlying action.
183 std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI);
184 if (!Act)
185 return nullptr;
186
187 const FrontendOptions &FEOpts = CI.getFrontendOpts();
188
189 if (CI.getLangOpts().HLSL)
190 Act = std::make_unique<HLSLFrontendAction>(args: std::move(Act));
191
192 if (FEOpts.FixAndRecompile) {
193 Act = std::make_unique<FixItRecompile>(args: std::move(Act));
194 }
195
196 // Wrap the base FE action in an extract api action to generate
197 // symbol graph as a biproduct of compilation (enabled with
198 // --emit-symbol-graph option)
199 if (FEOpts.EmitSymbolGraph) {
200 if (FEOpts.SymbolGraphOutputDir.empty()) {
201 CI.getDiagnostics().Report(DiagID: diag::warn_missing_symbol_graph_dir);
202 CI.getFrontendOpts().SymbolGraphOutputDir = ".";
203 }
204 CI.getCodeGenOpts().ClearASTBeforeBackend = false;
205 Act = std::make_unique<WrappingExtractAPIAction>(args: std::move(Act));
206 }
207
208 // If there are any AST files to merge, create a frontend action
209 // adaptor to perform the merge.
210 if (!FEOpts.ASTMergeFiles.empty())
211 Act = std::make_unique<ASTMergeAction>(args: std::move(Act),
212 args: FEOpts.ASTMergeFiles);
213
214 if (!CI.getSSAFOpts().TUSummaryFile.empty()) {
215 Act = std::make_unique<ssaf::TUSummaryExtractorFrontendAction>(
216 args: std::move(Act));
217 }
218 // Enter the source-transformation action when the transformation option is
219 // set, and also when only an output option (--ssaf-src-edit-file= /
220 // --ssaf-transformation-report-file=) is set — the action's
221 // reportOrphanOptionMisuse then diagnoses that as a reverse orphan rather
222 // than silently ignoring the option.
223 if (!CI.getSSAFOpts().SourceTransformation.empty() ||
224 !CI.getSSAFOpts().SrcEditFile.empty() ||
225 !CI.getSSAFOpts().TransformationReportFile.empty()) {
226 Act = std::make_unique<ssaf::SourceTransformationFrontendAction>(
227 args: std::move(Act));
228 }
229 return Act;
230}
231
232bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
233 unsigned NumErrorsBefore = Clang->getDiagnostics().getNumErrors();
234
235 // Honor -help.
236 if (Clang->getFrontendOpts().ShowHelp) {
237 getDriverOptTable().printHelp(
238 OS&: llvm::outs(), Usage: "clang -cc1 [options] file...",
239 Title: "LLVM 'Clang' Compiler: http://clang.llvm.org",
240 /*ShowHidden=*/false, /*ShowAllAliases=*/false,
241 VisibilityMask: llvm::opt::Visibility(options::CC1Option));
242 return true;
243 }
244
245 // Honor -version.
246 //
247 // FIXME: Use a better -version message?
248 if (Clang->getFrontendOpts().ShowVersion) {
249 llvm::cl::PrintVersionMessage();
250 return true;
251 }
252
253 Clang->LoadRequestedPlugins();
254
255 // Honor -mllvm.
256 //
257 // FIXME: Remove this, one day.
258 // This should happen AFTER plugins have been loaded!
259 if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
260 unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
261 auto Args = std::make_unique<const char*[]>(num: NumArgs + 2);
262 Args[0] = "clang (LLVM option parsing)";
263 for (unsigned i = 0; i != NumArgs; ++i)
264 Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
265 Args[NumArgs + 1] = nullptr;
266 llvm::cl::ParseCommandLineOptions(argc: NumArgs + 1, argv: Args.get(), /*Overview=*/"",
267 /*Errs=*/nullptr,
268 /*VFS=*/&Clang->getVirtualFileSystem());
269 }
270
271#if CLANG_ENABLE_STATIC_ANALYZER
272 // These should happen AFTER plugins have been loaded!
273
274 AnalyzerOptions &AnOpts = Clang->getAnalyzerOpts();
275
276 // Honor -analyzer-checker-help and -analyzer-checker-help-hidden.
277 if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha ||
278 AnOpts.ShowCheckerHelpDeveloper) {
279 ento::printCheckerHelp(OS&: llvm::outs(), CI&: *Clang);
280 return true;
281 }
282
283 // Honor -analyzer-checker-option-help.
284 if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList ||
285 AnOpts.ShowCheckerOptionDeveloperList) {
286 ento::printCheckerConfigList(OS&: llvm::outs(), CI&: *Clang);
287 return true;
288 }
289
290 // Honor -analyzer-list-enabled-checkers.
291 if (AnOpts.ShowEnabledCheckerList) {
292 ento::printEnabledCheckerList(OS&: llvm::outs(), CI&: *Clang);
293 return true;
294 }
295
296 // Honor -analyzer-config-help.
297 if (AnOpts.ShowConfigOptionsList) {
298 ento::printAnalyzerConfigList(OS&: llvm::outs());
299 return true;
300 }
301#endif
302
303#if CLANG_ENABLE_CIR
304 if (!Clang->getFrontendOpts().MLIRArgs.empty()) {
305 mlir::registerCIRPasses();
306 mlir::registerMLIRContextCLOptions();
307 mlir::registerPassManagerCLOptions();
308 mlir::registerAsmPrinterCLOptions();
309 unsigned NumArgs = Clang->getFrontendOpts().MLIRArgs.size();
310 auto Args = std::make_unique<const char *[]>(NumArgs + 2);
311 Args[0] = "clang (MLIR option parsing)";
312 for (unsigned i = 0; i != NumArgs; ++i)
313 Args[i + 1] = Clang->getFrontendOpts().MLIRArgs[i].c_str();
314 Args[NumArgs + 1] = nullptr;
315 llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(),
316 /*Description=*/"", /*Errs=*/nullptr,
317 &Clang->getVirtualFileSystem());
318 }
319#endif
320
321 // If there were errors in the above, don't do anything else.
322 // This intentionally ignores errors emitted before this function to
323 // accommodate lenient callers that decided to make progress despite errors.
324 if (Clang->getDiagnostics().getNumErrors() != NumErrorsBefore)
325 return false;
326
327 // Create and execute the frontend action.
328 std::unique_ptr<FrontendAction> Act(CreateFrontendAction(CI&: *Clang));
329 if (!Act)
330 return false;
331 bool Success = Clang->ExecuteAction(Act&: *Act);
332 if (Clang->getFrontendOpts().DisableFree)
333 llvm::BuryPointer(Ptr: std::move(Act));
334 return Success;
335}
336
337} // namespace clang
338