clang 24.0.0git
ExecuteCompilerInvocation.cpp
Go to the documentation of this file.
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
16#include "clang/Config/config.h"
29#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
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"
43#endif
44
45using namespace clang;
46using namespace llvm::opt;
47
48namespace clang {
49
50static std::unique_ptr<FrontendAction>
52 using namespace clang::frontend;
53 StringRef Action("unknown");
54 (void)Action;
55
56 unsigned UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
58 bool EmitsCIR = Act == EmitCIR;
59
60 if (!UseCIR && EmitsCIR)
61 llvm::report_fatal_error("-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>();
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(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>();
113 return std::make_unique<GenerateModuleInterfaceAction>();
115 return std::make_unique<GenerateReducedModuleInterfaceAction>();
117 return std::make_unique<GenerateHeaderUnitAction>();
118 case GeneratePCH: return std::make_unique<GeneratePCHAction>();
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 CI.getFrontendOpts().PluginArgs[std::string(Plugin.getName())]))
137 return nullptr;
138 return std::move(P);
139 }
140 }
141
142 CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
144 return nullptr;
145 }
146
147 case PrintPreamble: return std::make_unique<PrintPreambleAction>();
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>();
169 return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>();
170 }
171
172#if !CLANG_ENABLE_STATIC_ANALYZER || !CLANG_ENABLE_OBJC_REWRITER
173 CI.getDiagnostics().Report(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>
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>(std::move(Act));
191
192 if (FEOpts.FixAndRecompile) {
193 Act = std::make_unique<FixItRecompile>(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(diag::warn_missing_symbol_graph_dir);
203 }
204 CI.getCodeGenOpts().ClearASTBeforeBackend = false;
205 Act = std::make_unique<WrappingExtractAPIAction>(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>(std::move(Act),
212 FEOpts.ASTMergeFiles);
213
214 if (!CI.getSSAFOpts().TUSummaryFile.empty()) {
215 Act = std::make_unique<ssaf::TUSummaryExtractorFrontendAction>(
216 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() ||
226 Act = std::make_unique<ssaf::SourceTransformationFrontendAction>(
227 std::move(Act));
228 }
229 return Act;
230}
231
233 unsigned NumErrorsBefore = Clang->getDiagnostics().getNumErrors();
234
235 // Honor -help.
236 if (Clang->getFrontendOpts().ShowHelp) {
237 getDriverOptTable().printHelp(
238 llvm::outs(), "clang -cc1 [options] file...",
239 "LLVM 'Clang' Compiler: http://clang.llvm.org",
240 /*ShowHidden=*/false, /*ShowAllAliases=*/false,
241 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*[]>(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(NumArgs + 1, 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 ||
279 ento::printCheckerHelp(llvm::outs(), *Clang);
280 return true;
281 }
282
283 // Honor -analyzer-checker-option-help.
286 ento::printCheckerConfigList(llvm::outs(), *Clang);
287 return true;
288 }
289
290 // Honor -analyzer-list-enabled-checkers.
291 if (AnOpts.ShowEnabledCheckerList) {
292 ento::printEnabledCheckerList(llvm::outs(), *Clang);
293 return true;
294 }
295
296 // Honor -analyzer-config-help.
297 if (AnOpts.ShowConfigOptionsList) {
298 ento::printAnalyzerConfigList(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(*Clang));
329 if (!Act)
330 return false;
331 bool Success = Clang->ExecuteAction(*Act);
332 if (Clang->getFrontendOpts().DisableFree)
333 llvm::BuryPointer(std::move(Act));
334 return Success;
335}
336
337} // namespace clang
This file defines the ExtractAPIAction and WrappingExtractAPIAction frontend actions.
This file pulls in all built-in SSAF extractor and format registrations by referencing their anchor s...
Stores options for the analyzer from the command line.
unsigned ShowCheckerOptionDeveloperList
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
AnalyzerOptions & getAnalyzerOpts()
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
PreprocessorOutputOptions & getPreprocessorOutputOpts()
ssaf::SSAFOptions & getSSAFOpts()
void LoadRequestedPlugins()
Load the list of plugins requested in the FrontendOptions.
FrontendOptions & getFrontendOpts()
llvm::vfs::FileSystem & getVirtualFileSystem() const
bool ExecuteAction(FrontendAction &Act)
ExecuteAction - Execute the provided action against the compiler's CompilerInvocation object.
CodeGenOptions & getCodeGenOpts()
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getNumErrors() const
Definition Diagnostic.h:907
FrontendOptions - Options for controlling the behavior of the frontend.
unsigned EmitSymbolGraph
Whether to emit symbol graph files as a side effect of compilation.
std::map< std::string, std::vector< std::string > > PluginArgs
Args to pass to the plugins.
std::vector< std::string > MLIRArgs
A list of arguments to forward to MLIR's option processing; this should only be used for debugging an...
std::vector< std::string > LLVMArgs
A list of arguments to forward to LLVM's option processing; this should only be used for debugging an...
unsigned ShowHelp
Show the -help text.
unsigned FixAndRecompile
Apply fixes and recompile.
unsigned UseClangIRPipeline
Use Clang IR pipeline to emit code.
std::string ActionName
The name of the action to run when using a plugin action.
unsigned ShowVersion
Show the -version text.
std::vector< std::string > ASTMergeFiles
The list of AST files to merge.
unsigned DisableFree
Disable memory freeing on exit.
frontend::ActionKind ProgramAction
The frontend action to perform.
@ ReplaceAction
Replace the main action.
@ CmdlineAfterMainAction
Execute the action after the main action if on the command line.
unsigned RewriteIncludes
Preprocess include directives only.
unsigned RewriteImports
Include contents of transitively-imported modules.
std::string SrcEditFile
Path of the source-edit output file produced by the source transformation.
Definition SSAFOptions.h:48
std::string TransformationReportFile
Path of the transformation-report output file produced by the source transformation.
Definition SSAFOptions.h:53
std::string SourceTransformation
Name of the SSAF source transformation to run.
Definition SSAFOptions.h:38
std::string TUSummaryFile
The TU summary output file with the file extension representing the serialization format.
Definition SSAFOptions.h:27
void printEnabledCheckerList(llvm::raw_ostream &OS, CompilerInstance &CI)
void printCheckerHelp(llvm::raw_ostream &OS, CompilerInstance &CI)
void printAnalyzerConfigList(llvm::raw_ostream &OS)
void printCheckerConfigList(llvm::raw_ostream &OS, CompilerInstance &CI)
@ GenerateHeaderUnit
Generate a C++20 header unit module from a header file.
@ VerifyPCH
Load and verify that a PCH file is usable.
@ PrintPreprocessedInput
-E mode.
@ RewriteTest
Rewriter playground.
@ ParseSyntaxOnly
Parse and perform semantic analysis.
@ EmitBC
Emit a .bc file.
@ GenerateModuleInterface
Generate pre-compiled module from a standard C++ module interface unit.
@ EmitLLVM
Emit a .ll file.
@ PrintPreamble
Print the "preamble" of the input file.
@ InitOnly
Only execute frontend initialization.
@ ASTView
Parse ASTs and view them in Graphviz.
@ PluginAction
Run a plugin action,.
@ EmitObj
Emit a .o file.
@ DumpRawTokens
Dump out raw tokens.
@ PrintDependencyDirectivesSourceMinimizerOutput
Print the output of the dependency directives source minimizer.
@ RewriteObjC
ObjC->C Rewriter.
@ RunPreprocessorOnly
Just lex, no output.
@ EmitCIR
Emit a .cir file.
@ DumpCompilerOptions
Dump the compiler configuration.
@ RunAnalysis
Run one or more source code analyses.
@ ASTPrint
Parse ASTs and print them.
@ GenerateReducedModuleInterface
Generate reduced module interface for a standard C++ module interface unit.
@ GenerateInterfaceStubs
Generate Interface Stub Files.
@ ASTDump
Parse ASTs and dump them.
@ DumpTokens
Dump out preprocessed tokens.
@ FixIt
Parse and apply any fixits to the source.
@ EmitAssembly
Emit a .s file.
@ EmitCodeGenOnly
Generate machine code, but don't emit anything.
@ RewriteMacros
Expand macros but not #includes.
@ EmitHTML
Translate input source into HTML.
@ GeneratePCH
Generate pre-compiled header.
@ EmitLLVMOnly
Generate LLVM IR, but do not emit anything.
@ GenerateModule
Generate pre-compiled module from a module map.
@ ASTDeclList
Parse ASTs and list Decl nodes.
The JSON file list parser is used to communicate input to InstallAPI.
static std::unique_ptr< FrontendAction > CreateFrontendBaseAction(CompilerInstance &CI)
@ Success
Annotation was successful.
Definition Parser.h:65
bool ExecuteCompilerInvocation(CompilerInstance *Clang)
ExecuteCompilerInvocation - Execute the given actions described by the compiler invocation object in ...
std::unique_ptr< FrontendAction > CreateFrontendAction(CompilerInstance &CI)
Construct the FrontendAction of a compiler invocation based on the options specified for the compiler...
const llvm::opt::OptTable & getDriverOptTable()