xref: /freebsd-src/contrib/llvm-project/clang/lib/Frontend/FrontendActions.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- FrontendActions.cpp ----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/Frontend/FrontendActions.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
1104eeddc0SDimitry Andric #include "clang/AST/Decl.h"
120b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
13a7dea167SDimitry Andric #include "clang/Basic/LangStandard.h"
1481ad6265SDimitry Andric #include "clang/Basic/Module.h"
1504eeddc0SDimitry Andric #include "clang/Basic/TargetInfo.h"
160b57cec5SDimitry Andric #include "clang/Frontend/ASTConsumers.h"
170b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
180b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h"
190b57cec5SDimitry Andric #include "clang/Frontend/MultiplexConsumer.h"
200b57cec5SDimitry Andric #include "clang/Frontend/Utils.h"
2181ad6265SDimitry Andric #include "clang/Lex/DependencyDirectivesScanner.h"
220b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h"
230b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
240b57cec5SDimitry Andric #include "clang/Lex/PreprocessorOptions.h"
250b57cec5SDimitry Andric #include "clang/Sema/TemplateInstCallback.h"
260b57cec5SDimitry Andric #include "clang/Serialization/ASTReader.h"
270b57cec5SDimitry Andric #include "clang/Serialization/ASTWriter.h"
2881ad6265SDimitry Andric #include "clang/Serialization/ModuleFile.h"
2904eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h"
300b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
310b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
320b57cec5SDimitry Andric #include "llvm/Support/Path.h"
330b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
350b57cec5SDimitry Andric #include <memory>
36bdd1243dSDimitry Andric #include <optional>
370b57cec5SDimitry Andric #include <system_error>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric using namespace clang;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric namespace {
420b57cec5SDimitry Andric CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
430b57cec5SDimitry Andric   return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()
440b57cec5SDimitry Andric                                         : nullptr;
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
480b57cec5SDimitry Andric   if (Action.hasCodeCompletionSupport() &&
490b57cec5SDimitry Andric       !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
500b57cec5SDimitry Andric     CI.createCodeCompletionConsumer();
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   if (!CI.hasSema())
530b57cec5SDimitry Andric     CI.createSema(Action.getTranslationUnitKind(),
540b57cec5SDimitry Andric                   GetCodeCompletionConsumer(CI));
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric } // namespace
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
590b57cec5SDimitry Andric // Custom Actions
600b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
630b57cec5SDimitry Andric InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
64a7dea167SDimitry Andric   return std::make_unique<ASTConsumer>();
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric void InitOnlyAction::ExecuteAction() {
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
70fe6060f1SDimitry Andric // Basically PreprocessOnlyAction::ExecuteAction.
71fe6060f1SDimitry Andric void ReadPCHAndPreprocessAction::ExecuteAction() {
72fe6060f1SDimitry Andric   Preprocessor &PP = getCompilerInstance().getPreprocessor();
73fe6060f1SDimitry Andric 
74fe6060f1SDimitry Andric   // Ignore unknown pragmas.
75fe6060f1SDimitry Andric   PP.IgnorePragmas();
76fe6060f1SDimitry Andric 
77fe6060f1SDimitry Andric   Token Tok;
78fe6060f1SDimitry Andric   // Start parsing the specified input file.
79fe6060f1SDimitry Andric   PP.EnterMainSourceFile();
80fe6060f1SDimitry Andric   do {
81fe6060f1SDimitry Andric     PP.Lex(Tok);
82fe6060f1SDimitry Andric   } while (Tok.isNot(tok::eof));
83fe6060f1SDimitry Andric }
84fe6060f1SDimitry Andric 
85fe6060f1SDimitry Andric std::unique_ptr<ASTConsumer>
86fe6060f1SDimitry Andric ReadPCHAndPreprocessAction::CreateASTConsumer(CompilerInstance &CI,
87fe6060f1SDimitry Andric                                               StringRef InFile) {
88fe6060f1SDimitry Andric   return std::make_unique<ASTConsumer>();
89fe6060f1SDimitry Andric }
90fe6060f1SDimitry Andric 
910b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
920b57cec5SDimitry Andric // AST Consumer Actions
930b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
960b57cec5SDimitry Andric ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
970b57cec5SDimitry Andric   if (std::unique_ptr<raw_ostream> OS =
980b57cec5SDimitry Andric           CI.createDefaultOutputFile(false, InFile))
990b57cec5SDimitry Andric     return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter);
1000b57cec5SDimitry Andric   return nullptr;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
1040b57cec5SDimitry Andric ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
1050b57cec5SDimitry Andric   const FrontendOptions &Opts = CI.getFrontendOpts();
1060b57cec5SDimitry Andric   return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter,
1070b57cec5SDimitry Andric                          Opts.ASTDumpDecls, Opts.ASTDumpAll,
1085ffd83dbSDimitry Andric                          Opts.ASTDumpLookups, Opts.ASTDumpDeclTypes,
1095ffd83dbSDimitry Andric                          Opts.ASTDumpFormat);
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
1130b57cec5SDimitry Andric ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
1140b57cec5SDimitry Andric   return CreateASTDeclNodeLister();
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
1180b57cec5SDimitry Andric ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
1190b57cec5SDimitry Andric   return CreateASTViewer();
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
1230b57cec5SDimitry Andric GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
1240b57cec5SDimitry Andric   std::string Sysroot;
1250b57cec5SDimitry Andric   if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
1260b57cec5SDimitry Andric     return nullptr;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   std::string OutputFile;
1290b57cec5SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS =
1300b57cec5SDimitry Andric       CreateOutputFile(CI, InFile, /*ref*/ OutputFile);
1310b57cec5SDimitry Andric   if (!OS)
1320b57cec5SDimitry Andric     return nullptr;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   if (!CI.getFrontendOpts().RelocatablePCH)
1350b57cec5SDimitry Andric     Sysroot.clear();
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   const auto &FrontendOpts = CI.getFrontendOpts();
1380b57cec5SDimitry Andric   auto Buffer = std::make_shared<PCHBuffer>();
1390b57cec5SDimitry Andric   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
140a7dea167SDimitry Andric   Consumers.push_back(std::make_unique<PCHGenerator>(
1410b57cec5SDimitry Andric       CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
1420b57cec5SDimitry Andric       FrontendOpts.ModuleFileExtensions,
1430b57cec5SDimitry Andric       CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
1445f757f3fSDimitry Andric       FrontendOpts.IncludeTimestamps, FrontendOpts.BuildingImplicitModule,
1455f757f3fSDimitry Andric       +CI.getLangOpts().CacheGeneratedPCH));
1460b57cec5SDimitry Andric   Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
1475ffd83dbSDimitry Andric       CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
1480b57cec5SDimitry Andric 
149a7dea167SDimitry Andric   return std::make_unique<MultiplexConsumer>(std::move(Consumers));
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
1530b57cec5SDimitry Andric                                                     std::string &Sysroot) {
1540b57cec5SDimitry Andric   Sysroot = CI.getHeaderSearchOpts().Sysroot;
1550b57cec5SDimitry Andric   if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
1560b57cec5SDimitry Andric     CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
1570b57cec5SDimitry Andric     return false;
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   return true;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric std::unique_ptr<llvm::raw_pwrite_stream>
1640b57cec5SDimitry Andric GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile,
1650b57cec5SDimitry Andric                                     std::string &OutputFile) {
166e8d8bef9SDimitry Andric   // Because this is exposed via libclang we must disable RemoveFileOnSignal.
167e8d8bef9SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS = CI.createDefaultOutputFile(
168e8d8bef9SDimitry Andric       /*Binary=*/true, InFile, /*Extension=*/"", /*RemoveFileOnSignal=*/false);
1690b57cec5SDimitry Andric   if (!OS)
1700b57cec5SDimitry Andric     return nullptr;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   OutputFile = CI.getFrontendOpts().OutputFile;
1730b57cec5SDimitry Andric   return OS;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric bool GeneratePCHAction::shouldEraseOutputFiles() {
1770b57cec5SDimitry Andric   if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors)
1780b57cec5SDimitry Andric     return false;
1790b57cec5SDimitry Andric   return ASTFrontendAction::shouldEraseOutputFiles();
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
1830b57cec5SDimitry Andric   CI.getLangOpts().CompilingPCH = true;
1840b57cec5SDimitry Andric   return true;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
187*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<ASTConsumer>>
188*0fca6ea1SDimitry Andric GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
1890b57cec5SDimitry Andric                                               StringRef InFile) {
1900b57cec5SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
1910b57cec5SDimitry Andric   if (!OS)
192*0fca6ea1SDimitry Andric     return {};
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   std::string OutputFile = CI.getFrontendOpts().OutputFile;
1950b57cec5SDimitry Andric   std::string Sysroot;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   auto Buffer = std::make_shared<PCHBuffer>();
1980b57cec5SDimitry Andric   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
1990b57cec5SDimitry Andric 
200a7dea167SDimitry Andric   Consumers.push_back(std::make_unique<PCHGenerator>(
2010b57cec5SDimitry Andric       CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
2020b57cec5SDimitry Andric       CI.getFrontendOpts().ModuleFileExtensions,
203e8d8bef9SDimitry Andric       /*AllowASTWithErrors=*/
204e8d8bef9SDimitry Andric       +CI.getFrontendOpts().AllowPCMWithCompilerErrors,
2050b57cec5SDimitry Andric       /*IncludeTimestamps=*/
20606c3fb27SDimitry Andric       +CI.getFrontendOpts().BuildingImplicitModule &&
20706c3fb27SDimitry Andric           +CI.getFrontendOpts().IncludeTimestamps,
2085f757f3fSDimitry Andric       /*BuildingImplicitModule=*/+CI.getFrontendOpts().BuildingImplicitModule,
2090b57cec5SDimitry Andric       /*ShouldCacheASTInMemory=*/
2100b57cec5SDimitry Andric       +CI.getFrontendOpts().BuildingImplicitModule));
2110b57cec5SDimitry Andric   Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
2125ffd83dbSDimitry Andric       CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
213*0fca6ea1SDimitry Andric   return Consumers;
214*0fca6ea1SDimitry Andric }
215*0fca6ea1SDimitry Andric 
216*0fca6ea1SDimitry Andric std::unique_ptr<ASTConsumer>
217*0fca6ea1SDimitry Andric GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
218*0fca6ea1SDimitry Andric                                         StringRef InFile) {
219*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<ASTConsumer>> Consumers =
220*0fca6ea1SDimitry Andric       CreateMultiplexConsumer(CI, InFile);
221*0fca6ea1SDimitry Andric   if (Consumers.empty())
222*0fca6ea1SDimitry Andric     return nullptr;
223*0fca6ea1SDimitry Andric 
224a7dea167SDimitry Andric   return std::make_unique<MultiplexConsumer>(std::move(Consumers));
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
227e8d8bef9SDimitry Andric bool GenerateModuleAction::shouldEraseOutputFiles() {
228e8d8bef9SDimitry Andric   return !getCompilerInstance().getFrontendOpts().AllowPCMWithCompilerErrors &&
229e8d8bef9SDimitry Andric          ASTFrontendAction::shouldEraseOutputFiles();
230e8d8bef9SDimitry Andric }
231e8d8bef9SDimitry Andric 
2320b57cec5SDimitry Andric bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
2330b57cec5SDimitry Andric     CompilerInstance &CI) {
2340b57cec5SDimitry Andric   if (!CI.getLangOpts().Modules) {
2350b57cec5SDimitry Andric     CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules);
2360b57cec5SDimitry Andric     return false;
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   return GenerateModuleAction::BeginSourceFileAction(CI);
2400b57cec5SDimitry Andric }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric std::unique_ptr<raw_pwrite_stream>
2430b57cec5SDimitry Andric GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
2440b57cec5SDimitry Andric                                                     StringRef InFile) {
2450b57cec5SDimitry Andric   // If no output file was provided, figure out where this module would go
2460b57cec5SDimitry Andric   // in the module cache.
2470b57cec5SDimitry Andric   if (CI.getFrontendOpts().OutputFile.empty()) {
2480b57cec5SDimitry Andric     StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;
2490b57cec5SDimitry Andric     if (ModuleMapFile.empty())
2500b57cec5SDimitry Andric       ModuleMapFile = InFile;
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
2530b57cec5SDimitry Andric     CI.getFrontendOpts().OutputFile =
2540b57cec5SDimitry Andric         HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule,
2550b57cec5SDimitry Andric                                    ModuleMapFile);
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric 
258e8d8bef9SDimitry Andric   // Because this is exposed via libclang we must disable RemoveFileOnSignal.
259e8d8bef9SDimitry Andric   return CI.createDefaultOutputFile(/*Binary=*/true, InFile, /*Extension=*/"",
260e8d8bef9SDimitry Andric                                     /*RemoveFileOnSignal=*/false,
261fe6060f1SDimitry Andric                                     /*CreateMissingDirectories=*/true,
262fe6060f1SDimitry Andric                                     /*ForceUseTemporary=*/true);
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric bool GenerateModuleInterfaceAction::BeginSourceFileAction(
2660b57cec5SDimitry Andric     CompilerInstance &CI) {
2670b57cec5SDimitry Andric   CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   return GenerateModuleAction::BeginSourceFileAction(CI);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2725f757f3fSDimitry Andric std::unique_ptr<ASTConsumer>
2735f757f3fSDimitry Andric GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
2745f757f3fSDimitry Andric                                                  StringRef InFile) {
275*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
2765f757f3fSDimitry Andric 
277*0fca6ea1SDimitry Andric   if (CI.getFrontendOpts().GenReducedBMI &&
278*0fca6ea1SDimitry Andric       !CI.getFrontendOpts().ModuleOutputPath.empty()) {
279*0fca6ea1SDimitry Andric     Consumers.push_back(std::make_unique<ReducedBMIGenerator>(
280*0fca6ea1SDimitry Andric         CI.getPreprocessor(), CI.getModuleCache(),
281*0fca6ea1SDimitry Andric         CI.getFrontendOpts().ModuleOutputPath));
282*0fca6ea1SDimitry Andric   }
283*0fca6ea1SDimitry Andric 
284*0fca6ea1SDimitry Andric   Consumers.push_back(std::make_unique<CXX20ModulesGenerator>(
285*0fca6ea1SDimitry Andric       CI.getPreprocessor(), CI.getModuleCache(),
286*0fca6ea1SDimitry Andric       CI.getFrontendOpts().OutputFile));
287*0fca6ea1SDimitry Andric 
288*0fca6ea1SDimitry Andric   return std::make_unique<MultiplexConsumer>(std::move(Consumers));
2895f757f3fSDimitry Andric }
2905f757f3fSDimitry Andric 
2910b57cec5SDimitry Andric std::unique_ptr<raw_pwrite_stream>
2920b57cec5SDimitry Andric GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
2930b57cec5SDimitry Andric                                                 StringRef InFile) {
2940b57cec5SDimitry Andric   return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric 
297*0fca6ea1SDimitry Andric std::unique_ptr<ASTConsumer>
298*0fca6ea1SDimitry Andric GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
299*0fca6ea1SDimitry Andric                                                         StringRef InFile) {
300*0fca6ea1SDimitry Andric   return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(),
301*0fca6ea1SDimitry Andric                                                CI.getModuleCache(),
302*0fca6ea1SDimitry Andric                                                CI.getFrontendOpts().OutputFile);
303*0fca6ea1SDimitry Andric }
304*0fca6ea1SDimitry Andric 
30581ad6265SDimitry Andric bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
30681ad6265SDimitry Andric   if (!CI.getLangOpts().CPlusPlusModules) {
30781ad6265SDimitry Andric     CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
30881ad6265SDimitry Andric     return false;
30981ad6265SDimitry Andric   }
31081ad6265SDimitry Andric   CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderUnit);
31181ad6265SDimitry Andric   return GenerateModuleAction::BeginSourceFileAction(CI);
31281ad6265SDimitry Andric }
31381ad6265SDimitry Andric 
31481ad6265SDimitry Andric std::unique_ptr<raw_pwrite_stream>
31581ad6265SDimitry Andric GenerateHeaderUnitAction::CreateOutputFile(CompilerInstance &CI,
31681ad6265SDimitry Andric                                            StringRef InFile) {
31781ad6265SDimitry Andric   return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
31881ad6265SDimitry Andric }
31981ad6265SDimitry Andric 
3200b57cec5SDimitry Andric SyntaxOnlyAction::~SyntaxOnlyAction() {
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
3240b57cec5SDimitry Andric SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
325a7dea167SDimitry Andric   return std::make_unique<ASTConsumer>();
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
3290b57cec5SDimitry Andric DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
3300b57cec5SDimitry Andric                                         StringRef InFile) {
331a7dea167SDimitry Andric   return std::make_unique<ASTConsumer>();
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
3350b57cec5SDimitry Andric VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
336a7dea167SDimitry Andric   return std::make_unique<ASTConsumer>();
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric void VerifyPCHAction::ExecuteAction() {
3400b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
3410b57cec5SDimitry Andric   bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
3420b57cec5SDimitry Andric   const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
3430b57cec5SDimitry Andric   std::unique_ptr<ASTReader> Reader(new ASTReader(
3440b57cec5SDimitry Andric       CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),
3450b57cec5SDimitry Andric       CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
3460b57cec5SDimitry Andric       Sysroot.empty() ? "" : Sysroot.c_str(),
347e8d8bef9SDimitry Andric       DisableValidationForModuleKind::None,
348e8d8bef9SDimitry Andric       /*AllowASTWithCompilerErrors*/ false,
3490b57cec5SDimitry Andric       /*AllowConfigurationMismatch*/ true,
3500b57cec5SDimitry Andric       /*ValidateSystemInputs*/ true));
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   Reader->ReadAST(getCurrentFile(),
3530b57cec5SDimitry Andric                   Preamble ? serialization::MK_Preamble
3540b57cec5SDimitry Andric                            : serialization::MK_PCH,
3550b57cec5SDimitry Andric                   SourceLocation(),
3560b57cec5SDimitry Andric                   ASTReader::ARR_ConfigurationMismatch);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric namespace {
3600b57cec5SDimitry Andric struct TemplightEntry {
3610b57cec5SDimitry Andric   std::string Name;
3620b57cec5SDimitry Andric   std::string Kind;
3630b57cec5SDimitry Andric   std::string Event;
3640b57cec5SDimitry Andric   std::string DefinitionLocation;
3650b57cec5SDimitry Andric   std::string PointOfInstantiation;
3660b57cec5SDimitry Andric };
3670b57cec5SDimitry Andric } // namespace
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric namespace llvm {
3700b57cec5SDimitry Andric namespace yaml {
3710b57cec5SDimitry Andric template <> struct MappingTraits<TemplightEntry> {
3720b57cec5SDimitry Andric   static void mapping(IO &io, TemplightEntry &fields) {
3730b57cec5SDimitry Andric     io.mapRequired("name", fields.Name);
3740b57cec5SDimitry Andric     io.mapRequired("kind", fields.Kind);
3750b57cec5SDimitry Andric     io.mapRequired("event", fields.Event);
3760b57cec5SDimitry Andric     io.mapRequired("orig", fields.DefinitionLocation);
3770b57cec5SDimitry Andric     io.mapRequired("poi", fields.PointOfInstantiation);
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric };
3800b57cec5SDimitry Andric } // namespace yaml
3810b57cec5SDimitry Andric } // namespace llvm
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric namespace {
3840b57cec5SDimitry Andric class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
3850b57cec5SDimitry Andric   using CodeSynthesisContext = Sema::CodeSynthesisContext;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric public:
3880b57cec5SDimitry Andric   void initialize(const Sema &) override {}
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   void finalize(const Sema &) override {}
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   void atTemplateBegin(const Sema &TheSema,
3930b57cec5SDimitry Andric                        const CodeSynthesisContext &Inst) override {
3940b57cec5SDimitry Andric     displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
3950b57cec5SDimitry Andric   }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   void atTemplateEnd(const Sema &TheSema,
3980b57cec5SDimitry Andric                      const CodeSynthesisContext &Inst) override {
3990b57cec5SDimitry Andric     displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric private:
4030b57cec5SDimitry Andric   static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
4040b57cec5SDimitry Andric     switch (Kind) {
4050b57cec5SDimitry Andric     case CodeSynthesisContext::TemplateInstantiation:
4060b57cec5SDimitry Andric       return "TemplateInstantiation";
4070b57cec5SDimitry Andric     case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
4080b57cec5SDimitry Andric       return "DefaultTemplateArgumentInstantiation";
4090b57cec5SDimitry Andric     case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
4100b57cec5SDimitry Andric       return "DefaultFunctionArgumentInstantiation";
4110b57cec5SDimitry Andric     case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
4120b57cec5SDimitry Andric       return "ExplicitTemplateArgumentSubstitution";
4130b57cec5SDimitry Andric     case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
4140b57cec5SDimitry Andric       return "DeducedTemplateArgumentSubstitution";
41506c3fb27SDimitry Andric     case CodeSynthesisContext::LambdaExpressionSubstitution:
41606c3fb27SDimitry Andric       return "LambdaExpressionSubstitution";
4170b57cec5SDimitry Andric     case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
4180b57cec5SDimitry Andric       return "PriorTemplateArgumentSubstitution";
4190b57cec5SDimitry Andric     case CodeSynthesisContext::DefaultTemplateArgumentChecking:
4200b57cec5SDimitry Andric       return "DefaultTemplateArgumentChecking";
4210b57cec5SDimitry Andric     case CodeSynthesisContext::ExceptionSpecEvaluation:
4220b57cec5SDimitry Andric       return "ExceptionSpecEvaluation";
4230b57cec5SDimitry Andric     case CodeSynthesisContext::ExceptionSpecInstantiation:
4240b57cec5SDimitry Andric       return "ExceptionSpecInstantiation";
4250b57cec5SDimitry Andric     case CodeSynthesisContext::DeclaringSpecialMember:
4260b57cec5SDimitry Andric       return "DeclaringSpecialMember";
427480093f4SDimitry Andric     case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
428480093f4SDimitry Andric       return "DeclaringImplicitEqualityComparison";
4290b57cec5SDimitry Andric     case CodeSynthesisContext::DefiningSynthesizedFunction:
4300b57cec5SDimitry Andric       return "DefiningSynthesizedFunction";
431a7dea167SDimitry Andric     case CodeSynthesisContext::RewritingOperatorAsSpaceship:
432a7dea167SDimitry Andric       return "RewritingOperatorAsSpaceship";
4330b57cec5SDimitry Andric     case CodeSynthesisContext::Memoization:
4340b57cec5SDimitry Andric       return "Memoization";
435a7dea167SDimitry Andric     case CodeSynthesisContext::ConstraintsCheck:
436a7dea167SDimitry Andric       return "ConstraintsCheck";
437a7dea167SDimitry Andric     case CodeSynthesisContext::ConstraintSubstitution:
438a7dea167SDimitry Andric       return "ConstraintSubstitution";
439480093f4SDimitry Andric     case CodeSynthesisContext::ConstraintNormalization:
440480093f4SDimitry Andric       return "ConstraintNormalization";
441bdd1243dSDimitry Andric     case CodeSynthesisContext::RequirementParameterInstantiation:
442bdd1243dSDimitry Andric       return "RequirementParameterInstantiation";
443480093f4SDimitry Andric     case CodeSynthesisContext::ParameterMappingSubstitution:
444480093f4SDimitry Andric       return "ParameterMappingSubstitution";
44555e4f9d5SDimitry Andric     case CodeSynthesisContext::RequirementInstantiation:
44655e4f9d5SDimitry Andric       return "RequirementInstantiation";
44755e4f9d5SDimitry Andric     case CodeSynthesisContext::NestedRequirementConstraintsCheck:
44855e4f9d5SDimitry Andric       return "NestedRequirementConstraintsCheck";
4495ffd83dbSDimitry Andric     case CodeSynthesisContext::InitializingStructuredBinding:
4505ffd83dbSDimitry Andric       return "InitializingStructuredBinding";
4515ffd83dbSDimitry Andric     case CodeSynthesisContext::MarkingClassDllexported:
4525ffd83dbSDimitry Andric       return "MarkingClassDllexported";
45381ad6265SDimitry Andric     case CodeSynthesisContext::BuildingBuiltinDumpStructCall:
45481ad6265SDimitry Andric       return "BuildingBuiltinDumpStructCall";
45506c3fb27SDimitry Andric     case CodeSynthesisContext::BuildingDeductionGuides:
45606c3fb27SDimitry Andric       return "BuildingDeductionGuides";
457*0fca6ea1SDimitry Andric     case CodeSynthesisContext::TypeAliasTemplateInstantiation:
458*0fca6ea1SDimitry Andric       return "TypeAliasTemplateInstantiation";
4590b57cec5SDimitry Andric     }
4600b57cec5SDimitry Andric     return "";
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   template <bool BeginInstantiation>
4640b57cec5SDimitry Andric   static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,
4650b57cec5SDimitry Andric                                     const CodeSynthesisContext &Inst) {
4660b57cec5SDimitry Andric     std::string YAML;
4670b57cec5SDimitry Andric     {
4680b57cec5SDimitry Andric       llvm::raw_string_ostream OS(YAML);
4690b57cec5SDimitry Andric       llvm::yaml::Output YO(OS);
4700b57cec5SDimitry Andric       TemplightEntry Entry =
4710b57cec5SDimitry Andric           getTemplightEntry<BeginInstantiation>(TheSema, Inst);
4720b57cec5SDimitry Andric       llvm::yaml::EmptyContext Context;
4730b57cec5SDimitry Andric       llvm::yaml::yamlize(YO, Entry, true, Context);
4740b57cec5SDimitry Andric     }
4750b57cec5SDimitry Andric     Out << "---" << YAML << "\n";
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric 
47804eeddc0SDimitry Andric   static void printEntryName(const Sema &TheSema, const Decl *Entity,
47904eeddc0SDimitry Andric                              llvm::raw_string_ostream &OS) {
48004eeddc0SDimitry Andric     auto *NamedTemplate = cast<NamedDecl>(Entity);
48104eeddc0SDimitry Andric 
48204eeddc0SDimitry Andric     PrintingPolicy Policy = TheSema.Context.getPrintingPolicy();
48304eeddc0SDimitry Andric     // FIXME: Also ask for FullyQualifiedNames?
48404eeddc0SDimitry Andric     Policy.SuppressDefaultTemplateArgs = false;
48504eeddc0SDimitry Andric     NamedTemplate->getNameForDiagnostic(OS, Policy, true);
48604eeddc0SDimitry Andric 
48704eeddc0SDimitry Andric     if (!OS.str().empty())
48804eeddc0SDimitry Andric       return;
48904eeddc0SDimitry Andric 
49004eeddc0SDimitry Andric     Decl *Ctx = Decl::castFromDeclContext(NamedTemplate->getDeclContext());
49104eeddc0SDimitry Andric     NamedDecl *NamedCtx = dyn_cast_or_null<NamedDecl>(Ctx);
49204eeddc0SDimitry Andric 
49304eeddc0SDimitry Andric     if (const auto *Decl = dyn_cast<TagDecl>(NamedTemplate)) {
49404eeddc0SDimitry Andric       if (const auto *R = dyn_cast<RecordDecl>(Decl)) {
49504eeddc0SDimitry Andric         if (R->isLambda()) {
49604eeddc0SDimitry Andric           OS << "lambda at ";
49704eeddc0SDimitry Andric           Decl->getLocation().print(OS, TheSema.getSourceManager());
49804eeddc0SDimitry Andric           return;
49904eeddc0SDimitry Andric         }
50004eeddc0SDimitry Andric       }
50104eeddc0SDimitry Andric       OS << "unnamed " << Decl->getKindName();
50204eeddc0SDimitry Andric       return;
50304eeddc0SDimitry Andric     }
50404eeddc0SDimitry Andric 
50506c3fb27SDimitry Andric     assert(NamedCtx && "NamedCtx cannot be null");
50606c3fb27SDimitry Andric 
50704eeddc0SDimitry Andric     if (const auto *Decl = dyn_cast<ParmVarDecl>(NamedTemplate)) {
50804eeddc0SDimitry Andric       OS << "unnamed function parameter " << Decl->getFunctionScopeIndex()
50904eeddc0SDimitry Andric          << " ";
51004eeddc0SDimitry Andric       if (Decl->getFunctionScopeDepth() > 0)
51104eeddc0SDimitry Andric         OS << "(at depth " << Decl->getFunctionScopeDepth() << ") ";
51204eeddc0SDimitry Andric       OS << "of ";
51304eeddc0SDimitry Andric       NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
51404eeddc0SDimitry Andric       return;
51504eeddc0SDimitry Andric     }
51604eeddc0SDimitry Andric 
51704eeddc0SDimitry Andric     if (const auto *Decl = dyn_cast<TemplateTypeParmDecl>(NamedTemplate)) {
51804eeddc0SDimitry Andric       if (const Type *Ty = Decl->getTypeForDecl()) {
51904eeddc0SDimitry Andric         if (const auto *TTPT = dyn_cast_or_null<TemplateTypeParmType>(Ty)) {
52004eeddc0SDimitry Andric           OS << "unnamed template type parameter " << TTPT->getIndex() << " ";
52104eeddc0SDimitry Andric           if (TTPT->getDepth() > 0)
52204eeddc0SDimitry Andric             OS << "(at depth " << TTPT->getDepth() << ") ";
52304eeddc0SDimitry Andric           OS << "of ";
52404eeddc0SDimitry Andric           NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
52504eeddc0SDimitry Andric           return;
52604eeddc0SDimitry Andric         }
52704eeddc0SDimitry Andric       }
52804eeddc0SDimitry Andric     }
52904eeddc0SDimitry Andric 
53004eeddc0SDimitry Andric     if (const auto *Decl = dyn_cast<NonTypeTemplateParmDecl>(NamedTemplate)) {
53104eeddc0SDimitry Andric       OS << "unnamed template non-type parameter " << Decl->getIndex() << " ";
53204eeddc0SDimitry Andric       if (Decl->getDepth() > 0)
53304eeddc0SDimitry Andric         OS << "(at depth " << Decl->getDepth() << ") ";
53404eeddc0SDimitry Andric       OS << "of ";
53504eeddc0SDimitry Andric       NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
53604eeddc0SDimitry Andric       return;
53704eeddc0SDimitry Andric     }
53804eeddc0SDimitry Andric 
53904eeddc0SDimitry Andric     if (const auto *Decl = dyn_cast<TemplateTemplateParmDecl>(NamedTemplate)) {
54004eeddc0SDimitry Andric       OS << "unnamed template template parameter " << Decl->getIndex() << " ";
54104eeddc0SDimitry Andric       if (Decl->getDepth() > 0)
54204eeddc0SDimitry Andric         OS << "(at depth " << Decl->getDepth() << ") ";
54304eeddc0SDimitry Andric       OS << "of ";
54404eeddc0SDimitry Andric       NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
54504eeddc0SDimitry Andric       return;
54604eeddc0SDimitry Andric     }
54704eeddc0SDimitry Andric 
54804eeddc0SDimitry Andric     llvm_unreachable("Failed to retrieve a name for this entry!");
54904eeddc0SDimitry Andric     OS << "unnamed identifier";
55004eeddc0SDimitry Andric   }
55104eeddc0SDimitry Andric 
5520b57cec5SDimitry Andric   template <bool BeginInstantiation>
5530b57cec5SDimitry Andric   static TemplightEntry getTemplightEntry(const Sema &TheSema,
5540b57cec5SDimitry Andric                                           const CodeSynthesisContext &Inst) {
5550b57cec5SDimitry Andric     TemplightEntry Entry;
5560b57cec5SDimitry Andric     Entry.Kind = toString(Inst.Kind);
5570b57cec5SDimitry Andric     Entry.Event = BeginInstantiation ? "Begin" : "End";
5580b57cec5SDimitry Andric     llvm::raw_string_ostream OS(Entry.Name);
55904eeddc0SDimitry Andric     printEntryName(TheSema, Inst.Entity, OS);
5600b57cec5SDimitry Andric     const PresumedLoc DefLoc =
5610b57cec5SDimitry Andric         TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
5620b57cec5SDimitry Andric     if (!DefLoc.isInvalid())
5630b57cec5SDimitry Andric       Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
5640b57cec5SDimitry Andric                                  std::to_string(DefLoc.getLine()) + ":" +
5650b57cec5SDimitry Andric                                  std::to_string(DefLoc.getColumn());
5660b57cec5SDimitry Andric     const PresumedLoc PoiLoc =
5670b57cec5SDimitry Andric         TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
5680b57cec5SDimitry Andric     if (!PoiLoc.isInvalid()) {
5690b57cec5SDimitry Andric       Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
5700b57cec5SDimitry Andric                                    std::to_string(PoiLoc.getLine()) + ":" +
5710b57cec5SDimitry Andric                                    std::to_string(PoiLoc.getColumn());
5720b57cec5SDimitry Andric     }
5730b57cec5SDimitry Andric     return Entry;
5740b57cec5SDimitry Andric   }
5750b57cec5SDimitry Andric };
5760b57cec5SDimitry Andric } // namespace
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
5790b57cec5SDimitry Andric TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
580a7dea167SDimitry Andric   return std::make_unique<ASTConsumer>();
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric void TemplightDumpAction::ExecuteAction() {
5840b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   // This part is normally done by ASTFrontEndAction, but needs to happen
5870b57cec5SDimitry Andric   // before Templight observers can be created
5880b57cec5SDimitry Andric   // FIXME: Move the truncation aspect of this into Sema, we delayed this till
5890b57cec5SDimitry Andric   // here so the source manager would be initialized.
5900b57cec5SDimitry Andric   EnsureSemaIsCreated(CI, *this);
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   CI.getSema().TemplateInstCallbacks.push_back(
593a7dea167SDimitry Andric       std::make_unique<DefaultTemplateInstCallback>());
5940b57cec5SDimitry Andric   ASTFrontendAction::ExecuteAction();
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric namespace {
5980b57cec5SDimitry Andric   /// AST reader listener that dumps module information for a module
5990b57cec5SDimitry Andric   /// file.
6000b57cec5SDimitry Andric   class DumpModuleInfoListener : public ASTReaderListener {
6010b57cec5SDimitry Andric     llvm::raw_ostream &Out;
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   public:
6040b57cec5SDimitry Andric     DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric #define DUMP_BOOLEAN(Value, Text)                       \
6070b57cec5SDimitry Andric     Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric     bool ReadFullVersionInformation(StringRef FullVersion) override {
6100b57cec5SDimitry Andric       Out.indent(2)
6110b57cec5SDimitry Andric         << "Generated by "
6120b57cec5SDimitry Andric         << (FullVersion == getClangFullRepositoryVersion()? "this"
6130b57cec5SDimitry Andric                                                           : "a different")
6140b57cec5SDimitry Andric         << " Clang: " << FullVersion << "\n";
6150b57cec5SDimitry Andric       return ASTReaderListener::ReadFullVersionInformation(FullVersion);
6160b57cec5SDimitry Andric     }
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric     void ReadModuleName(StringRef ModuleName) override {
6190b57cec5SDimitry Andric       Out.indent(2) << "Module name: " << ModuleName << "\n";
6200b57cec5SDimitry Andric     }
6210b57cec5SDimitry Andric     void ReadModuleMapFile(StringRef ModuleMapPath) override {
6220b57cec5SDimitry Andric       Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
6230b57cec5SDimitry Andric     }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
6260b57cec5SDimitry Andric                              bool AllowCompatibleDifferences) override {
6270b57cec5SDimitry Andric       Out.indent(2) << "Language options:\n";
6280b57cec5SDimitry Andric #define LANGOPT(Name, Bits, Default, Description) \
6290b57cec5SDimitry Andric       DUMP_BOOLEAN(LangOpts.Name, Description);
6300b57cec5SDimitry Andric #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
6310b57cec5SDimitry Andric       Out.indent(4) << Description << ": "                   \
6320b57cec5SDimitry Andric                     << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
6330b57cec5SDimitry Andric #define VALUE_LANGOPT(Name, Bits, Default, Description) \
6340b57cec5SDimitry Andric       Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
6350b57cec5SDimitry Andric #define BENIGN_LANGOPT(Name, Bits, Default, Description)
6360b57cec5SDimitry Andric #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
6370b57cec5SDimitry Andric #include "clang/Basic/LangOptions.def"
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric       if (!LangOpts.ModuleFeatures.empty()) {
6400b57cec5SDimitry Andric         Out.indent(4) << "Module features:\n";
6410b57cec5SDimitry Andric         for (StringRef Feature : LangOpts.ModuleFeatures)
6420b57cec5SDimitry Andric           Out.indent(6) << Feature << "\n";
6430b57cec5SDimitry Andric       }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric       return false;
6460b57cec5SDimitry Andric     }
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
6490b57cec5SDimitry Andric                            bool AllowCompatibleDifferences) override {
6500b57cec5SDimitry Andric       Out.indent(2) << "Target options:\n";
6510b57cec5SDimitry Andric       Out.indent(4) << "  Triple: " << TargetOpts.Triple << "\n";
6520b57cec5SDimitry Andric       Out.indent(4) << "  CPU: " << TargetOpts.CPU << "\n";
653e8d8bef9SDimitry Andric       Out.indent(4) << "  TuneCPU: " << TargetOpts.TuneCPU << "\n";
6540b57cec5SDimitry Andric       Out.indent(4) << "  ABI: " << TargetOpts.ABI << "\n";
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric       if (!TargetOpts.FeaturesAsWritten.empty()) {
6570b57cec5SDimitry Andric         Out.indent(4) << "Target features:\n";
6580b57cec5SDimitry Andric         for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
6590b57cec5SDimitry Andric              I != N; ++I) {
6600b57cec5SDimitry Andric           Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
6610b57cec5SDimitry Andric         }
6620b57cec5SDimitry Andric       }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric       return false;
6650b57cec5SDimitry Andric     }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric     bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
6680b57cec5SDimitry Andric                                bool Complain) override {
6690b57cec5SDimitry Andric       Out.indent(2) << "Diagnostic options:\n";
6700b57cec5SDimitry Andric #define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
6710b57cec5SDimitry Andric #define ENUM_DIAGOPT(Name, Type, Bits, Default) \
6720b57cec5SDimitry Andric       Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n";
6730b57cec5SDimitry Andric #define VALUE_DIAGOPT(Name, Bits, Default) \
6740b57cec5SDimitry Andric       Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";
6750b57cec5SDimitry Andric #include "clang/Basic/DiagnosticOptions.def"
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric       Out.indent(4) << "Diagnostic flags:\n";
6780b57cec5SDimitry Andric       for (const std::string &Warning : DiagOpts->Warnings)
6790b57cec5SDimitry Andric         Out.indent(6) << "-W" << Warning << "\n";
6800b57cec5SDimitry Andric       for (const std::string &Remark : DiagOpts->Remarks)
6810b57cec5SDimitry Andric         Out.indent(6) << "-R" << Remark << "\n";
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric       return false;
6840b57cec5SDimitry Andric     }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
6870b57cec5SDimitry Andric                                  StringRef SpecificModuleCachePath,
6880b57cec5SDimitry Andric                                  bool Complain) override {
6890b57cec5SDimitry Andric       Out.indent(2) << "Header search options:\n";
6900b57cec5SDimitry Andric       Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
6910b57cec5SDimitry Andric       Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n";
6920b57cec5SDimitry Andric       Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
6930b57cec5SDimitry Andric       DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
6940b57cec5SDimitry Andric                    "Use builtin include directories [-nobuiltininc]");
6950b57cec5SDimitry Andric       DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
6960b57cec5SDimitry Andric                    "Use standard system include directories [-nostdinc]");
6970b57cec5SDimitry Andric       DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
6980b57cec5SDimitry Andric                    "Use standard C++ include directories [-nostdinc++]");
6990b57cec5SDimitry Andric       DUMP_BOOLEAN(HSOpts.UseLibcxx,
7000b57cec5SDimitry Andric                    "Use libc++ (rather than libstdc++) [-stdlib=]");
7010b57cec5SDimitry Andric       return false;
7020b57cec5SDimitry Andric     }
7030b57cec5SDimitry Andric 
7045f757f3fSDimitry Andric     bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
7055f757f3fSDimitry Andric                                bool Complain) override {
7065f757f3fSDimitry Andric       Out.indent(2) << "Header search paths:\n";
7075f757f3fSDimitry Andric       Out.indent(4) << "User entries:\n";
7085f757f3fSDimitry Andric       for (const auto &Entry : HSOpts.UserEntries)
7095f757f3fSDimitry Andric         Out.indent(6) << Entry.Path << "\n";
7105f757f3fSDimitry Andric       Out.indent(4) << "System header prefixes:\n";
7115f757f3fSDimitry Andric       for (const auto &Prefix : HSOpts.SystemHeaderPrefixes)
7125f757f3fSDimitry Andric         Out.indent(6) << Prefix.Prefix << "\n";
7135f757f3fSDimitry Andric       Out.indent(4) << "VFS overlay files:\n";
7145f757f3fSDimitry Andric       for (const auto &Overlay : HSOpts.VFSOverlayFiles)
7155f757f3fSDimitry Andric         Out.indent(6) << Overlay << "\n";
7165f757f3fSDimitry Andric       return false;
7175f757f3fSDimitry Andric     }
7185f757f3fSDimitry Andric 
7190b57cec5SDimitry Andric     bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
7205f757f3fSDimitry Andric                                  bool ReadMacros, bool Complain,
7210b57cec5SDimitry Andric                                  std::string &SuggestedPredefines) override {
7220b57cec5SDimitry Andric       Out.indent(2) << "Preprocessor options:\n";
7230b57cec5SDimitry Andric       DUMP_BOOLEAN(PPOpts.UsePredefines,
7240b57cec5SDimitry Andric                    "Uses compiler/target-specific predefines [-undef]");
7250b57cec5SDimitry Andric       DUMP_BOOLEAN(PPOpts.DetailedRecord,
7260b57cec5SDimitry Andric                    "Uses detailed preprocessing record (for indexing)");
7270b57cec5SDimitry Andric 
7285f757f3fSDimitry Andric       if (ReadMacros) {
7290b57cec5SDimitry Andric         Out.indent(4) << "Predefined macros:\n";
7300b57cec5SDimitry Andric       }
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric       for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
7330b57cec5SDimitry Andric              I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
7340b57cec5SDimitry Andric            I != IEnd; ++I) {
7350b57cec5SDimitry Andric         Out.indent(6);
7360b57cec5SDimitry Andric         if (I->second)
7370b57cec5SDimitry Andric           Out << "-U";
7380b57cec5SDimitry Andric         else
7390b57cec5SDimitry Andric           Out << "-D";
7400b57cec5SDimitry Andric         Out << I->first << "\n";
7410b57cec5SDimitry Andric       }
7420b57cec5SDimitry Andric       return false;
7430b57cec5SDimitry Andric     }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric     /// Indicates that a particular module file extension has been read.
7460b57cec5SDimitry Andric     void readModuleFileExtension(
7470b57cec5SDimitry Andric            const ModuleFileExtensionMetadata &Metadata) override {
7480b57cec5SDimitry Andric       Out.indent(2) << "Module file extension '"
7490b57cec5SDimitry Andric                     << Metadata.BlockName << "' " << Metadata.MajorVersion
7500b57cec5SDimitry Andric                     << "." << Metadata.MinorVersion;
7510b57cec5SDimitry Andric       if (!Metadata.UserInfo.empty()) {
7520b57cec5SDimitry Andric         Out << ": ";
7530b57cec5SDimitry Andric         Out.write_escaped(Metadata.UserInfo);
7540b57cec5SDimitry Andric       }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric       Out << "\n";
7570b57cec5SDimitry Andric     }
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric     /// Tells the \c ASTReaderListener that we want to receive the
7600b57cec5SDimitry Andric     /// input files of the AST file via \c visitInputFile.
7610b57cec5SDimitry Andric     bool needsInputFileVisitation() override { return true; }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric     /// Tells the \c ASTReaderListener that we want to receive the
7640b57cec5SDimitry Andric     /// input files of the AST file via \c visitInputFile.
7650b57cec5SDimitry Andric     bool needsSystemInputFileVisitation() override { return true; }
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric     /// Indicates that the AST file contains particular input file.
7680b57cec5SDimitry Andric     ///
7690b57cec5SDimitry Andric     /// \returns true to continue receiving the next input file, false to stop.
7700b57cec5SDimitry Andric     bool visitInputFile(StringRef Filename, bool isSystem,
7710b57cec5SDimitry Andric                         bool isOverridden, bool isExplicitModule) override {
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric       Out.indent(2) << "Input file: " << Filename;
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric       if (isSystem || isOverridden || isExplicitModule) {
7760b57cec5SDimitry Andric         Out << " [";
7770b57cec5SDimitry Andric         if (isSystem) {
7780b57cec5SDimitry Andric           Out << "System";
7790b57cec5SDimitry Andric           if (isOverridden || isExplicitModule)
7800b57cec5SDimitry Andric             Out << ", ";
7810b57cec5SDimitry Andric         }
7820b57cec5SDimitry Andric         if (isOverridden) {
7830b57cec5SDimitry Andric           Out << "Overridden";
7840b57cec5SDimitry Andric           if (isExplicitModule)
7850b57cec5SDimitry Andric             Out << ", ";
7860b57cec5SDimitry Andric         }
7870b57cec5SDimitry Andric         if (isExplicitModule)
7880b57cec5SDimitry Andric           Out << "ExplicitModule";
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric         Out << "]";
7910b57cec5SDimitry Andric       }
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric       Out << "\n";
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric       return true;
7960b57cec5SDimitry Andric     }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric     /// Returns true if this \c ASTReaderListener wants to receive the
7990b57cec5SDimitry Andric     /// imports of the AST file via \c visitImport, false otherwise.
8000b57cec5SDimitry Andric     bool needsImportVisitation() const override { return true; }
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric     /// If needsImportVisitation returns \c true, this is called for each
8030b57cec5SDimitry Andric     /// AST file imported by this AST file.
8040b57cec5SDimitry Andric     void visitImport(StringRef ModuleName, StringRef Filename) override {
8050b57cec5SDimitry Andric       Out.indent(2) << "Imports module '" << ModuleName
8060b57cec5SDimitry Andric                     << "': " << Filename.str() << "\n";
8070b57cec5SDimitry Andric     }
8080b57cec5SDimitry Andric #undef DUMP_BOOLEAN
8090b57cec5SDimitry Andric   };
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {
8130b57cec5SDimitry Andric   // The Object file reader also supports raw ast files and there is no point in
8140b57cec5SDimitry Andric   // being strict about the module file format in -module-file-info mode.
8150b57cec5SDimitry Andric   CI.getHeaderSearchOpts().ModuleFormat = "obj";
8160b57cec5SDimitry Andric   return true;
8170b57cec5SDimitry Andric }
8180b57cec5SDimitry Andric 
81981ad6265SDimitry Andric static StringRef ModuleKindName(Module::ModuleKind MK) {
82081ad6265SDimitry Andric   switch (MK) {
82181ad6265SDimitry Andric   case Module::ModuleMapModule:
82281ad6265SDimitry Andric     return "Module Map Module";
82381ad6265SDimitry Andric   case Module::ModuleInterfaceUnit:
82481ad6265SDimitry Andric     return "Interface Unit";
82506c3fb27SDimitry Andric   case Module::ModuleImplementationUnit:
82606c3fb27SDimitry Andric     return "Implementation Unit";
82781ad6265SDimitry Andric   case Module::ModulePartitionInterface:
82881ad6265SDimitry Andric     return "Partition Interface";
82981ad6265SDimitry Andric   case Module::ModulePartitionImplementation:
83081ad6265SDimitry Andric     return "Partition Implementation";
83181ad6265SDimitry Andric   case Module::ModuleHeaderUnit:
83281ad6265SDimitry Andric     return "Header Unit";
83306c3fb27SDimitry Andric   case Module::ExplicitGlobalModuleFragment:
83481ad6265SDimitry Andric     return "Global Module Fragment";
83506c3fb27SDimitry Andric   case Module::ImplicitGlobalModuleFragment:
83606c3fb27SDimitry Andric     return "Implicit Module Fragment";
83781ad6265SDimitry Andric   case Module::PrivateModuleFragment:
83881ad6265SDimitry Andric     return "Private Module Fragment";
83981ad6265SDimitry Andric   }
84081ad6265SDimitry Andric   llvm_unreachable("unknown module kind!");
84181ad6265SDimitry Andric }
84281ad6265SDimitry Andric 
8430b57cec5SDimitry Andric void DumpModuleInfoAction::ExecuteAction() {
844bdd1243dSDimitry Andric   CompilerInstance &CI = getCompilerInstance();
845*0fca6ea1SDimitry Andric 
846*0fca6ea1SDimitry Andric   // Don't process files of type other than module to avoid crash
847*0fca6ea1SDimitry Andric   if (!isCurrentFileAST()) {
848*0fca6ea1SDimitry Andric     CI.getDiagnostics().Report(diag::err_file_is_not_module)
849*0fca6ea1SDimitry Andric         << getCurrentFile();
850*0fca6ea1SDimitry Andric     return;
851*0fca6ea1SDimitry Andric   }
852*0fca6ea1SDimitry Andric 
853*0fca6ea1SDimitry Andric   // Set up the output file.
854bdd1243dSDimitry Andric   StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
8550b57cec5SDimitry Andric   if (!OutputFileName.empty() && OutputFileName != "-") {
8560b57cec5SDimitry Andric     std::error_code EC;
85706c3fb27SDimitry Andric     OutputStream.reset(new llvm::raw_fd_ostream(
85806c3fb27SDimitry Andric         OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF));
8590b57cec5SDimitry Andric   }
860753f127fSDimitry Andric   llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs();
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   Out << "Information for module file '" << getCurrentFile() << "':\n";
863bdd1243dSDimitry Andric   auto &FileMgr = CI.getFileManager();
8640b57cec5SDimitry Andric   auto Buffer = FileMgr.getBufferForFile(getCurrentFile());
8650b57cec5SDimitry Andric   StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();
866*0fca6ea1SDimitry Andric   bool IsRaw = Magic.starts_with("CPCH");
8670b57cec5SDimitry Andric   Out << "  Module format: " << (IsRaw ? "raw" : "obj") << "\n";
8680b57cec5SDimitry Andric 
869bdd1243dSDimitry Andric   Preprocessor &PP = CI.getPreprocessor();
8700b57cec5SDimitry Andric   DumpModuleInfoListener Listener(Out);
87181ad6265SDimitry Andric   HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
87281ad6265SDimitry Andric 
87381ad6265SDimitry Andric   // The FrontendAction::BeginSourceFile () method loads the AST so that much
87481ad6265SDimitry Andric   // of the information is already available and modules should have been
87581ad6265SDimitry Andric   // loaded.
87681ad6265SDimitry Andric 
87781ad6265SDimitry Andric   const LangOptions &LO = getCurrentASTUnit().getLangOpts();
87881ad6265SDimitry Andric   if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
87981ad6265SDimitry Andric     ASTReader *R = getCurrentASTUnit().getASTReader().get();
88081ad6265SDimitry Andric     unsigned SubModuleCount = R->getTotalNumSubmodules();
88181ad6265SDimitry Andric     serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
88281ad6265SDimitry Andric     Out << "  ====== C++20 Module structure ======\n";
88381ad6265SDimitry Andric 
88481ad6265SDimitry Andric     if (MF.ModuleName != LO.CurrentModule)
88581ad6265SDimitry Andric       Out << "  Mismatched module names : " << MF.ModuleName << " and "
88681ad6265SDimitry Andric           << LO.CurrentModule << "\n";
88781ad6265SDimitry Andric 
88881ad6265SDimitry Andric     struct SubModInfo {
88981ad6265SDimitry Andric       unsigned Idx;
89081ad6265SDimitry Andric       Module *Mod;
89181ad6265SDimitry Andric       Module::ModuleKind Kind;
89281ad6265SDimitry Andric       std::string &Name;
89381ad6265SDimitry Andric       bool Seen;
89481ad6265SDimitry Andric     };
89581ad6265SDimitry Andric     std::map<std::string, SubModInfo> SubModMap;
89681ad6265SDimitry Andric     auto PrintSubMapEntry = [&](std::string Name, Module::ModuleKind Kind) {
89781ad6265SDimitry Andric       Out << "    " << ModuleKindName(Kind) << " '" << Name << "'";
89881ad6265SDimitry Andric       auto I = SubModMap.find(Name);
89981ad6265SDimitry Andric       if (I == SubModMap.end())
90081ad6265SDimitry Andric         Out << " was not found in the sub modules!\n";
90181ad6265SDimitry Andric       else {
90281ad6265SDimitry Andric         I->second.Seen = true;
90381ad6265SDimitry Andric         Out << " is at index #" << I->second.Idx << "\n";
90481ad6265SDimitry Andric       }
90581ad6265SDimitry Andric     };
90681ad6265SDimitry Andric     Module *Primary = nullptr;
90781ad6265SDimitry Andric     for (unsigned Idx = 0; Idx <= SubModuleCount; ++Idx) {
90881ad6265SDimitry Andric       Module *M = R->getModule(Idx);
90981ad6265SDimitry Andric       if (!M)
91081ad6265SDimitry Andric         continue;
91181ad6265SDimitry Andric       if (M->Name == LO.CurrentModule) {
91281ad6265SDimitry Andric         Primary = M;
91381ad6265SDimitry Andric         Out << "  " << ModuleKindName(M->Kind) << " '" << LO.CurrentModule
91481ad6265SDimitry Andric             << "' is the Primary Module at index #" << Idx << "\n";
91581ad6265SDimitry Andric         SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, true}});
91681ad6265SDimitry Andric       } else
91781ad6265SDimitry Andric         SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, false}});
91881ad6265SDimitry Andric     }
91981ad6265SDimitry Andric     if (Primary) {
92081ad6265SDimitry Andric       if (!Primary->submodules().empty())
92181ad6265SDimitry Andric         Out << "   Sub Modules:\n";
922bdd1243dSDimitry Andric       for (auto *MI : Primary->submodules()) {
92381ad6265SDimitry Andric         PrintSubMapEntry(MI->Name, MI->Kind);
92481ad6265SDimitry Andric       }
92581ad6265SDimitry Andric       if (!Primary->Imports.empty())
92681ad6265SDimitry Andric         Out << "   Imports:\n";
927bdd1243dSDimitry Andric       for (auto *IMP : Primary->Imports) {
92881ad6265SDimitry Andric         PrintSubMapEntry(IMP->Name, IMP->Kind);
92981ad6265SDimitry Andric       }
93081ad6265SDimitry Andric       if (!Primary->Exports.empty())
93181ad6265SDimitry Andric         Out << "   Exports:\n";
93281ad6265SDimitry Andric       for (unsigned MN = 0, N = Primary->Exports.size(); MN != N; ++MN) {
93381ad6265SDimitry Andric         if (Module *M = Primary->Exports[MN].getPointer()) {
93481ad6265SDimitry Andric           PrintSubMapEntry(M->Name, M->Kind);
93581ad6265SDimitry Andric         }
93681ad6265SDimitry Andric       }
93781ad6265SDimitry Andric     }
938bdd1243dSDimitry Andric 
939bdd1243dSDimitry Andric     // Emit the macro definitions in the module file so that we can know how
940bdd1243dSDimitry Andric     // much definitions in the module file quickly.
941bdd1243dSDimitry Andric     // TODO: Emit the macro definition bodies completely.
942bdd1243dSDimitry Andric     if (auto FilteredMacros = llvm::make_filter_range(
943bdd1243dSDimitry Andric             R->getPreprocessor().macros(),
944bdd1243dSDimitry Andric             [](const auto &Macro) { return Macro.first->isFromAST(); });
945bdd1243dSDimitry Andric         !FilteredMacros.empty()) {
946bdd1243dSDimitry Andric       Out << "   Macro Definitions:\n";
947bdd1243dSDimitry Andric       for (/*<IdentifierInfo *, MacroState> pair*/ const auto &Macro :
948bdd1243dSDimitry Andric            FilteredMacros)
949bdd1243dSDimitry Andric         Out << "     " << Macro.first->getName() << "\n";
950bdd1243dSDimitry Andric     }
951bdd1243dSDimitry Andric 
95281ad6265SDimitry Andric     // Now let's print out any modules we did not see as part of the Primary.
95306c3fb27SDimitry Andric     for (const auto &SM : SubModMap) {
95481ad6265SDimitry Andric       if (!SM.second.Seen && SM.second.Mod) {
95581ad6265SDimitry Andric         Out << "  " << ModuleKindName(SM.second.Kind) << " '" << SM.first
95681ad6265SDimitry Andric             << "' at index #" << SM.second.Idx
95781ad6265SDimitry Andric             << " has no direct reference in the Primary\n";
95881ad6265SDimitry Andric       }
95981ad6265SDimitry Andric     }
96081ad6265SDimitry Andric     Out << "  ====== ======\n";
96181ad6265SDimitry Andric   }
96281ad6265SDimitry Andric 
96381ad6265SDimitry Andric   // The reminder of the output is produced from the listener as the AST
96481ad6265SDimitry Andric   // FileCcontrolBlock is (re-)parsed.
9650b57cec5SDimitry Andric   ASTReader::readASTFileControlBlock(
966bdd1243dSDimitry Andric       getCurrentFile(), FileMgr, CI.getModuleCache(),
967bdd1243dSDimitry Andric       CI.getPCHContainerReader(),
9680b57cec5SDimitry Andric       /*FindModuleFileExtensions=*/true, Listener,
9690b57cec5SDimitry Andric       HSOpts.ModulesValidateDiagnosticOptions);
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9730b57cec5SDimitry Andric // Preprocessor Actions
9740b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric void DumpRawTokensAction::ExecuteAction() {
9770b57cec5SDimitry Andric   Preprocessor &PP = getCompilerInstance().getPreprocessor();
9780b57cec5SDimitry Andric   SourceManager &SM = PP.getSourceManager();
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric   // Start lexing the specified input file.
981e8d8bef9SDimitry Andric   llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
9820b57cec5SDimitry Andric   Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
9830b57cec5SDimitry Andric   RawLex.SetKeepWhitespaceMode(true);
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   Token RawTok;
9860b57cec5SDimitry Andric   RawLex.LexFromRawLexer(RawTok);
9870b57cec5SDimitry Andric   while (RawTok.isNot(tok::eof)) {
9880b57cec5SDimitry Andric     PP.DumpToken(RawTok, true);
9890b57cec5SDimitry Andric     llvm::errs() << "\n";
9900b57cec5SDimitry Andric     RawLex.LexFromRawLexer(RawTok);
9910b57cec5SDimitry Andric   }
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric void DumpTokensAction::ExecuteAction() {
9950b57cec5SDimitry Andric   Preprocessor &PP = getCompilerInstance().getPreprocessor();
9960b57cec5SDimitry Andric   // Start preprocessing the specified input file.
9970b57cec5SDimitry Andric   Token Tok;
9980b57cec5SDimitry Andric   PP.EnterMainSourceFile();
9990b57cec5SDimitry Andric   do {
10000b57cec5SDimitry Andric     PP.Lex(Tok);
10010b57cec5SDimitry Andric     PP.DumpToken(Tok, true);
10020b57cec5SDimitry Andric     llvm::errs() << "\n";
10030b57cec5SDimitry Andric   } while (Tok.isNot(tok::eof));
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric void PreprocessOnlyAction::ExecuteAction() {
10070b57cec5SDimitry Andric   Preprocessor &PP = getCompilerInstance().getPreprocessor();
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // Ignore unknown pragmas.
10100b57cec5SDimitry Andric   PP.IgnorePragmas();
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   Token Tok;
10130b57cec5SDimitry Andric   // Start parsing the specified input file.
10140b57cec5SDimitry Andric   PP.EnterMainSourceFile();
10150b57cec5SDimitry Andric   do {
10160b57cec5SDimitry Andric     PP.Lex(Tok);
10170b57cec5SDimitry Andric   } while (Tok.isNot(tok::eof));
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric void PrintPreprocessedAction::ExecuteAction() {
10210b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
10220b57cec5SDimitry Andric   // Output file may need to be set to 'Binary', to avoid converting Unix style
1023fe6060f1SDimitry Andric   // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>) on Windows.
10240b57cec5SDimitry Andric   //
10250b57cec5SDimitry Andric   // Look to see what type of line endings the file uses. If there's a
10260b57cec5SDimitry Andric   // CRLF, then we won't open the file up in binary mode. If there is
10270b57cec5SDimitry Andric   // just an LF or CR, then we will open the file up in binary mode.
10280b57cec5SDimitry Andric   // In this fashion, the output format should match the input format, unless
10290b57cec5SDimitry Andric   // the input format has inconsistent line endings.
10300b57cec5SDimitry Andric   //
10310b57cec5SDimitry Andric   // This should be a relatively fast operation since most files won't have
10320b57cec5SDimitry Andric   // all of their source code on a single line. However, that is still a
10330b57cec5SDimitry Andric   // concern, so if we scan for too long, we'll just assume the file should
10340b57cec5SDimitry Andric   // be opened in binary mode.
1035fe6060f1SDimitry Andric 
1036fe6060f1SDimitry Andric   bool BinaryMode = false;
1037fe6060f1SDimitry Andric   if (llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows()) {
1038fe6060f1SDimitry Andric     BinaryMode = true;
10390b57cec5SDimitry Andric     const SourceManager &SM = CI.getSourceManager();
1040bdd1243dSDimitry Andric     if (std::optional<llvm::MemoryBufferRef> Buffer =
1041e8d8bef9SDimitry Andric             SM.getBufferOrNone(SM.getMainFileID())) {
10420b57cec5SDimitry Andric       const char *cur = Buffer->getBufferStart();
10430b57cec5SDimitry Andric       const char *end = Buffer->getBufferEnd();
10440b57cec5SDimitry Andric       const char *next = (cur != end) ? cur + 1 : end;
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric       // Limit ourselves to only scanning 256 characters into the source
10475e801ac6SDimitry Andric       // file.  This is mostly a check in case the file has no
10480b57cec5SDimitry Andric       // newlines whatsoever.
1049fe6060f1SDimitry Andric       if (end - cur > 256)
1050fe6060f1SDimitry Andric         end = cur + 256;
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric       while (next < end) {
10530b57cec5SDimitry Andric         if (*cur == 0x0D) {  // CR
10540b57cec5SDimitry Andric           if (*next == 0x0A) // CRLF
10550b57cec5SDimitry Andric             BinaryMode = false;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric           break;
10580b57cec5SDimitry Andric         } else if (*cur == 0x0A) // LF
10590b57cec5SDimitry Andric           break;
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric         ++cur;
10620b57cec5SDimitry Andric         ++next;
10630b57cec5SDimitry Andric       }
10640b57cec5SDimitry Andric     }
1065fe6060f1SDimitry Andric   }
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric   std::unique_ptr<raw_ostream> OS =
10680b57cec5SDimitry Andric       CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName());
10690b57cec5SDimitry Andric   if (!OS) return;
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   // If we're preprocessing a module map, start by dumping the contents of the
10720b57cec5SDimitry Andric   // module itself before switching to the input buffer.
10730b57cec5SDimitry Andric   auto &Input = getCurrentInput();
10740b57cec5SDimitry Andric   if (Input.getKind().getFormat() == InputKind::ModuleMap) {
10750b57cec5SDimitry Andric     if (Input.isFile()) {
10760b57cec5SDimitry Andric       (*OS) << "# 1 \"";
10770b57cec5SDimitry Andric       OS->write_escaped(Input.getFile());
10780b57cec5SDimitry Andric       (*OS) << "\"\n";
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric     getCurrentModule()->print(*OS);
10810b57cec5SDimitry Andric     (*OS) << "#pragma clang module contents\n";
10820b57cec5SDimitry Andric   }
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(),
10850b57cec5SDimitry Andric                            CI.getPreprocessorOutputOpts());
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric void PrintPreambleAction::ExecuteAction() {
10890b57cec5SDimitry Andric   switch (getCurrentFileKind().getLanguage()) {
1090a7dea167SDimitry Andric   case Language::C:
1091a7dea167SDimitry Andric   case Language::CXX:
1092a7dea167SDimitry Andric   case Language::ObjC:
1093a7dea167SDimitry Andric   case Language::ObjCXX:
1094a7dea167SDimitry Andric   case Language::OpenCL:
1095fe6060f1SDimitry Andric   case Language::OpenCLCXX:
1096a7dea167SDimitry Andric   case Language::CUDA:
1097a7dea167SDimitry Andric   case Language::HIP:
109881ad6265SDimitry Andric   case Language::HLSL:
1099*0fca6ea1SDimitry Andric   case Language::CIR:
11000b57cec5SDimitry Andric     break;
11010b57cec5SDimitry Andric 
1102a7dea167SDimitry Andric   case Language::Unknown:
1103a7dea167SDimitry Andric   case Language::Asm:
1104a7dea167SDimitry Andric   case Language::LLVM_IR:
1105a7dea167SDimitry Andric   case Language::RenderScript:
11060b57cec5SDimitry Andric     // We can't do anything with these.
11070b57cec5SDimitry Andric     return;
11080b57cec5SDimitry Andric   }
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   // We don't expect to find any #include directives in a preprocessed input.
11110b57cec5SDimitry Andric   if (getCurrentFileKind().isPreprocessed())
11120b57cec5SDimitry Andric     return;
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
11150b57cec5SDimitry Andric   auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
11160b57cec5SDimitry Andric   if (Buffer) {
11170b57cec5SDimitry Andric     unsigned Preamble =
11180b57cec5SDimitry Andric         Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;
11190b57cec5SDimitry Andric     llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
11200b57cec5SDimitry Andric   }
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric void DumpCompilerOptionsAction::ExecuteAction() {
11240b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
11250b57cec5SDimitry Andric   std::unique_ptr<raw_ostream> OSP =
11260b57cec5SDimitry Andric       CI.createDefaultOutputFile(false, getCurrentFile());
11270b57cec5SDimitry Andric   if (!OSP)
11280b57cec5SDimitry Andric     return;
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric   raw_ostream &OS = *OSP;
11310b57cec5SDimitry Andric   const Preprocessor &PP = CI.getPreprocessor();
11320b57cec5SDimitry Andric   const LangOptions &LangOpts = PP.getLangOpts();
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   // FIXME: Rather than manually format the JSON (which is awkward due to
11350b57cec5SDimitry Andric   // needing to remove trailing commas), this should make use of a JSON library.
11360b57cec5SDimitry Andric   // FIXME: Instead of printing enums as an integral value and specifying the
11370b57cec5SDimitry Andric   // type as a separate field, use introspection to print the enumerator.
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric   OS << "{\n";
11400b57cec5SDimitry Andric   OS << "\n\"features\" : [\n";
11410b57cec5SDimitry Andric   {
11420b57cec5SDimitry Andric     llvm::SmallString<128> Str;
11430b57cec5SDimitry Andric #define FEATURE(Name, Predicate)                                               \
11440b57cec5SDimitry Andric   ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
11450b57cec5SDimitry Andric       .toVector(Str);
11460b57cec5SDimitry Andric #include "clang/Basic/Features.def"
11470b57cec5SDimitry Andric #undef FEATURE
11480b57cec5SDimitry Andric     // Remove the newline and comma from the last entry to ensure this remains
11490b57cec5SDimitry Andric     // valid JSON.
11500b57cec5SDimitry Andric     OS << Str.substr(0, Str.size() - 2);
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric   OS << "\n],\n";
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   OS << "\n\"extensions\" : [\n";
11550b57cec5SDimitry Andric   {
11560b57cec5SDimitry Andric     llvm::SmallString<128> Str;
11570b57cec5SDimitry Andric #define EXTENSION(Name, Predicate)                                             \
11580b57cec5SDimitry Andric   ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
11590b57cec5SDimitry Andric       .toVector(Str);
11600b57cec5SDimitry Andric #include "clang/Basic/Features.def"
11610b57cec5SDimitry Andric #undef EXTENSION
11620b57cec5SDimitry Andric     // Remove the newline and comma from the last entry to ensure this remains
11630b57cec5SDimitry Andric     // valid JSON.
11640b57cec5SDimitry Andric     OS << Str.substr(0, Str.size() - 2);
11650b57cec5SDimitry Andric   }
11660b57cec5SDimitry Andric   OS << "\n]\n";
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric   OS << "}";
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {
11720b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
11730b57cec5SDimitry Andric   SourceManager &SM = CI.getPreprocessor().getSourceManager();
1174e8d8bef9SDimitry Andric   llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());
11750b57cec5SDimitry Andric 
117681ad6265SDimitry Andric   llvm::SmallVector<dependency_directives_scan::Token, 16> Tokens;
117781ad6265SDimitry Andric   llvm::SmallVector<dependency_directives_scan::Directive, 32> Directives;
117881ad6265SDimitry Andric   if (scanSourceForDependencyDirectives(
117981ad6265SDimitry Andric           FromFile.getBuffer(), Tokens, Directives, &CI.getDiagnostics(),
11800b57cec5SDimitry Andric           SM.getLocForStartOfFile(SM.getMainFileID()))) {
11810b57cec5SDimitry Andric     assert(CI.getDiagnostics().hasErrorOccurred() &&
11820b57cec5SDimitry Andric            "no errors reported for failure");
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric     // Preprocess the source when verifying the diagnostics to capture the
11850b57cec5SDimitry Andric     // 'expected' comments.
11860b57cec5SDimitry Andric     if (CI.getDiagnosticOpts().VerifyDiagnostics) {
11870b57cec5SDimitry Andric       // Make sure we don't emit new diagnostics!
1188a7dea167SDimitry Andric       CI.getDiagnostics().setSuppressAllDiagnostics(true);
11890b57cec5SDimitry Andric       Preprocessor &PP = getCompilerInstance().getPreprocessor();
11900b57cec5SDimitry Andric       PP.EnterMainSourceFile();
11910b57cec5SDimitry Andric       Token Tok;
11920b57cec5SDimitry Andric       do {
11930b57cec5SDimitry Andric         PP.Lex(Tok);
11940b57cec5SDimitry Andric       } while (Tok.isNot(tok::eof));
11950b57cec5SDimitry Andric     }
11960b57cec5SDimitry Andric     return;
11970b57cec5SDimitry Andric   }
119881ad6265SDimitry Andric   printDependencyDirectivesAsSource(FromFile.getBuffer(), Directives,
119981ad6265SDimitry Andric                                     llvm::outs());
12000b57cec5SDimitry Andric }
1201349cc55cSDimitry Andric 
1202349cc55cSDimitry Andric void GetDependenciesByModuleNameAction::ExecuteAction() {
1203349cc55cSDimitry Andric   CompilerInstance &CI = getCompilerInstance();
1204349cc55cSDimitry Andric   Preprocessor &PP = CI.getPreprocessor();
1205349cc55cSDimitry Andric   SourceManager &SM = PP.getSourceManager();
1206349cc55cSDimitry Andric   FileID MainFileID = SM.getMainFileID();
1207349cc55cSDimitry Andric   SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);
1208349cc55cSDimitry Andric   SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
1209349cc55cSDimitry Andric   IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);
1210349cc55cSDimitry Andric   Path.push_back(std::make_pair(ModuleID, FileStart));
1211349cc55cSDimitry Andric   auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);
1212349cc55cSDimitry Andric   PPCallbacks *CB = PP.getPPCallbacks();
1213349cc55cSDimitry Andric   CB->moduleImport(SourceLocation(), Path, ModResult);
1214349cc55cSDimitry Andric }
1215