1 //===--- FrontendActions.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 #include "clang/Frontend/FrontendActions.h"
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/Basic/FileManager.h"
13 #include "clang/Basic/LangStandard.h"
14 #include "clang/Basic/Module.h"
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Frontend/ASTConsumers.h"
17 #include "clang/Frontend/CompilerInstance.h"
18 #include "clang/Frontend/FrontendDiagnostic.h"
19 #include "clang/Frontend/MultiplexConsumer.h"
20 #include "clang/Frontend/Utils.h"
21 #include "clang/Lex/DependencyDirectivesScanner.h"
22 #include "clang/Lex/HeaderSearch.h"
23 #include "clang/Lex/Preprocessor.h"
24 #include "clang/Lex/PreprocessorOptions.h"
25 #include "clang/Sema/TemplateInstCallback.h"
26 #include "clang/Serialization/ASTReader.h"
27 #include "clang/Serialization/ASTWriter.h"
28 #include "clang/Serialization/ModuleFile.h"
29 #include "llvm/Config/llvm-config.h" // for LLVM_HOST_TRIPLE
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/YAMLTraits.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <memory>
36 #include <optional>
37 #include <system_error>
38
39 using namespace clang;
40
41 namespace {
GetCodeCompletionConsumer(CompilerInstance & CI)42 CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
43 return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()
44 : nullptr;
45 }
46
EnsureSemaIsCreated(CompilerInstance & CI,FrontendAction & Action)47 void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
48 if (Action.hasCodeCompletionSupport() &&
49 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
50 CI.createCodeCompletionConsumer();
51
52 if (!CI.hasSema())
53 CI.createSema(Action.getTranslationUnitKind(),
54 GetCodeCompletionConsumer(CI));
55 }
56 } // namespace
57
58 //===----------------------------------------------------------------------===//
59 // Custom Actions
60 //===----------------------------------------------------------------------===//
61
62 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)63 InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
64 return std::make_unique<ASTConsumer>();
65 }
66
ExecuteAction()67 void InitOnlyAction::ExecuteAction() {
68 }
69
70 // Basically PreprocessOnlyAction::ExecuteAction.
ExecuteAction()71 void ReadPCHAndPreprocessAction::ExecuteAction() {
72 Preprocessor &PP = getCompilerInstance().getPreprocessor();
73
74 // Ignore unknown pragmas.
75 PP.IgnorePragmas();
76
77 Token Tok;
78 // Start parsing the specified input file.
79 PP.EnterMainSourceFile();
80 do {
81 PP.Lex(Tok);
82 } while (Tok.isNot(tok::eof));
83 }
84
85 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)86 ReadPCHAndPreprocessAction::CreateASTConsumer(CompilerInstance &CI,
87 StringRef InFile) {
88 return std::make_unique<ASTConsumer>();
89 }
90
91 //===----------------------------------------------------------------------===//
92 // AST Consumer Actions
93 //===----------------------------------------------------------------------===//
94
95 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)96 ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
97 if (std::unique_ptr<raw_ostream> OS =
98 CI.createDefaultOutputFile(false, InFile))
99 return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter);
100 return nullptr;
101 }
102
103 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)104 ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
105 const FrontendOptions &Opts = CI.getFrontendOpts();
106 return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter,
107 Opts.ASTDumpDecls, Opts.ASTDumpAll,
108 Opts.ASTDumpLookups, Opts.ASTDumpDeclTypes,
109 Opts.ASTDumpFormat);
110 }
111
112 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)113 ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
114 return CreateASTDeclNodeLister();
115 }
116
117 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)118 ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
119 return CreateASTViewer();
120 }
121
122 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)123 GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
124 std::string Sysroot;
125 if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
126 return nullptr;
127
128 std::string OutputFile;
129 std::unique_ptr<raw_pwrite_stream> OS =
130 CreateOutputFile(CI, InFile, /*ref*/ OutputFile);
131 if (!OS)
132 return nullptr;
133
134 if (!CI.getFrontendOpts().RelocatablePCH)
135 Sysroot.clear();
136
137 const auto &FrontendOpts = CI.getFrontendOpts();
138 auto Buffer = std::make_shared<PCHBuffer>();
139 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
140 Consumers.push_back(std::make_unique<PCHGenerator>(
141 CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
142 FrontendOpts.ModuleFileExtensions,
143 CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
144 FrontendOpts.IncludeTimestamps, FrontendOpts.BuildingImplicitModule,
145 +CI.getLangOpts().CacheGeneratedPCH));
146 Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
147 CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
148
149 return std::make_unique<MultiplexConsumer>(std::move(Consumers));
150 }
151
ComputeASTConsumerArguments(CompilerInstance & CI,std::string & Sysroot)152 bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
153 std::string &Sysroot) {
154 Sysroot = CI.getHeaderSearchOpts().Sysroot;
155 if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
156 CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
157 return false;
158 }
159
160 return true;
161 }
162
163 std::unique_ptr<llvm::raw_pwrite_stream>
CreateOutputFile(CompilerInstance & CI,StringRef InFile,std::string & OutputFile)164 GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile,
165 std::string &OutputFile) {
166 // Because this is exposed via libclang we must disable RemoveFileOnSignal.
167 std::unique_ptr<raw_pwrite_stream> OS = CI.createDefaultOutputFile(
168 /*Binary=*/true, InFile, /*Extension=*/"", /*RemoveFileOnSignal=*/false);
169 if (!OS)
170 return nullptr;
171
172 OutputFile = CI.getFrontendOpts().OutputFile;
173 return OS;
174 }
175
shouldEraseOutputFiles()176 bool GeneratePCHAction::shouldEraseOutputFiles() {
177 if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors)
178 return false;
179 return ASTFrontendAction::shouldEraseOutputFiles();
180 }
181
BeginSourceFileAction(CompilerInstance & CI)182 bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
183 CI.getLangOpts().CompilingPCH = true;
184 return true;
185 }
186
187 std::vector<std::unique_ptr<ASTConsumer>>
CreateMultiplexConsumer(CompilerInstance & CI,StringRef InFile)188 GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
189 StringRef InFile) {
190 std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
191 if (!OS)
192 return {};
193
194 std::string OutputFile = CI.getFrontendOpts().OutputFile;
195 std::string Sysroot;
196
197 auto Buffer = std::make_shared<PCHBuffer>();
198 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
199
200 Consumers.push_back(std::make_unique<PCHGenerator>(
201 CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
202 CI.getFrontendOpts().ModuleFileExtensions,
203 /*AllowASTWithErrors=*/
204 +CI.getFrontendOpts().AllowPCMWithCompilerErrors,
205 /*IncludeTimestamps=*/
206 +CI.getFrontendOpts().BuildingImplicitModule &&
207 +CI.getFrontendOpts().IncludeTimestamps,
208 /*BuildingImplicitModule=*/+CI.getFrontendOpts().BuildingImplicitModule,
209 /*ShouldCacheASTInMemory=*/
210 +CI.getFrontendOpts().BuildingImplicitModule));
211 Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
212 CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
213 return Consumers;
214 }
215
216 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)217 GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
218 StringRef InFile) {
219 std::vector<std::unique_ptr<ASTConsumer>> Consumers =
220 CreateMultiplexConsumer(CI, InFile);
221 if (Consumers.empty())
222 return nullptr;
223
224 return std::make_unique<MultiplexConsumer>(std::move(Consumers));
225 }
226
shouldEraseOutputFiles()227 bool GenerateModuleAction::shouldEraseOutputFiles() {
228 return !getCompilerInstance().getFrontendOpts().AllowPCMWithCompilerErrors &&
229 ASTFrontendAction::shouldEraseOutputFiles();
230 }
231
BeginSourceFileAction(CompilerInstance & CI)232 bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
233 CompilerInstance &CI) {
234 if (!CI.getLangOpts().Modules) {
235 CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules);
236 return false;
237 }
238
239 return GenerateModuleAction::BeginSourceFileAction(CI);
240 }
241
242 std::unique_ptr<raw_pwrite_stream>
CreateOutputFile(CompilerInstance & CI,StringRef InFile)243 GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
244 StringRef InFile) {
245 // If no output file was provided, figure out where this module would go
246 // in the module cache.
247 if (CI.getFrontendOpts().OutputFile.empty()) {
248 StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;
249 if (ModuleMapFile.empty())
250 ModuleMapFile = InFile;
251
252 HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
253 CI.getFrontendOpts().OutputFile =
254 HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule,
255 ModuleMapFile);
256 }
257
258 // Because this is exposed via libclang we must disable RemoveFileOnSignal.
259 return CI.createDefaultOutputFile(/*Binary=*/true, InFile, /*Extension=*/"",
260 /*RemoveFileOnSignal=*/false,
261 /*CreateMissingDirectories=*/true,
262 /*ForceUseTemporary=*/true);
263 }
264
PrepareToExecuteAction(CompilerInstance & CI)265 bool GenerateModuleInterfaceAction::PrepareToExecuteAction(
266 CompilerInstance &CI) {
267 for (const auto &FIF : CI.getFrontendOpts().Inputs) {
268 if (const auto InputFormat = FIF.getKind().getFormat();
269 InputFormat != InputKind::Format::Source) {
270 CI.getDiagnostics().Report(
271 diag::err_frontend_action_unsupported_input_format)
272 << "module interface compilation" << FIF.getFile() << InputFormat;
273 return false;
274 }
275 }
276 return GenerateModuleAction::PrepareToExecuteAction(CI);
277 }
278
BeginSourceFileAction(CompilerInstance & CI)279 bool GenerateModuleInterfaceAction::BeginSourceFileAction(
280 CompilerInstance &CI) {
281 CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
282
283 return GenerateModuleAction::BeginSourceFileAction(CI);
284 }
285
286 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)287 GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
288 StringRef InFile) {
289 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
290
291 if (CI.getFrontendOpts().GenReducedBMI &&
292 !CI.getFrontendOpts().ModuleOutputPath.empty()) {
293 Consumers.push_back(std::make_unique<ReducedBMIGenerator>(
294 CI.getPreprocessor(), CI.getModuleCache(),
295 CI.getFrontendOpts().ModuleOutputPath,
296 +CI.getFrontendOpts().AllowPCMWithCompilerErrors));
297 }
298
299 Consumers.push_back(std::make_unique<CXX20ModulesGenerator>(
300 CI.getPreprocessor(), CI.getModuleCache(),
301 CI.getFrontendOpts().OutputFile,
302 +CI.getFrontendOpts().AllowPCMWithCompilerErrors));
303
304 return std::make_unique<MultiplexConsumer>(std::move(Consumers));
305 }
306
307 std::unique_ptr<raw_pwrite_stream>
CreateOutputFile(CompilerInstance & CI,StringRef InFile)308 GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
309 StringRef InFile) {
310 return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
311 }
312
313 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)314 GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
315 StringRef InFile) {
316 return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(),
317 CI.getModuleCache(),
318 CI.getFrontendOpts().OutputFile);
319 }
320
BeginSourceFileAction(CompilerInstance & CI)321 bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
322 if (!CI.getLangOpts().CPlusPlusModules) {
323 CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
324 return false;
325 }
326 CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderUnit);
327 return GenerateModuleAction::BeginSourceFileAction(CI);
328 }
329
330 std::unique_ptr<raw_pwrite_stream>
CreateOutputFile(CompilerInstance & CI,StringRef InFile)331 GenerateHeaderUnitAction::CreateOutputFile(CompilerInstance &CI,
332 StringRef InFile) {
333 return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
334 }
335
~SyntaxOnlyAction()336 SyntaxOnlyAction::~SyntaxOnlyAction() {
337 }
338
339 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)340 SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
341 return std::make_unique<ASTConsumer>();
342 }
343
344 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)345 DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
346 StringRef InFile) {
347 return std::make_unique<ASTConsumer>();
348 }
349
350 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)351 VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
352 return std::make_unique<ASTConsumer>();
353 }
354
ExecuteAction()355 void VerifyPCHAction::ExecuteAction() {
356 CompilerInstance &CI = getCompilerInstance();
357 bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
358 const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
359 std::unique_ptr<ASTReader> Reader(new ASTReader(
360 CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),
361 CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
362 Sysroot.empty() ? "" : Sysroot.c_str(),
363 DisableValidationForModuleKind::None,
364 /*AllowASTWithCompilerErrors*/ false,
365 /*AllowConfigurationMismatch*/ true,
366 /*ValidateSystemInputs*/ true, /*ForceValidateUserInputs*/ true));
367
368 Reader->ReadAST(getCurrentFile(),
369 Preamble ? serialization::MK_Preamble
370 : serialization::MK_PCH,
371 SourceLocation(),
372 ASTReader::ARR_ConfigurationMismatch);
373 }
374
375 namespace {
376 struct TemplightEntry {
377 std::string Name;
378 std::string Kind;
379 std::string Event;
380 std::string DefinitionLocation;
381 std::string PointOfInstantiation;
382 };
383 } // namespace
384
385 namespace llvm {
386 namespace yaml {
387 template <> struct MappingTraits<TemplightEntry> {
mappingllvm::yaml::MappingTraits388 static void mapping(IO &io, TemplightEntry &fields) {
389 io.mapRequired("name", fields.Name);
390 io.mapRequired("kind", fields.Kind);
391 io.mapRequired("event", fields.Event);
392 io.mapRequired("orig", fields.DefinitionLocation);
393 io.mapRequired("poi", fields.PointOfInstantiation);
394 }
395 };
396 } // namespace yaml
397 } // namespace llvm
398
399 namespace {
400 class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
401 using CodeSynthesisContext = Sema::CodeSynthesisContext;
402
403 public:
initialize(const Sema &)404 void initialize(const Sema &) override {}
405
finalize(const Sema &)406 void finalize(const Sema &) override {}
407
atTemplateBegin(const Sema & TheSema,const CodeSynthesisContext & Inst)408 void atTemplateBegin(const Sema &TheSema,
409 const CodeSynthesisContext &Inst) override {
410 displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
411 }
412
atTemplateEnd(const Sema & TheSema,const CodeSynthesisContext & Inst)413 void atTemplateEnd(const Sema &TheSema,
414 const CodeSynthesisContext &Inst) override {
415 displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
416 }
417
418 private:
toString(CodeSynthesisContext::SynthesisKind Kind)419 static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
420 switch (Kind) {
421 case CodeSynthesisContext::TemplateInstantiation:
422 return "TemplateInstantiation";
423 case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
424 return "DefaultTemplateArgumentInstantiation";
425 case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
426 return "DefaultFunctionArgumentInstantiation";
427 case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
428 return "ExplicitTemplateArgumentSubstitution";
429 case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
430 return "DeducedTemplateArgumentSubstitution";
431 case CodeSynthesisContext::LambdaExpressionSubstitution:
432 return "LambdaExpressionSubstitution";
433 case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
434 return "PriorTemplateArgumentSubstitution";
435 case CodeSynthesisContext::DefaultTemplateArgumentChecking:
436 return "DefaultTemplateArgumentChecking";
437 case CodeSynthesisContext::ExceptionSpecEvaluation:
438 return "ExceptionSpecEvaluation";
439 case CodeSynthesisContext::ExceptionSpecInstantiation:
440 return "ExceptionSpecInstantiation";
441 case CodeSynthesisContext::DeclaringSpecialMember:
442 return "DeclaringSpecialMember";
443 case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
444 return "DeclaringImplicitEqualityComparison";
445 case CodeSynthesisContext::DefiningSynthesizedFunction:
446 return "DefiningSynthesizedFunction";
447 case CodeSynthesisContext::RewritingOperatorAsSpaceship:
448 return "RewritingOperatorAsSpaceship";
449 case CodeSynthesisContext::Memoization:
450 return "Memoization";
451 case CodeSynthesisContext::ConstraintsCheck:
452 return "ConstraintsCheck";
453 case CodeSynthesisContext::ConstraintSubstitution:
454 return "ConstraintSubstitution";
455 case CodeSynthesisContext::ConstraintNormalization:
456 return "ConstraintNormalization";
457 case CodeSynthesisContext::RequirementParameterInstantiation:
458 return "RequirementParameterInstantiation";
459 case CodeSynthesisContext::ParameterMappingSubstitution:
460 return "ParameterMappingSubstitution";
461 case CodeSynthesisContext::RequirementInstantiation:
462 return "RequirementInstantiation";
463 case CodeSynthesisContext::NestedRequirementConstraintsCheck:
464 return "NestedRequirementConstraintsCheck";
465 case CodeSynthesisContext::InitializingStructuredBinding:
466 return "InitializingStructuredBinding";
467 case CodeSynthesisContext::MarkingClassDllexported:
468 return "MarkingClassDllexported";
469 case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
470 return "BuildingBuiltinDumpStructCall";
471 case CodeSynthesisContext::BuildingDeductionGuides:
472 return "BuildingDeductionGuides";
473 case CodeSynthesisContext::TypeAliasTemplateInstantiation:
474 return "TypeAliasTemplateInstantiation";
475 case CodeSynthesisContext::PartialOrderingTTP:
476 return "PartialOrderingTTP";
477 }
478 return "";
479 }
480
481 template <bool BeginInstantiation>
displayTemplightEntry(llvm::raw_ostream & Out,const Sema & TheSema,const CodeSynthesisContext & Inst)482 static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,
483 const CodeSynthesisContext &Inst) {
484 std::string YAML;
485 {
486 llvm::raw_string_ostream OS(YAML);
487 llvm::yaml::Output YO(OS);
488 TemplightEntry Entry =
489 getTemplightEntry<BeginInstantiation>(TheSema, Inst);
490 llvm::yaml::EmptyContext Context;
491 llvm::yaml::yamlize(YO, Entry, true, Context);
492 }
493 Out << "---" << YAML << "\n";
494 }
495
printEntryName(const Sema & TheSema,const Decl * Entity,llvm::raw_string_ostream & OS)496 static void printEntryName(const Sema &TheSema, const Decl *Entity,
497 llvm::raw_string_ostream &OS) {
498 auto *NamedTemplate = cast<NamedDecl>(Entity);
499
500 PrintingPolicy Policy = TheSema.Context.getPrintingPolicy();
501 // FIXME: Also ask for FullyQualifiedNames?
502 Policy.SuppressDefaultTemplateArgs = false;
503 NamedTemplate->getNameForDiagnostic(OS, Policy, true);
504
505 if (!OS.str().empty())
506 return;
507
508 Decl *Ctx = Decl::castFromDeclContext(NamedTemplate->getDeclContext());
509 NamedDecl *NamedCtx = dyn_cast_or_null<NamedDecl>(Ctx);
510
511 if (const auto *Decl = dyn_cast<TagDecl>(NamedTemplate)) {
512 if (const auto *R = dyn_cast<RecordDecl>(Decl)) {
513 if (R->isLambda()) {
514 OS << "lambda at ";
515 Decl->getLocation().print(OS, TheSema.getSourceManager());
516 return;
517 }
518 }
519 OS << "unnamed " << Decl->getKindName();
520 return;
521 }
522
523 assert(NamedCtx && "NamedCtx cannot be null");
524
525 if (const auto *Decl = dyn_cast<ParmVarDecl>(NamedTemplate)) {
526 OS << "unnamed function parameter " << Decl->getFunctionScopeIndex()
527 << " ";
528 if (Decl->getFunctionScopeDepth() > 0)
529 OS << "(at depth " << Decl->getFunctionScopeDepth() << ") ";
530 OS << "of ";
531 NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
532 return;
533 }
534
535 if (const auto *Decl = dyn_cast<TemplateTypeParmDecl>(NamedTemplate)) {
536 if (const Type *Ty = Decl->getTypeForDecl()) {
537 if (const auto *TTPT = dyn_cast_or_null<TemplateTypeParmType>(Ty)) {
538 OS << "unnamed template type parameter " << TTPT->getIndex() << " ";
539 if (TTPT->getDepth() > 0)
540 OS << "(at depth " << TTPT->getDepth() << ") ";
541 OS << "of ";
542 NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
543 return;
544 }
545 }
546 }
547
548 if (const auto *Decl = dyn_cast<NonTypeTemplateParmDecl>(NamedTemplate)) {
549 OS << "unnamed template non-type parameter " << Decl->getIndex() << " ";
550 if (Decl->getDepth() > 0)
551 OS << "(at depth " << Decl->getDepth() << ") ";
552 OS << "of ";
553 NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
554 return;
555 }
556
557 if (const auto *Decl = dyn_cast<TemplateTemplateParmDecl>(NamedTemplate)) {
558 OS << "unnamed template template parameter " << Decl->getIndex() << " ";
559 if (Decl->getDepth() > 0)
560 OS << "(at depth " << Decl->getDepth() << ") ";
561 OS << "of ";
562 NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
563 return;
564 }
565
566 llvm_unreachable("Failed to retrieve a name for this entry!");
567 OS << "unnamed identifier";
568 }
569
570 template <bool BeginInstantiation>
getTemplightEntry(const Sema & TheSema,const CodeSynthesisContext & Inst)571 static TemplightEntry getTemplightEntry(const Sema &TheSema,
572 const CodeSynthesisContext &Inst) {
573 TemplightEntry Entry;
574 Entry.Kind = toString(Inst.Kind);
575 Entry.Event = BeginInstantiation ? "Begin" : "End";
576 llvm::raw_string_ostream OS(Entry.Name);
577 printEntryName(TheSema, Inst.Entity, OS);
578 const PresumedLoc DefLoc =
579 TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
580 if (!DefLoc.isInvalid())
581 Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
582 std::to_string(DefLoc.getLine()) + ":" +
583 std::to_string(DefLoc.getColumn());
584 const PresumedLoc PoiLoc =
585 TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
586 if (!PoiLoc.isInvalid()) {
587 Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
588 std::to_string(PoiLoc.getLine()) + ":" +
589 std::to_string(PoiLoc.getColumn());
590 }
591 return Entry;
592 }
593 };
594 } // namespace
595
596 std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)597 TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
598 return std::make_unique<ASTConsumer>();
599 }
600
ExecuteAction()601 void TemplightDumpAction::ExecuteAction() {
602 CompilerInstance &CI = getCompilerInstance();
603
604 // This part is normally done by ASTFrontEndAction, but needs to happen
605 // before Templight observers can be created
606 // FIXME: Move the truncation aspect of this into Sema, we delayed this till
607 // here so the source manager would be initialized.
608 EnsureSemaIsCreated(CI, *this);
609
610 CI.getSema().TemplateInstCallbacks.push_back(
611 std::make_unique<DefaultTemplateInstCallback>());
612 ASTFrontendAction::ExecuteAction();
613 }
614
615 namespace {
616 /// AST reader listener that dumps module information for a module
617 /// file.
618 class DumpModuleInfoListener : public ASTReaderListener {
619 llvm::raw_ostream &Out;
620
621 public:
DumpModuleInfoListener(llvm::raw_ostream & Out)622 DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
623
624 #define DUMP_BOOLEAN(Value, Text) \
625 Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
626
ReadFullVersionInformation(StringRef FullVersion)627 bool ReadFullVersionInformation(StringRef FullVersion) override {
628 Out.indent(2)
629 << "Generated by "
630 << (FullVersion == getClangFullRepositoryVersion()? "this"
631 : "a different")
632 << " Clang: " << FullVersion << "\n";
633 return ASTReaderListener::ReadFullVersionInformation(FullVersion);
634 }
635
ReadModuleName(StringRef ModuleName)636 void ReadModuleName(StringRef ModuleName) override {
637 Out.indent(2) << "Module name: " << ModuleName << "\n";
638 }
ReadModuleMapFile(StringRef ModuleMapPath)639 void ReadModuleMapFile(StringRef ModuleMapPath) override {
640 Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
641 }
642
ReadLanguageOptions(const LangOptions & LangOpts,StringRef ModuleFilename,bool Complain,bool AllowCompatibleDifferences)643 bool ReadLanguageOptions(const LangOptions &LangOpts,
644 StringRef ModuleFilename, bool Complain,
645 bool AllowCompatibleDifferences) override {
646 // FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.
647 using CK = LangOptions::CompatibilityKind;
648
649 Out.indent(2) << "Language options:\n";
650 #define LANGOPT(Name, Bits, Default, Compatibility, Description) \
651 if constexpr (CK::Compatibility != CK::Benign) \
652 DUMP_BOOLEAN(LangOpts.Name, Description);
653 #define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description) \
654 if constexpr (CK::Compatibility != CK::Benign) \
655 Out.indent(4) << Description << ": " \
656 << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
657 #define VALUE_LANGOPT(Name, Bits, Default, Compatibility, Description) \
658 if constexpr (CK::Compatibility != CK::Benign) \
659 Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
660 #include "clang/Basic/LangOptions.def"
661
662 if (!LangOpts.ModuleFeatures.empty()) {
663 Out.indent(4) << "Module features:\n";
664 for (StringRef Feature : LangOpts.ModuleFeatures)
665 Out.indent(6) << Feature << "\n";
666 }
667
668 return false;
669 }
670
ReadTargetOptions(const TargetOptions & TargetOpts,StringRef ModuleFilename,bool Complain,bool AllowCompatibleDifferences)671 bool ReadTargetOptions(const TargetOptions &TargetOpts,
672 StringRef ModuleFilename, bool Complain,
673 bool AllowCompatibleDifferences) override {
674 Out.indent(2) << "Target options:\n";
675 Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
676 Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";
677 Out.indent(4) << " TuneCPU: " << TargetOpts.TuneCPU << "\n";
678 Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n";
679
680 if (!TargetOpts.FeaturesAsWritten.empty()) {
681 Out.indent(4) << "Target features:\n";
682 for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
683 I != N; ++I) {
684 Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
685 }
686 }
687
688 return false;
689 }
690
ReadDiagnosticOptions(DiagnosticOptions & DiagOpts,StringRef ModuleFilename,bool Complain)691 bool ReadDiagnosticOptions(DiagnosticOptions &DiagOpts,
692 StringRef ModuleFilename,
693 bool Complain) override {
694 Out.indent(2) << "Diagnostic options:\n";
695 #define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts.Name, #Name);
696 #define ENUM_DIAGOPT(Name, Type, Bits, Default) \
697 Out.indent(4) << #Name << ": " << DiagOpts.get##Name() << "\n";
698 #define VALUE_DIAGOPT(Name, Bits, Default) \
699 Out.indent(4) << #Name << ": " << DiagOpts.Name << "\n";
700 #include "clang/Basic/DiagnosticOptions.def"
701
702 Out.indent(4) << "Diagnostic flags:\n";
703 for (const std::string &Warning : DiagOpts.Warnings)
704 Out.indent(6) << "-W" << Warning << "\n";
705 for (const std::string &Remark : DiagOpts.Remarks)
706 Out.indent(6) << "-R" << Remark << "\n";
707
708 return false;
709 }
710
ReadHeaderSearchOptions(const HeaderSearchOptions & HSOpts,StringRef ModuleFilename,StringRef SpecificModuleCachePath,bool Complain)711 bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
712 StringRef ModuleFilename,
713 StringRef SpecificModuleCachePath,
714 bool Complain) override {
715 Out.indent(2) << "Header search options:\n";
716 Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
717 Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n";
718 Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
719 DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
720 "Use builtin include directories [-nobuiltininc]");
721 DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
722 "Use standard system include directories [-nostdinc]");
723 DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
724 "Use standard C++ include directories [-nostdinc++]");
725 DUMP_BOOLEAN(HSOpts.UseLibcxx,
726 "Use libc++ (rather than libstdc++) [-stdlib=]");
727 return false;
728 }
729
ReadHeaderSearchPaths(const HeaderSearchOptions & HSOpts,bool Complain)730 bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
731 bool Complain) override {
732 Out.indent(2) << "Header search paths:\n";
733 Out.indent(4) << "User entries:\n";
734 for (const auto &Entry : HSOpts.UserEntries)
735 Out.indent(6) << Entry.Path << "\n";
736 Out.indent(4) << "System header prefixes:\n";
737 for (const auto &Prefix : HSOpts.SystemHeaderPrefixes)
738 Out.indent(6) << Prefix.Prefix << "\n";
739 Out.indent(4) << "VFS overlay files:\n";
740 for (const auto &Overlay : HSOpts.VFSOverlayFiles)
741 Out.indent(6) << Overlay << "\n";
742 return false;
743 }
744
ReadPreprocessorOptions(const PreprocessorOptions & PPOpts,StringRef ModuleFilename,bool ReadMacros,bool Complain,std::string & SuggestedPredefines)745 bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
746 StringRef ModuleFilename, bool ReadMacros,
747 bool Complain,
748 std::string &SuggestedPredefines) override {
749 Out.indent(2) << "Preprocessor options:\n";
750 DUMP_BOOLEAN(PPOpts.UsePredefines,
751 "Uses compiler/target-specific predefines [-undef]");
752 DUMP_BOOLEAN(PPOpts.DetailedRecord,
753 "Uses detailed preprocessing record (for indexing)");
754
755 if (ReadMacros) {
756 Out.indent(4) << "Predefined macros:\n";
757 }
758
759 for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
760 I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
761 I != IEnd; ++I) {
762 Out.indent(6);
763 if (I->second)
764 Out << "-U";
765 else
766 Out << "-D";
767 Out << I->first << "\n";
768 }
769 return false;
770 }
771
772 /// Indicates that a particular module file extension has been read.
readModuleFileExtension(const ModuleFileExtensionMetadata & Metadata)773 void readModuleFileExtension(
774 const ModuleFileExtensionMetadata &Metadata) override {
775 Out.indent(2) << "Module file extension '"
776 << Metadata.BlockName << "' " << Metadata.MajorVersion
777 << "." << Metadata.MinorVersion;
778 if (!Metadata.UserInfo.empty()) {
779 Out << ": ";
780 Out.write_escaped(Metadata.UserInfo);
781 }
782
783 Out << "\n";
784 }
785
786 /// Tells the \c ASTReaderListener that we want to receive the
787 /// input files of the AST file via \c visitInputFile.
needsInputFileVisitation()788 bool needsInputFileVisitation() override { return true; }
789
790 /// Tells the \c ASTReaderListener that we want to receive the
791 /// input files of the AST file via \c visitInputFile.
needsSystemInputFileVisitation()792 bool needsSystemInputFileVisitation() override { return true; }
793
794 /// Indicates that the AST file contains particular input file.
795 ///
796 /// \returns true to continue receiving the next input file, false to stop.
visitInputFile(StringRef FilenameAsRequested,StringRef Filename,bool isSystem,bool isOverridden,bool isExplicitModule)797 bool visitInputFile(StringRef FilenameAsRequested, StringRef Filename,
798 bool isSystem, bool isOverridden,
799 bool isExplicitModule) override {
800
801 Out.indent(2) << "Input file: " << FilenameAsRequested;
802
803 if (isSystem || isOverridden || isExplicitModule) {
804 Out << " [";
805 if (isSystem) {
806 Out << "System";
807 if (isOverridden || isExplicitModule)
808 Out << ", ";
809 }
810 if (isOverridden) {
811 Out << "Overridden";
812 if (isExplicitModule)
813 Out << ", ";
814 }
815 if (isExplicitModule)
816 Out << "ExplicitModule";
817
818 Out << "]";
819 }
820
821 Out << "\n";
822
823 return true;
824 }
825
826 /// Returns true if this \c ASTReaderListener wants to receive the
827 /// imports of the AST file via \c visitImport, false otherwise.
needsImportVisitation() const828 bool needsImportVisitation() const override { return true; }
829
830 /// If needsImportVisitation returns \c true, this is called for each
831 /// AST file imported by this AST file.
visitImport(StringRef ModuleName,StringRef Filename)832 void visitImport(StringRef ModuleName, StringRef Filename) override {
833 Out.indent(2) << "Imports module '" << ModuleName
834 << "': " << Filename.str() << "\n";
835 }
836 #undef DUMP_BOOLEAN
837 };
838 }
839
BeginInvocation(CompilerInstance & CI)840 bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {
841 // The Object file reader also supports raw ast files and there is no point in
842 // being strict about the module file format in -module-file-info mode.
843 CI.getHeaderSearchOpts().ModuleFormat = "obj";
844 return true;
845 }
846
ModuleKindName(Module::ModuleKind MK)847 static StringRef ModuleKindName(Module::ModuleKind MK) {
848 switch (MK) {
849 case Module::ModuleMapModule:
850 return "Module Map Module";
851 case Module::ModuleInterfaceUnit:
852 return "Interface Unit";
853 case Module::ModuleImplementationUnit:
854 return "Implementation Unit";
855 case Module::ModulePartitionInterface:
856 return "Partition Interface";
857 case Module::ModulePartitionImplementation:
858 return "Partition Implementation";
859 case Module::ModuleHeaderUnit:
860 return "Header Unit";
861 case Module::ExplicitGlobalModuleFragment:
862 return "Global Module Fragment";
863 case Module::ImplicitGlobalModuleFragment:
864 return "Implicit Module Fragment";
865 case Module::PrivateModuleFragment:
866 return "Private Module Fragment";
867 }
868 llvm_unreachable("unknown module kind!");
869 }
870
ExecuteAction()871 void DumpModuleInfoAction::ExecuteAction() {
872 CompilerInstance &CI = getCompilerInstance();
873
874 // Don't process files of type other than module to avoid crash
875 if (!isCurrentFileAST()) {
876 CI.getDiagnostics().Report(diag::err_file_is_not_module)
877 << getCurrentFile();
878 return;
879 }
880
881 // Set up the output file.
882 StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
883 if (!OutputFileName.empty() && OutputFileName != "-") {
884 std::error_code EC;
885 OutputStream.reset(new llvm::raw_fd_ostream(
886 OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF));
887 }
888 llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs();
889
890 Out << "Information for module file '" << getCurrentFile() << "':\n";
891 auto &FileMgr = CI.getFileManager();
892 auto Buffer = FileMgr.getBufferForFile(getCurrentFile());
893 StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();
894 bool IsRaw = Magic.starts_with("CPCH");
895 Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n";
896
897 Preprocessor &PP = CI.getPreprocessor();
898 DumpModuleInfoListener Listener(Out);
899 const HeaderSearchOptions &HSOpts =
900 PP.getHeaderSearchInfo().getHeaderSearchOpts();
901
902 // The FrontendAction::BeginSourceFile () method loads the AST so that much
903 // of the information is already available and modules should have been
904 // loaded.
905
906 const LangOptions &LO = getCurrentASTUnit().getLangOpts();
907 if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
908 ASTReader *R = getCurrentASTUnit().getASTReader().get();
909 unsigned SubModuleCount = R->getTotalNumSubmodules();
910 serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
911 Out << " ====== C++20 Module structure ======\n";
912
913 if (MF.ModuleName != LO.CurrentModule)
914 Out << " Mismatched module names : " << MF.ModuleName << " and "
915 << LO.CurrentModule << "\n";
916
917 struct SubModInfo {
918 unsigned Idx;
919 Module *Mod;
920 Module::ModuleKind Kind;
921 std::string &Name;
922 bool Seen;
923 };
924 std::map<std::string, SubModInfo> SubModMap;
925 auto PrintSubMapEntry = [&](std::string Name, Module::ModuleKind Kind) {
926 Out << " " << ModuleKindName(Kind) << " '" << Name << "'";
927 auto I = SubModMap.find(Name);
928 if (I == SubModMap.end())
929 Out << " was not found in the sub modules!\n";
930 else {
931 I->second.Seen = true;
932 Out << " is at index #" << I->second.Idx << "\n";
933 }
934 };
935 Module *Primary = nullptr;
936 for (unsigned Idx = 0; Idx <= SubModuleCount; ++Idx) {
937 Module *M = R->getModule(Idx);
938 if (!M)
939 continue;
940 if (M->Name == LO.CurrentModule) {
941 Primary = M;
942 Out << " " << ModuleKindName(M->Kind) << " '" << LO.CurrentModule
943 << "' is the Primary Module at index #" << Idx << "\n";
944 SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, true}});
945 } else
946 SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, false}});
947 }
948 if (Primary) {
949 if (!Primary->submodules().empty())
950 Out << " Sub Modules:\n";
951 for (auto *MI : Primary->submodules()) {
952 PrintSubMapEntry(MI->Name, MI->Kind);
953 }
954 if (!Primary->Imports.empty())
955 Out << " Imports:\n";
956 for (auto *IMP : Primary->Imports) {
957 PrintSubMapEntry(IMP->Name, IMP->Kind);
958 }
959 if (!Primary->Exports.empty())
960 Out << " Exports:\n";
961 for (unsigned MN = 0, N = Primary->Exports.size(); MN != N; ++MN) {
962 if (Module *M = Primary->Exports[MN].getPointer()) {
963 PrintSubMapEntry(M->Name, M->Kind);
964 }
965 }
966 }
967
968 // Emit the macro definitions in the module file so that we can know how
969 // much definitions in the module file quickly.
970 // TODO: Emit the macro definition bodies completely.
971 if (auto FilteredMacros = llvm::make_filter_range(
972 R->getPreprocessor().macros(),
973 [](const auto &Macro) { return Macro.first->isFromAST(); });
974 !FilteredMacros.empty()) {
975 Out << " Macro Definitions:\n";
976 for (/*<IdentifierInfo *, MacroState> pair*/ const auto &Macro :
977 FilteredMacros)
978 Out << " " << Macro.first->getName() << "\n";
979 }
980
981 // Now let's print out any modules we did not see as part of the Primary.
982 for (const auto &SM : SubModMap) {
983 if (!SM.second.Seen && SM.second.Mod) {
984 Out << " " << ModuleKindName(SM.second.Kind) << " '" << SM.first
985 << "' at index #" << SM.second.Idx
986 << " has no direct reference in the Primary\n";
987 }
988 }
989 Out << " ====== ======\n";
990 }
991
992 // The reminder of the output is produced from the listener as the AST
993 // FileCcontrolBlock is (re-)parsed.
994 ASTReader::readASTFileControlBlock(
995 getCurrentFile(), FileMgr, CI.getModuleCache(),
996 CI.getPCHContainerReader(),
997 /*FindModuleFileExtensions=*/true, Listener,
998 HSOpts.ModulesValidateDiagnosticOptions);
999 }
1000
1001 //===----------------------------------------------------------------------===//
1002 // Preprocessor Actions
1003 //===----------------------------------------------------------------------===//
1004
ExecuteAction()1005 void DumpRawTokensAction::ExecuteAction() {
1006 Preprocessor &PP = getCompilerInstance().getPreprocessor();
1007 SourceManager &SM = PP.getSourceManager();
1008
1009 // Start lexing the specified input file.
1010 llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
1011 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
1012 RawLex.SetKeepWhitespaceMode(true);
1013
1014 Token RawTok;
1015 RawLex.LexFromRawLexer(RawTok);
1016 while (RawTok.isNot(tok::eof)) {
1017 PP.DumpToken(RawTok, true);
1018 llvm::errs() << "\n";
1019 RawLex.LexFromRawLexer(RawTok);
1020 }
1021 }
1022
ExecuteAction()1023 void DumpTokensAction::ExecuteAction() {
1024 Preprocessor &PP = getCompilerInstance().getPreprocessor();
1025 // Start preprocessing the specified input file.
1026 Token Tok;
1027 PP.EnterMainSourceFile();
1028 do {
1029 PP.Lex(Tok);
1030 PP.DumpToken(Tok, true);
1031 llvm::errs() << "\n";
1032 } while (Tok.isNot(tok::eof));
1033 }
1034
ExecuteAction()1035 void PreprocessOnlyAction::ExecuteAction() {
1036 Preprocessor &PP = getCompilerInstance().getPreprocessor();
1037
1038 // Ignore unknown pragmas.
1039 PP.IgnorePragmas();
1040
1041 Token Tok;
1042 // Start parsing the specified input file.
1043 PP.EnterMainSourceFile();
1044 do {
1045 PP.Lex(Tok);
1046 } while (Tok.isNot(tok::eof));
1047 }
1048
ExecuteAction()1049 void PrintPreprocessedAction::ExecuteAction() {
1050 CompilerInstance &CI = getCompilerInstance();
1051 // Output file may need to be set to 'Binary', to avoid converting Unix style
1052 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>) on Windows.
1053 //
1054 // Look to see what type of line endings the file uses. If there's a
1055 // CRLF, then we won't open the file up in binary mode. If there is
1056 // just an LF or CR, then we will open the file up in binary mode.
1057 // In this fashion, the output format should match the input format, unless
1058 // the input format has inconsistent line endings.
1059 //
1060 // This should be a relatively fast operation since most files won't have
1061 // all of their source code on a single line. However, that is still a
1062 // concern, so if we scan for too long, we'll just assume the file should
1063 // be opened in binary mode.
1064
1065 bool BinaryMode = false;
1066 if (llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows()) {
1067 BinaryMode = true;
1068 const SourceManager &SM = CI.getSourceManager();
1069 if (std::optional<llvm::MemoryBufferRef> Buffer =
1070 SM.getBufferOrNone(SM.getMainFileID())) {
1071 const char *cur = Buffer->getBufferStart();
1072 const char *end = Buffer->getBufferEnd();
1073 const char *next = (cur != end) ? cur + 1 : end;
1074
1075 // Limit ourselves to only scanning 256 characters into the source
1076 // file. This is mostly a check in case the file has no
1077 // newlines whatsoever.
1078 if (end - cur > 256)
1079 end = cur + 256;
1080
1081 while (next < end) {
1082 if (*cur == 0x0D) { // CR
1083 if (*next == 0x0A) // CRLF
1084 BinaryMode = false;
1085
1086 break;
1087 } else if (*cur == 0x0A) // LF
1088 break;
1089
1090 ++cur;
1091 ++next;
1092 }
1093 }
1094 }
1095
1096 std::unique_ptr<raw_ostream> OS =
1097 CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName());
1098 if (!OS) return;
1099
1100 // If we're preprocessing a module map, start by dumping the contents of the
1101 // module itself before switching to the input buffer.
1102 auto &Input = getCurrentInput();
1103 if (Input.getKind().getFormat() == InputKind::ModuleMap) {
1104 if (Input.isFile()) {
1105 (*OS) << "# 1 \"";
1106 OS->write_escaped(Input.getFile());
1107 (*OS) << "\"\n";
1108 }
1109 getCurrentModule()->print(*OS);
1110 (*OS) << "#pragma clang module contents\n";
1111 }
1112
1113 DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(),
1114 CI.getPreprocessorOutputOpts());
1115 }
1116
ExecuteAction()1117 void PrintPreambleAction::ExecuteAction() {
1118 switch (getCurrentFileKind().getLanguage()) {
1119 case Language::C:
1120 case Language::CXX:
1121 case Language::ObjC:
1122 case Language::ObjCXX:
1123 case Language::OpenCL:
1124 case Language::OpenCLCXX:
1125 case Language::CUDA:
1126 case Language::HIP:
1127 case Language::HLSL:
1128 case Language::CIR:
1129 break;
1130
1131 case Language::Unknown:
1132 case Language::Asm:
1133 case Language::LLVM_IR:
1134 // We can't do anything with these.
1135 return;
1136 }
1137
1138 // We don't expect to find any #include directives in a preprocessed input.
1139 if (getCurrentFileKind().isPreprocessed())
1140 return;
1141
1142 CompilerInstance &CI = getCompilerInstance();
1143 auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
1144 if (Buffer) {
1145 unsigned Preamble =
1146 Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;
1147 llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
1148 }
1149 }
1150
ExecuteAction()1151 void DumpCompilerOptionsAction::ExecuteAction() {
1152 CompilerInstance &CI = getCompilerInstance();
1153 std::unique_ptr<raw_ostream> OSP =
1154 CI.createDefaultOutputFile(false, getCurrentFile());
1155 if (!OSP)
1156 return;
1157
1158 raw_ostream &OS = *OSP;
1159 const Preprocessor &PP = CI.getPreprocessor();
1160 const LangOptions &LangOpts = PP.getLangOpts();
1161
1162 // FIXME: Rather than manually format the JSON (which is awkward due to
1163 // needing to remove trailing commas), this should make use of a JSON library.
1164 // FIXME: Instead of printing enums as an integral value and specifying the
1165 // type as a separate field, use introspection to print the enumerator.
1166
1167 OS << "{\n";
1168 OS << "\n\"features\" : [\n";
1169 {
1170 llvm::SmallString<128> Str;
1171 #define FEATURE(Name, Predicate) \
1172 ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
1173 .toVector(Str);
1174 #include "clang/Basic/Features.def"
1175 #undef FEATURE
1176 // Remove the newline and comma from the last entry to ensure this remains
1177 // valid JSON.
1178 OS << Str.substr(0, Str.size() - 2);
1179 }
1180 OS << "\n],\n";
1181
1182 OS << "\n\"extensions\" : [\n";
1183 {
1184 llvm::SmallString<128> Str;
1185 #define EXTENSION(Name, Predicate) \
1186 ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
1187 .toVector(Str);
1188 #include "clang/Basic/Features.def"
1189 #undef EXTENSION
1190 // Remove the newline and comma from the last entry to ensure this remains
1191 // valid JSON.
1192 OS << Str.substr(0, Str.size() - 2);
1193 }
1194 OS << "\n]\n";
1195
1196 OS << "}";
1197 }
1198
ExecuteAction()1199 void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
1200 CompilerInstance &CI = getCompilerInstance();
1201 SourceManager &SM = CI.getPreprocessor().getSourceManager();
1202 llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
1203
1204 llvm::SmallVector<dependency_directives_scan::Token, 16> Tokens;
1205 llvm::SmallVector<dependency_directives_scan::Directive, 32> Directives;
1206 if (scanSourceForDependencyDirectives(
1207 FromFile.getBuffer(), Tokens, Directives, &CI.getDiagnostics(),
1208 SM.getLocForStartOfFile(SM.getMainFileID()))) {
1209 assert(CI.getDiagnostics().hasErrorOccurred() &&
1210 "no errors reported for failure");
1211
1212 // Preprocess the source when verifying the diagnostics to capture the
1213 // 'expected' comments.
1214 if (CI.getDiagnosticOpts().VerifyDiagnostics) {
1215 // Make sure we don't emit new diagnostics!
1216 CI.getDiagnostics().setSuppressAllDiagnostics(true);
1217 Preprocessor &PP = getCompilerInstance().getPreprocessor();
1218 PP.EnterMainSourceFile();
1219 Token Tok;
1220 do {
1221 PP.Lex(Tok);
1222 } while (Tok.isNot(tok::eof));
1223 }
1224 return;
1225 }
1226 printDependencyDirectivesAsSource(FromFile.getBuffer(), Directives,
1227 llvm::outs());
1228 }
1229
ExecuteAction()1230 void GetDependenciesByModuleNameAction::ExecuteAction() {
1231 CompilerInstance &CI = getCompilerInstance();
1232 Preprocessor &PP = CI.getPreprocessor();
1233 SourceManager &SM = PP.getSourceManager();
1234 FileID MainFileID = SM.getMainFileID();
1235 SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
1236 SmallVector<IdentifierLoc, 2> Path;
1237 IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
1238 Path.emplace_back(FileStart, ModuleID);
1239 auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);
1240 PPCallbacks *CB = PP.getPPCallbacks();
1241 CB->moduleImport(SourceLocation(), Path, ModResult);
1242 }
1243