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