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