Path: blob/main/contrib/llvm-project/clang/lib/Frontend/FrontendActions.cpp
35232 views
//===--- FrontendActions.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Frontend/FrontendActions.h"9#include "clang/AST/ASTConsumer.h"10#include "clang/AST/Decl.h"11#include "clang/Basic/FileManager.h"12#include "clang/Basic/LangStandard.h"13#include "clang/Basic/Module.h"14#include "clang/Basic/TargetInfo.h"15#include "clang/Frontend/ASTConsumers.h"16#include "clang/Frontend/CompilerInstance.h"17#include "clang/Frontend/FrontendDiagnostic.h"18#include "clang/Frontend/MultiplexConsumer.h"19#include "clang/Frontend/Utils.h"20#include "clang/Lex/DependencyDirectivesScanner.h"21#include "clang/Lex/HeaderSearch.h"22#include "clang/Lex/Preprocessor.h"23#include "clang/Lex/PreprocessorOptions.h"24#include "clang/Sema/TemplateInstCallback.h"25#include "clang/Serialization/ASTReader.h"26#include "clang/Serialization/ASTWriter.h"27#include "clang/Serialization/ModuleFile.h"28#include "llvm/Support/ErrorHandling.h"29#include "llvm/Support/FileSystem.h"30#include "llvm/Support/MemoryBuffer.h"31#include "llvm/Support/Path.h"32#include "llvm/Support/YAMLTraits.h"33#include "llvm/Support/raw_ostream.h"34#include <memory>35#include <optional>36#include <system_error>3738using namespace clang;3940namespace {41CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {42return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()43: nullptr;44}4546void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {47if (Action.hasCodeCompletionSupport() &&48!CI.getFrontendOpts().CodeCompletionAt.FileName.empty())49CI.createCodeCompletionConsumer();5051if (!CI.hasSema())52CI.createSema(Action.getTranslationUnitKind(),53GetCodeCompletionConsumer(CI));54}55} // namespace5657//===----------------------------------------------------------------------===//58// Custom Actions59//===----------------------------------------------------------------------===//6061std::unique_ptr<ASTConsumer>62InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {63return std::make_unique<ASTConsumer>();64}6566void InitOnlyAction::ExecuteAction() {67}6869// Basically PreprocessOnlyAction::ExecuteAction.70void ReadPCHAndPreprocessAction::ExecuteAction() {71Preprocessor &PP = getCompilerInstance().getPreprocessor();7273// Ignore unknown pragmas.74PP.IgnorePragmas();7576Token Tok;77// Start parsing the specified input file.78PP.EnterMainSourceFile();79do {80PP.Lex(Tok);81} while (Tok.isNot(tok::eof));82}8384std::unique_ptr<ASTConsumer>85ReadPCHAndPreprocessAction::CreateASTConsumer(CompilerInstance &CI,86StringRef InFile) {87return std::make_unique<ASTConsumer>();88}8990//===----------------------------------------------------------------------===//91// AST Consumer Actions92//===----------------------------------------------------------------------===//9394std::unique_ptr<ASTConsumer>95ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {96if (std::unique_ptr<raw_ostream> OS =97CI.createDefaultOutputFile(false, InFile))98return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter);99return nullptr;100}101102std::unique_ptr<ASTConsumer>103ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {104const FrontendOptions &Opts = CI.getFrontendOpts();105return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter,106Opts.ASTDumpDecls, Opts.ASTDumpAll,107Opts.ASTDumpLookups, Opts.ASTDumpDeclTypes,108Opts.ASTDumpFormat);109}110111std::unique_ptr<ASTConsumer>112ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {113return CreateASTDeclNodeLister();114}115116std::unique_ptr<ASTConsumer>117ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {118return CreateASTViewer();119}120121std::unique_ptr<ASTConsumer>122GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {123std::string Sysroot;124if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))125return nullptr;126127std::string OutputFile;128std::unique_ptr<raw_pwrite_stream> OS =129CreateOutputFile(CI, InFile, /*ref*/ OutputFile);130if (!OS)131return nullptr;132133if (!CI.getFrontendOpts().RelocatablePCH)134Sysroot.clear();135136const auto &FrontendOpts = CI.getFrontendOpts();137auto Buffer = std::make_shared<PCHBuffer>();138std::vector<std::unique_ptr<ASTConsumer>> Consumers;139Consumers.push_back(std::make_unique<PCHGenerator>(140CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,141FrontendOpts.ModuleFileExtensions,142CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,143FrontendOpts.IncludeTimestamps, FrontendOpts.BuildingImplicitModule,144+CI.getLangOpts().CacheGeneratedPCH));145Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(146CI, std::string(InFile), OutputFile, std::move(OS), Buffer));147148return std::make_unique<MultiplexConsumer>(std::move(Consumers));149}150151bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,152std::string &Sysroot) {153Sysroot = CI.getHeaderSearchOpts().Sysroot;154if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {155CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);156return false;157}158159return true;160}161162std::unique_ptr<llvm::raw_pwrite_stream>163GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile,164std::string &OutputFile) {165// Because this is exposed via libclang we must disable RemoveFileOnSignal.166std::unique_ptr<raw_pwrite_stream> OS = CI.createDefaultOutputFile(167/*Binary=*/true, InFile, /*Extension=*/"", /*RemoveFileOnSignal=*/false);168if (!OS)169return nullptr;170171OutputFile = CI.getFrontendOpts().OutputFile;172return OS;173}174175bool GeneratePCHAction::shouldEraseOutputFiles() {176if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors)177return false;178return ASTFrontendAction::shouldEraseOutputFiles();179}180181bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {182CI.getLangOpts().CompilingPCH = true;183return true;184}185186std::vector<std::unique_ptr<ASTConsumer>>187GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,188StringRef InFile) {189std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);190if (!OS)191return {};192193std::string OutputFile = CI.getFrontendOpts().OutputFile;194std::string Sysroot;195196auto Buffer = std::make_shared<PCHBuffer>();197std::vector<std::unique_ptr<ASTConsumer>> Consumers;198199Consumers.push_back(std::make_unique<PCHGenerator>(200CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,201CI.getFrontendOpts().ModuleFileExtensions,202/*AllowASTWithErrors=*/203+CI.getFrontendOpts().AllowPCMWithCompilerErrors,204/*IncludeTimestamps=*/205+CI.getFrontendOpts().BuildingImplicitModule &&206+CI.getFrontendOpts().IncludeTimestamps,207/*BuildingImplicitModule=*/+CI.getFrontendOpts().BuildingImplicitModule,208/*ShouldCacheASTInMemory=*/209+CI.getFrontendOpts().BuildingImplicitModule));210Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(211CI, std::string(InFile), OutputFile, std::move(OS), Buffer));212return Consumers;213}214215std::unique_ptr<ASTConsumer>216GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,217StringRef InFile) {218std::vector<std::unique_ptr<ASTConsumer>> Consumers =219CreateMultiplexConsumer(CI, InFile);220if (Consumers.empty())221return nullptr;222223return std::make_unique<MultiplexConsumer>(std::move(Consumers));224}225226bool GenerateModuleAction::shouldEraseOutputFiles() {227return !getCompilerInstance().getFrontendOpts().AllowPCMWithCompilerErrors &&228ASTFrontendAction::shouldEraseOutputFiles();229}230231bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(232CompilerInstance &CI) {233if (!CI.getLangOpts().Modules) {234CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules);235return false;236}237238return GenerateModuleAction::BeginSourceFileAction(CI);239}240241std::unique_ptr<raw_pwrite_stream>242GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,243StringRef InFile) {244// If no output file was provided, figure out where this module would go245// in the module cache.246if (CI.getFrontendOpts().OutputFile.empty()) {247StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;248if (ModuleMapFile.empty())249ModuleMapFile = InFile;250251HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();252CI.getFrontendOpts().OutputFile =253HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule,254ModuleMapFile);255}256257// Because this is exposed via libclang we must disable RemoveFileOnSignal.258return CI.createDefaultOutputFile(/*Binary=*/true, InFile, /*Extension=*/"",259/*RemoveFileOnSignal=*/false,260/*CreateMissingDirectories=*/true,261/*ForceUseTemporary=*/true);262}263264bool GenerateModuleInterfaceAction::BeginSourceFileAction(265CompilerInstance &CI) {266CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);267268return GenerateModuleAction::BeginSourceFileAction(CI);269}270271std::unique_ptr<ASTConsumer>272GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,273StringRef InFile) {274std::vector<std::unique_ptr<ASTConsumer>> Consumers;275276if (CI.getFrontendOpts().GenReducedBMI &&277!CI.getFrontendOpts().ModuleOutputPath.empty()) {278Consumers.push_back(std::make_unique<ReducedBMIGenerator>(279CI.getPreprocessor(), CI.getModuleCache(),280CI.getFrontendOpts().ModuleOutputPath));281}282283Consumers.push_back(std::make_unique<CXX20ModulesGenerator>(284CI.getPreprocessor(), CI.getModuleCache(),285CI.getFrontendOpts().OutputFile));286287return std::make_unique<MultiplexConsumer>(std::move(Consumers));288}289290std::unique_ptr<raw_pwrite_stream>291GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,292StringRef InFile) {293return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");294}295296std::unique_ptr<ASTConsumer>297GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,298StringRef InFile) {299return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(),300CI.getModuleCache(),301CI.getFrontendOpts().OutputFile);302}303304bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {305if (!CI.getLangOpts().CPlusPlusModules) {306CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);307return false;308}309CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderUnit);310return GenerateModuleAction::BeginSourceFileAction(CI);311}312313std::unique_ptr<raw_pwrite_stream>314GenerateHeaderUnitAction::CreateOutputFile(CompilerInstance &CI,315StringRef InFile) {316return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");317}318319SyntaxOnlyAction::~SyntaxOnlyAction() {320}321322std::unique_ptr<ASTConsumer>323SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {324return std::make_unique<ASTConsumer>();325}326327std::unique_ptr<ASTConsumer>328DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,329StringRef InFile) {330return std::make_unique<ASTConsumer>();331}332333std::unique_ptr<ASTConsumer>334VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {335return std::make_unique<ASTConsumer>();336}337338void VerifyPCHAction::ExecuteAction() {339CompilerInstance &CI = getCompilerInstance();340bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;341const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;342std::unique_ptr<ASTReader> Reader(new ASTReader(343CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),344CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,345Sysroot.empty() ? "" : Sysroot.c_str(),346DisableValidationForModuleKind::None,347/*AllowASTWithCompilerErrors*/ false,348/*AllowConfigurationMismatch*/ true,349/*ValidateSystemInputs*/ true));350351Reader->ReadAST(getCurrentFile(),352Preamble ? serialization::MK_Preamble353: serialization::MK_PCH,354SourceLocation(),355ASTReader::ARR_ConfigurationMismatch);356}357358namespace {359struct TemplightEntry {360std::string Name;361std::string Kind;362std::string Event;363std::string DefinitionLocation;364std::string PointOfInstantiation;365};366} // namespace367368namespace llvm {369namespace yaml {370template <> struct MappingTraits<TemplightEntry> {371static void mapping(IO &io, TemplightEntry &fields) {372io.mapRequired("name", fields.Name);373io.mapRequired("kind", fields.Kind);374io.mapRequired("event", fields.Event);375io.mapRequired("orig", fields.DefinitionLocation);376io.mapRequired("poi", fields.PointOfInstantiation);377}378};379} // namespace yaml380} // namespace llvm381382namespace {383class DefaultTemplateInstCallback : public TemplateInstantiationCallback {384using CodeSynthesisContext = Sema::CodeSynthesisContext;385386public:387void initialize(const Sema &) override {}388389void finalize(const Sema &) override {}390391void atTemplateBegin(const Sema &TheSema,392const CodeSynthesisContext &Inst) override {393displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);394}395396void atTemplateEnd(const Sema &TheSema,397const CodeSynthesisContext &Inst) override {398displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);399}400401private:402static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {403switch (Kind) {404case CodeSynthesisContext::TemplateInstantiation:405return "TemplateInstantiation";406case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:407return "DefaultTemplateArgumentInstantiation";408case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:409return "DefaultFunctionArgumentInstantiation";410case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:411return "ExplicitTemplateArgumentSubstitution";412case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:413return "DeducedTemplateArgumentSubstitution";414case CodeSynthesisContext::LambdaExpressionSubstitution:415return "LambdaExpressionSubstitution";416case CodeSynthesisContext::PriorTemplateArgumentSubstitution:417return "PriorTemplateArgumentSubstitution";418case CodeSynthesisContext::DefaultTemplateArgumentChecking:419return "DefaultTemplateArgumentChecking";420case CodeSynthesisContext::ExceptionSpecEvaluation:421return "ExceptionSpecEvaluation";422case CodeSynthesisContext::ExceptionSpecInstantiation:423return "ExceptionSpecInstantiation";424case CodeSynthesisContext::DeclaringSpecialMember:425return "DeclaringSpecialMember";426case CodeSynthesisContext::DeclaringImplicitEqualityComparison:427return "DeclaringImplicitEqualityComparison";428case CodeSynthesisContext::DefiningSynthesizedFunction:429return "DefiningSynthesizedFunction";430case CodeSynthesisContext::RewritingOperatorAsSpaceship:431return "RewritingOperatorAsSpaceship";432case CodeSynthesisContext::Memoization:433return "Memoization";434case CodeSynthesisContext::ConstraintsCheck:435return "ConstraintsCheck";436case CodeSynthesisContext::ConstraintSubstitution:437return "ConstraintSubstitution";438case CodeSynthesisContext::ConstraintNormalization:439return "ConstraintNormalization";440case CodeSynthesisContext::RequirementParameterInstantiation:441return "RequirementParameterInstantiation";442case CodeSynthesisContext::ParameterMappingSubstitution:443return "ParameterMappingSubstitution";444case CodeSynthesisContext::RequirementInstantiation:445return "RequirementInstantiation";446case CodeSynthesisContext::NestedRequirementConstraintsCheck:447return "NestedRequirementConstraintsCheck";448case CodeSynthesisContext::InitializingStructuredBinding:449return "InitializingStructuredBinding";450case CodeSynthesisContext::MarkingClassDllexported:451return "MarkingClassDllexported";452case CodeSynthesisContext::BuildingBuiltinDumpStructCall:453return "BuildingBuiltinDumpStructCall";454case CodeSynthesisContext::BuildingDeductionGuides:455return "BuildingDeductionGuides";456case CodeSynthesisContext::TypeAliasTemplateInstantiation:457return "TypeAliasTemplateInstantiation";458}459return "";460}461462template <bool BeginInstantiation>463static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,464const CodeSynthesisContext &Inst) {465std::string YAML;466{467llvm::raw_string_ostream OS(YAML);468llvm::yaml::Output YO(OS);469TemplightEntry Entry =470getTemplightEntry<BeginInstantiation>(TheSema, Inst);471llvm::yaml::EmptyContext Context;472llvm::yaml::yamlize(YO, Entry, true, Context);473}474Out << "---" << YAML << "\n";475}476477static void printEntryName(const Sema &TheSema, const Decl *Entity,478llvm::raw_string_ostream &OS) {479auto *NamedTemplate = cast<NamedDecl>(Entity);480481PrintingPolicy Policy = TheSema.Context.getPrintingPolicy();482// FIXME: Also ask for FullyQualifiedNames?483Policy.SuppressDefaultTemplateArgs = false;484NamedTemplate->getNameForDiagnostic(OS, Policy, true);485486if (!OS.str().empty())487return;488489Decl *Ctx = Decl::castFromDeclContext(NamedTemplate->getDeclContext());490NamedDecl *NamedCtx = dyn_cast_or_null<NamedDecl>(Ctx);491492if (const auto *Decl = dyn_cast<TagDecl>(NamedTemplate)) {493if (const auto *R = dyn_cast<RecordDecl>(Decl)) {494if (R->isLambda()) {495OS << "lambda at ";496Decl->getLocation().print(OS, TheSema.getSourceManager());497return;498}499}500OS << "unnamed " << Decl->getKindName();501return;502}503504assert(NamedCtx && "NamedCtx cannot be null");505506if (const auto *Decl = dyn_cast<ParmVarDecl>(NamedTemplate)) {507OS << "unnamed function parameter " << Decl->getFunctionScopeIndex()508<< " ";509if (Decl->getFunctionScopeDepth() > 0)510OS << "(at depth " << Decl->getFunctionScopeDepth() << ") ";511OS << "of ";512NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);513return;514}515516if (const auto *Decl = dyn_cast<TemplateTypeParmDecl>(NamedTemplate)) {517if (const Type *Ty = Decl->getTypeForDecl()) {518if (const auto *TTPT = dyn_cast_or_null<TemplateTypeParmType>(Ty)) {519OS << "unnamed template type parameter " << TTPT->getIndex() << " ";520if (TTPT->getDepth() > 0)521OS << "(at depth " << TTPT->getDepth() << ") ";522OS << "of ";523NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);524return;525}526}527}528529if (const auto *Decl = dyn_cast<NonTypeTemplateParmDecl>(NamedTemplate)) {530OS << "unnamed template non-type parameter " << Decl->getIndex() << " ";531if (Decl->getDepth() > 0)532OS << "(at depth " << Decl->getDepth() << ") ";533OS << "of ";534NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);535return;536}537538if (const auto *Decl = dyn_cast<TemplateTemplateParmDecl>(NamedTemplate)) {539OS << "unnamed template template parameter " << Decl->getIndex() << " ";540if (Decl->getDepth() > 0)541OS << "(at depth " << Decl->getDepth() << ") ";542OS << "of ";543NamedCtx->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);544return;545}546547llvm_unreachable("Failed to retrieve a name for this entry!");548OS << "unnamed identifier";549}550551template <bool BeginInstantiation>552static TemplightEntry getTemplightEntry(const Sema &TheSema,553const CodeSynthesisContext &Inst) {554TemplightEntry Entry;555Entry.Kind = toString(Inst.Kind);556Entry.Event = BeginInstantiation ? "Begin" : "End";557llvm::raw_string_ostream OS(Entry.Name);558printEntryName(TheSema, Inst.Entity, OS);559const PresumedLoc DefLoc =560TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());561if (!DefLoc.isInvalid())562Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +563std::to_string(DefLoc.getLine()) + ":" +564std::to_string(DefLoc.getColumn());565const PresumedLoc PoiLoc =566TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);567if (!PoiLoc.isInvalid()) {568Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +569std::to_string(PoiLoc.getLine()) + ":" +570std::to_string(PoiLoc.getColumn());571}572return Entry;573}574};575} // namespace576577std::unique_ptr<ASTConsumer>578TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {579return std::make_unique<ASTConsumer>();580}581582void TemplightDumpAction::ExecuteAction() {583CompilerInstance &CI = getCompilerInstance();584585// This part is normally done by ASTFrontEndAction, but needs to happen586// before Templight observers can be created587// FIXME: Move the truncation aspect of this into Sema, we delayed this till588// here so the source manager would be initialized.589EnsureSemaIsCreated(CI, *this);590591CI.getSema().TemplateInstCallbacks.push_back(592std::make_unique<DefaultTemplateInstCallback>());593ASTFrontendAction::ExecuteAction();594}595596namespace {597/// AST reader listener that dumps module information for a module598/// file.599class DumpModuleInfoListener : public ASTReaderListener {600llvm::raw_ostream &Out;601602public:603DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }604605#define DUMP_BOOLEAN(Value, Text) \606Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"607608bool ReadFullVersionInformation(StringRef FullVersion) override {609Out.indent(2)610<< "Generated by "611<< (FullVersion == getClangFullRepositoryVersion()? "this"612: "a different")613<< " Clang: " << FullVersion << "\n";614return ASTReaderListener::ReadFullVersionInformation(FullVersion);615}616617void ReadModuleName(StringRef ModuleName) override {618Out.indent(2) << "Module name: " << ModuleName << "\n";619}620void ReadModuleMapFile(StringRef ModuleMapPath) override {621Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";622}623624bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,625bool AllowCompatibleDifferences) override {626Out.indent(2) << "Language options:\n";627#define LANGOPT(Name, Bits, Default, Description) \628DUMP_BOOLEAN(LangOpts.Name, Description);629#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \630Out.indent(4) << Description << ": " \631<< static_cast<unsigned>(LangOpts.get##Name()) << "\n";632#define VALUE_LANGOPT(Name, Bits, Default, Description) \633Out.indent(4) << Description << ": " << LangOpts.Name << "\n";634#define BENIGN_LANGOPT(Name, Bits, Default, Description)635#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)636#include "clang/Basic/LangOptions.def"637638if (!LangOpts.ModuleFeatures.empty()) {639Out.indent(4) << "Module features:\n";640for (StringRef Feature : LangOpts.ModuleFeatures)641Out.indent(6) << Feature << "\n";642}643644return false;645}646647bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,648bool AllowCompatibleDifferences) override {649Out.indent(2) << "Target options:\n";650Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";651Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";652Out.indent(4) << " TuneCPU: " << TargetOpts.TuneCPU << "\n";653Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n";654655if (!TargetOpts.FeaturesAsWritten.empty()) {656Out.indent(4) << "Target features:\n";657for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();658I != N; ++I) {659Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";660}661}662663return false;664}665666bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,667bool Complain) override {668Out.indent(2) << "Diagnostic options:\n";669#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);670#define ENUM_DIAGOPT(Name, Type, Bits, Default) \671Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n";672#define VALUE_DIAGOPT(Name, Bits, Default) \673Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";674#include "clang/Basic/DiagnosticOptions.def"675676Out.indent(4) << "Diagnostic flags:\n";677for (const std::string &Warning : DiagOpts->Warnings)678Out.indent(6) << "-W" << Warning << "\n";679for (const std::string &Remark : DiagOpts->Remarks)680Out.indent(6) << "-R" << Remark << "\n";681682return false;683}684685bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,686StringRef SpecificModuleCachePath,687bool Complain) override {688Out.indent(2) << "Header search options:\n";689Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";690Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n";691Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";692DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,693"Use builtin include directories [-nobuiltininc]");694DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,695"Use standard system include directories [-nostdinc]");696DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,697"Use standard C++ include directories [-nostdinc++]");698DUMP_BOOLEAN(HSOpts.UseLibcxx,699"Use libc++ (rather than libstdc++) [-stdlib=]");700return false;701}702703bool ReadHeaderSearchPaths(const HeaderSearchOptions &HSOpts,704bool Complain) override {705Out.indent(2) << "Header search paths:\n";706Out.indent(4) << "User entries:\n";707for (const auto &Entry : HSOpts.UserEntries)708Out.indent(6) << Entry.Path << "\n";709Out.indent(4) << "System header prefixes:\n";710for (const auto &Prefix : HSOpts.SystemHeaderPrefixes)711Out.indent(6) << Prefix.Prefix << "\n";712Out.indent(4) << "VFS overlay files:\n";713for (const auto &Overlay : HSOpts.VFSOverlayFiles)714Out.indent(6) << Overlay << "\n";715return false;716}717718bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,719bool ReadMacros, bool Complain,720std::string &SuggestedPredefines) override {721Out.indent(2) << "Preprocessor options:\n";722DUMP_BOOLEAN(PPOpts.UsePredefines,723"Uses compiler/target-specific predefines [-undef]");724DUMP_BOOLEAN(PPOpts.DetailedRecord,725"Uses detailed preprocessing record (for indexing)");726727if (ReadMacros) {728Out.indent(4) << "Predefined macros:\n";729}730731for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator732I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();733I != IEnd; ++I) {734Out.indent(6);735if (I->second)736Out << "-U";737else738Out << "-D";739Out << I->first << "\n";740}741return false;742}743744/// Indicates that a particular module file extension has been read.745void readModuleFileExtension(746const ModuleFileExtensionMetadata &Metadata) override {747Out.indent(2) << "Module file extension '"748<< Metadata.BlockName << "' " << Metadata.MajorVersion749<< "." << Metadata.MinorVersion;750if (!Metadata.UserInfo.empty()) {751Out << ": ";752Out.write_escaped(Metadata.UserInfo);753}754755Out << "\n";756}757758/// Tells the \c ASTReaderListener that we want to receive the759/// input files of the AST file via \c visitInputFile.760bool needsInputFileVisitation() override { return true; }761762/// Tells the \c ASTReaderListener that we want to receive the763/// input files of the AST file via \c visitInputFile.764bool needsSystemInputFileVisitation() override { return true; }765766/// Indicates that the AST file contains particular input file.767///768/// \returns true to continue receiving the next input file, false to stop.769bool visitInputFile(StringRef Filename, bool isSystem,770bool isOverridden, bool isExplicitModule) override {771772Out.indent(2) << "Input file: " << Filename;773774if (isSystem || isOverridden || isExplicitModule) {775Out << " [";776if (isSystem) {777Out << "System";778if (isOverridden || isExplicitModule)779Out << ", ";780}781if (isOverridden) {782Out << "Overridden";783if (isExplicitModule)784Out << ", ";785}786if (isExplicitModule)787Out << "ExplicitModule";788789Out << "]";790}791792Out << "\n";793794return true;795}796797/// Returns true if this \c ASTReaderListener wants to receive the798/// imports of the AST file via \c visitImport, false otherwise.799bool needsImportVisitation() const override { return true; }800801/// If needsImportVisitation returns \c true, this is called for each802/// AST file imported by this AST file.803void visitImport(StringRef ModuleName, StringRef Filename) override {804Out.indent(2) << "Imports module '" << ModuleName805<< "': " << Filename.str() << "\n";806}807#undef DUMP_BOOLEAN808};809}810811bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {812// The Object file reader also supports raw ast files and there is no point in813// being strict about the module file format in -module-file-info mode.814CI.getHeaderSearchOpts().ModuleFormat = "obj";815return true;816}817818static StringRef ModuleKindName(Module::ModuleKind MK) {819switch (MK) {820case Module::ModuleMapModule:821return "Module Map Module";822case Module::ModuleInterfaceUnit:823return "Interface Unit";824case Module::ModuleImplementationUnit:825return "Implementation Unit";826case Module::ModulePartitionInterface:827return "Partition Interface";828case Module::ModulePartitionImplementation:829return "Partition Implementation";830case Module::ModuleHeaderUnit:831return "Header Unit";832case Module::ExplicitGlobalModuleFragment:833return "Global Module Fragment";834case Module::ImplicitGlobalModuleFragment:835return "Implicit Module Fragment";836case Module::PrivateModuleFragment:837return "Private Module Fragment";838}839llvm_unreachable("unknown module kind!");840}841842void DumpModuleInfoAction::ExecuteAction() {843CompilerInstance &CI = getCompilerInstance();844845// Don't process files of type other than module to avoid crash846if (!isCurrentFileAST()) {847CI.getDiagnostics().Report(diag::err_file_is_not_module)848<< getCurrentFile();849return;850}851852// Set up the output file.853StringRef OutputFileName = CI.getFrontendOpts().OutputFile;854if (!OutputFileName.empty() && OutputFileName != "-") {855std::error_code EC;856OutputStream.reset(new llvm::raw_fd_ostream(857OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF));858}859llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs();860861Out << "Information for module file '" << getCurrentFile() << "':\n";862auto &FileMgr = CI.getFileManager();863auto Buffer = FileMgr.getBufferForFile(getCurrentFile());864StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();865bool IsRaw = Magic.starts_with("CPCH");866Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n";867868Preprocessor &PP = CI.getPreprocessor();869DumpModuleInfoListener Listener(Out);870HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();871872// The FrontendAction::BeginSourceFile () method loads the AST so that much873// of the information is already available and modules should have been874// loaded.875876const LangOptions &LO = getCurrentASTUnit().getLangOpts();877if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {878ASTReader *R = getCurrentASTUnit().getASTReader().get();879unsigned SubModuleCount = R->getTotalNumSubmodules();880serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();881Out << " ====== C++20 Module structure ======\n";882883if (MF.ModuleName != LO.CurrentModule)884Out << " Mismatched module names : " << MF.ModuleName << " and "885<< LO.CurrentModule << "\n";886887struct SubModInfo {888unsigned Idx;889Module *Mod;890Module::ModuleKind Kind;891std::string &Name;892bool Seen;893};894std::map<std::string, SubModInfo> SubModMap;895auto PrintSubMapEntry = [&](std::string Name, Module::ModuleKind Kind) {896Out << " " << ModuleKindName(Kind) << " '" << Name << "'";897auto I = SubModMap.find(Name);898if (I == SubModMap.end())899Out << " was not found in the sub modules!\n";900else {901I->second.Seen = true;902Out << " is at index #" << I->second.Idx << "\n";903}904};905Module *Primary = nullptr;906for (unsigned Idx = 0; Idx <= SubModuleCount; ++Idx) {907Module *M = R->getModule(Idx);908if (!M)909continue;910if (M->Name == LO.CurrentModule) {911Primary = M;912Out << " " << ModuleKindName(M->Kind) << " '" << LO.CurrentModule913<< "' is the Primary Module at index #" << Idx << "\n";914SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, true}});915} else916SubModMap.insert({M->Name, {Idx, M, M->Kind, M->Name, false}});917}918if (Primary) {919if (!Primary->submodules().empty())920Out << " Sub Modules:\n";921for (auto *MI : Primary->submodules()) {922PrintSubMapEntry(MI->Name, MI->Kind);923}924if (!Primary->Imports.empty())925Out << " Imports:\n";926for (auto *IMP : Primary->Imports) {927PrintSubMapEntry(IMP->Name, IMP->Kind);928}929if (!Primary->Exports.empty())930Out << " Exports:\n";931for (unsigned MN = 0, N = Primary->Exports.size(); MN != N; ++MN) {932if (Module *M = Primary->Exports[MN].getPointer()) {933PrintSubMapEntry(M->Name, M->Kind);934}935}936}937938// Emit the macro definitions in the module file so that we can know how939// much definitions in the module file quickly.940// TODO: Emit the macro definition bodies completely.941if (auto FilteredMacros = llvm::make_filter_range(942R->getPreprocessor().macros(),943[](const auto &Macro) { return Macro.first->isFromAST(); });944!FilteredMacros.empty()) {945Out << " Macro Definitions:\n";946for (/*<IdentifierInfo *, MacroState> pair*/ const auto &Macro :947FilteredMacros)948Out << " " << Macro.first->getName() << "\n";949}950951// Now let's print out any modules we did not see as part of the Primary.952for (const auto &SM : SubModMap) {953if (!SM.second.Seen && SM.second.Mod) {954Out << " " << ModuleKindName(SM.second.Kind) << " '" << SM.first955<< "' at index #" << SM.second.Idx956<< " has no direct reference in the Primary\n";957}958}959Out << " ====== ======\n";960}961962// The reminder of the output is produced from the listener as the AST963// FileCcontrolBlock is (re-)parsed.964ASTReader::readASTFileControlBlock(965getCurrentFile(), FileMgr, CI.getModuleCache(),966CI.getPCHContainerReader(),967/*FindModuleFileExtensions=*/true, Listener,968HSOpts.ModulesValidateDiagnosticOptions);969}970971//===----------------------------------------------------------------------===//972// Preprocessor Actions973//===----------------------------------------------------------------------===//974975void DumpRawTokensAction::ExecuteAction() {976Preprocessor &PP = getCompilerInstance().getPreprocessor();977SourceManager &SM = PP.getSourceManager();978979// Start lexing the specified input file.980llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());981Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());982RawLex.SetKeepWhitespaceMode(true);983984Token RawTok;985RawLex.LexFromRawLexer(RawTok);986while (RawTok.isNot(tok::eof)) {987PP.DumpToken(RawTok, true);988llvm::errs() << "\n";989RawLex.LexFromRawLexer(RawTok);990}991}992993void DumpTokensAction::ExecuteAction() {994Preprocessor &PP = getCompilerInstance().getPreprocessor();995// Start preprocessing the specified input file.996Token Tok;997PP.EnterMainSourceFile();998do {999PP.Lex(Tok);1000PP.DumpToken(Tok, true);1001llvm::errs() << "\n";1002} while (Tok.isNot(tok::eof));1003}10041005void PreprocessOnlyAction::ExecuteAction() {1006Preprocessor &PP = getCompilerInstance().getPreprocessor();10071008// Ignore unknown pragmas.1009PP.IgnorePragmas();10101011Token Tok;1012// Start parsing the specified input file.1013PP.EnterMainSourceFile();1014do {1015PP.Lex(Tok);1016} while (Tok.isNot(tok::eof));1017}10181019void PrintPreprocessedAction::ExecuteAction() {1020CompilerInstance &CI = getCompilerInstance();1021// Output file may need to be set to 'Binary', to avoid converting Unix style1022// line feeds (<LF>) to Microsoft style line feeds (<CR><LF>) on Windows.1023//1024// Look to see what type of line endings the file uses. If there's a1025// CRLF, then we won't open the file up in binary mode. If there is1026// just an LF or CR, then we will open the file up in binary mode.1027// In this fashion, the output format should match the input format, unless1028// the input format has inconsistent line endings.1029//1030// This should be a relatively fast operation since most files won't have1031// all of their source code on a single line. However, that is still a1032// concern, so if we scan for too long, we'll just assume the file should1033// be opened in binary mode.10341035bool BinaryMode = false;1036if (llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows()) {1037BinaryMode = true;1038const SourceManager &SM = CI.getSourceManager();1039if (std::optional<llvm::MemoryBufferRef> Buffer =1040SM.getBufferOrNone(SM.getMainFileID())) {1041const char *cur = Buffer->getBufferStart();1042const char *end = Buffer->getBufferEnd();1043const char *next = (cur != end) ? cur + 1 : end;10441045// Limit ourselves to only scanning 256 characters into the source1046// file. This is mostly a check in case the file has no1047// newlines whatsoever.1048if (end - cur > 256)1049end = cur + 256;10501051while (next < end) {1052if (*cur == 0x0D) { // CR1053if (*next == 0x0A) // CRLF1054BinaryMode = false;10551056break;1057} else if (*cur == 0x0A) // LF1058break;10591060++cur;1061++next;1062}1063}1064}10651066std::unique_ptr<raw_ostream> OS =1067CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName());1068if (!OS) return;10691070// If we're preprocessing a module map, start by dumping the contents of the1071// module itself before switching to the input buffer.1072auto &Input = getCurrentInput();1073if (Input.getKind().getFormat() == InputKind::ModuleMap) {1074if (Input.isFile()) {1075(*OS) << "# 1 \"";1076OS->write_escaped(Input.getFile());1077(*OS) << "\"\n";1078}1079getCurrentModule()->print(*OS);1080(*OS) << "#pragma clang module contents\n";1081}10821083DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(),1084CI.getPreprocessorOutputOpts());1085}10861087void PrintPreambleAction::ExecuteAction() {1088switch (getCurrentFileKind().getLanguage()) {1089case Language::C:1090case Language::CXX:1091case Language::ObjC:1092case Language::ObjCXX:1093case Language::OpenCL:1094case Language::OpenCLCXX:1095case Language::CUDA:1096case Language::HIP:1097case Language::HLSL:1098case Language::CIR:1099break;11001101case Language::Unknown:1102case Language::Asm:1103case Language::LLVM_IR:1104case Language::RenderScript:1105// We can't do anything with these.1106return;1107}11081109// We don't expect to find any #include directives in a preprocessed input.1110if (getCurrentFileKind().isPreprocessed())1111return;11121113CompilerInstance &CI = getCompilerInstance();1114auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());1115if (Buffer) {1116unsigned Preamble =1117Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;1118llvm::outs().write((*Buffer)->getBufferStart(), Preamble);1119}1120}11211122void DumpCompilerOptionsAction::ExecuteAction() {1123CompilerInstance &CI = getCompilerInstance();1124std::unique_ptr<raw_ostream> OSP =1125CI.createDefaultOutputFile(false, getCurrentFile());1126if (!OSP)1127return;11281129raw_ostream &OS = *OSP;1130const Preprocessor &PP = CI.getPreprocessor();1131const LangOptions &LangOpts = PP.getLangOpts();11321133// FIXME: Rather than manually format the JSON (which is awkward due to1134// needing to remove trailing commas), this should make use of a JSON library.1135// FIXME: Instead of printing enums as an integral value and specifying the1136// type as a separate field, use introspection to print the enumerator.11371138OS << "{\n";1139OS << "\n\"features\" : [\n";1140{1141llvm::SmallString<128> Str;1142#define FEATURE(Name, Predicate) \1143("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \1144.toVector(Str);1145#include "clang/Basic/Features.def"1146#undef FEATURE1147// Remove the newline and comma from the last entry to ensure this remains1148// valid JSON.1149OS << Str.substr(0, Str.size() - 2);1150}1151OS << "\n],\n";11521153OS << "\n\"extensions\" : [\n";1154{1155llvm::SmallString<128> Str;1156#define EXTENSION(Name, Predicate) \1157("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \1158.toVector(Str);1159#include "clang/Basic/Features.def"1160#undef EXTENSION1161// Remove the newline and comma from the last entry to ensure this remains1162// valid JSON.1163OS << Str.substr(0, Str.size() - 2);1164}1165OS << "\n]\n";11661167OS << "}";1168}11691170void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() {1171CompilerInstance &CI = getCompilerInstance();1172SourceManager &SM = CI.getPreprocessor().getSourceManager();1173llvm::MemoryBufferRef FromFile = SM.getBufferOrFake(SM.getMainFileID());11741175llvm::SmallVector<dependency_directives_scan::Token, 16> Tokens;1176llvm::SmallVector<dependency_directives_scan::Directive, 32> Directives;1177if (scanSourceForDependencyDirectives(1178FromFile.getBuffer(), Tokens, Directives, &CI.getDiagnostics(),1179SM.getLocForStartOfFile(SM.getMainFileID()))) {1180assert(CI.getDiagnostics().hasErrorOccurred() &&1181"no errors reported for failure");11821183// Preprocess the source when verifying the diagnostics to capture the1184// 'expected' comments.1185if (CI.getDiagnosticOpts().VerifyDiagnostics) {1186// Make sure we don't emit new diagnostics!1187CI.getDiagnostics().setSuppressAllDiagnostics(true);1188Preprocessor &PP = getCompilerInstance().getPreprocessor();1189PP.EnterMainSourceFile();1190Token Tok;1191do {1192PP.Lex(Tok);1193} while (Tok.isNot(tok::eof));1194}1195return;1196}1197printDependencyDirectivesAsSource(FromFile.getBuffer(), Directives,1198llvm::outs());1199}12001201void GetDependenciesByModuleNameAction::ExecuteAction() {1202CompilerInstance &CI = getCompilerInstance();1203Preprocessor &PP = CI.getPreprocessor();1204SourceManager &SM = PP.getSourceManager();1205FileID MainFileID = SM.getMainFileID();1206SourceLocation FileStart = SM.getLocForStartOfFile(MainFileID);1207SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;1208IdentifierInfo *ModuleID = PP.getIdentifierInfo(ModuleName);1209Path.push_back(std::make_pair(ModuleID, FileStart));1210auto ModResult = CI.loadModule(FileStart, Path, Module::Hidden, false);1211PPCallbacks *CB = PP.getPPCallbacks();1212CB->moduleImport(SourceLocation(), Path, ModResult);1213}121412151216