1199482Srdivacky//===--- FrontendActions.cpp ----------------------------------------------===// 2199482Srdivacky// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6199482Srdivacky// 7199482Srdivacky//===----------------------------------------------------------------------===// 8199482Srdivacky 9199482Srdivacky#include "clang/Frontend/FrontendActions.h" 10199482Srdivacky#include "clang/AST/ASTConsumer.h" 11199482Srdivacky#include "clang/Basic/FileManager.h" 12360784Sdim#include "clang/Basic/LangStandard.h" 13199482Srdivacky#include "clang/Frontend/ASTConsumers.h" 14199482Srdivacky#include "clang/Frontend/CompilerInstance.h" 15199482Srdivacky#include "clang/Frontend/FrontendDiagnostic.h" 16288943Sdim#include "clang/Frontend/MultiplexConsumer.h" 17199482Srdivacky#include "clang/Frontend/Utils.h" 18353358Sdim#include "clang/Lex/DependencyDirectivesSourceMinimizer.h" 19249423Sdim#include "clang/Lex/HeaderSearch.h" 20249423Sdim#include "clang/Lex/Preprocessor.h" 21314564Sdim#include "clang/Lex/PreprocessorOptions.h" 22341825Sdim#include "clang/Sema/TemplateInstCallback.h" 23249423Sdim#include "clang/Serialization/ASTReader.h" 24212904Sdim#include "clang/Serialization/ASTWriter.h" 25234353Sdim#include "llvm/Support/FileSystem.h" 26212904Sdim#include "llvm/Support/MemoryBuffer.h" 27314564Sdim#include "llvm/Support/Path.h" 28353358Sdim#include "llvm/Support/YAMLTraits.h" 29199482Srdivacky#include "llvm/Support/raw_ostream.h" 30276479Sdim#include <memory> 31276479Sdim#include <system_error> 32226633Sdim 33199482Srdivackyusing namespace clang; 34199482Srdivacky 35341825Sdimnamespace { 36341825SdimCodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) { 37341825Sdim return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer() 38341825Sdim : nullptr; 39341825Sdim} 40341825Sdim 41341825Sdimvoid EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) { 42341825Sdim if (Action.hasCodeCompletionSupport() && 43341825Sdim !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 44341825Sdim CI.createCodeCompletionConsumer(); 45341825Sdim 46341825Sdim if (!CI.hasSema()) 47341825Sdim CI.createSema(Action.getTranslationUnitKind(), 48341825Sdim GetCodeCompletionConsumer(CI)); 49341825Sdim} 50341825Sdim} // namespace 51341825Sdim 52199482Srdivacky//===----------------------------------------------------------------------===// 53205408Srdivacky// Custom Actions 54205408Srdivacky//===----------------------------------------------------------------------===// 55205408Srdivacky 56280031Sdimstd::unique_ptr<ASTConsumer> 57280031SdimInitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 58360784Sdim return std::make_unique<ASTConsumer>(); 59205408Srdivacky} 60205408Srdivacky 61205408Srdivackyvoid InitOnlyAction::ExecuteAction() { 62205408Srdivacky} 63205408Srdivacky 64205408Srdivacky//===----------------------------------------------------------------------===// 65199482Srdivacky// AST Consumer Actions 66199482Srdivacky//===----------------------------------------------------------------------===// 67199482Srdivacky 68280031Sdimstd::unique_ptr<ASTConsumer> 69280031SdimASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 70309124Sdim if (std::unique_ptr<raw_ostream> OS = 71309124Sdim CI.createDefaultOutputFile(false, InFile)) 72309124Sdim return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter); 73276479Sdim return nullptr; 74199482Srdivacky} 75199482Srdivacky 76280031Sdimstd::unique_ptr<ASTConsumer> 77280031SdimASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 78353358Sdim const FrontendOptions &Opts = CI.getFrontendOpts(); 79353358Sdim return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter, 80353358Sdim Opts.ASTDumpDecls, Opts.ASTDumpAll, 81353358Sdim Opts.ASTDumpLookups, Opts.ASTDumpFormat); 82199482Srdivacky} 83199482Srdivacky 84280031Sdimstd::unique_ptr<ASTConsumer> 85280031SdimASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 86239462Sdim return CreateASTDeclNodeLister(); 87239462Sdim} 88239462Sdim 89280031Sdimstd::unique_ptr<ASTConsumer> 90280031SdimASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 91199482Srdivacky return CreateASTViewer(); 92199482Srdivacky} 93199482Srdivacky 94280031Sdimstd::unique_ptr<ASTConsumer> 95280031SdimGeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 96212904Sdim std::string Sysroot; 97327952Sdim if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot)) 98327952Sdim return nullptr; 99327952Sdim 100218893Sdim std::string OutputFile; 101309124Sdim std::unique_ptr<raw_pwrite_stream> OS = 102327952Sdim CreateOutputFile(CI, InFile, /*ref*/ OutputFile); 103288943Sdim if (!OS) 104276479Sdim return nullptr; 105212904Sdim 106226633Sdim if (!CI.getFrontendOpts().RelocatablePCH) 107226633Sdim Sysroot.clear(); 108288943Sdim 109341825Sdim const auto &FrontendOpts = CI.getFrontendOpts(); 110288943Sdim auto Buffer = std::make_shared<PCHBuffer>(); 111288943Sdim std::vector<std::unique_ptr<ASTConsumer>> Consumers; 112360784Sdim Consumers.push_back(std::make_unique<PCHGenerator>( 113353358Sdim CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, 114353358Sdim FrontendOpts.ModuleFileExtensions, 115353358Sdim CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, 116353358Sdim FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH)); 117296417Sdim Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( 118309124Sdim CI, InFile, OutputFile, std::move(OS), Buffer)); 119288943Sdim 120360784Sdim return std::make_unique<MultiplexConsumer>(std::move(Consumers)); 121212904Sdim} 122212904Sdim 123327952Sdimbool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, 124327952Sdim std::string &Sysroot) { 125212904Sdim Sysroot = CI.getHeaderSearchOpts().Sysroot; 126212904Sdim if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { 127212904Sdim CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); 128327952Sdim return false; 129199482Srdivacky } 130199482Srdivacky 131327952Sdim return true; 132327952Sdim} 133327952Sdim 134327952Sdimstd::unique_ptr<llvm::raw_pwrite_stream> 135327952SdimGeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, 136327952Sdim std::string &OutputFile) { 137218893Sdim // We use createOutputFile here because this is exposed via libclang, and we 138218893Sdim // must disable the RemoveFileOnSignal behavior. 139226633Sdim // We use a temporary to avoid race conditions. 140309124Sdim std::unique_ptr<raw_pwrite_stream> OS = 141288943Sdim CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, 142288943Sdim /*RemoveFileOnSignal=*/false, InFile, 143360784Sdim /*Extension=*/"", CI.getFrontendOpts().UseTemporary); 144200583Srdivacky if (!OS) 145288943Sdim return nullptr; 146200583Srdivacky 147218893Sdim OutputFile = CI.getFrontendOpts().OutputFile; 148288943Sdim return OS; 149199482Srdivacky} 150199482Srdivacky 151321369Sdimbool GeneratePCHAction::shouldEraseOutputFiles() { 152321369Sdim if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors) 153321369Sdim return false; 154321369Sdim return ASTFrontendAction::shouldEraseOutputFiles(); 155321369Sdim} 156321369Sdim 157321369Sdimbool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) { 158314564Sdim CI.getLangOpts().CompilingPCH = true; 159314564Sdim return true; 160314564Sdim} 161314564Sdim 162280031Sdimstd::unique_ptr<ASTConsumer> 163280031SdimGenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, 164280031Sdim StringRef InFile) { 165314564Sdim std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile); 166288943Sdim if (!OS) 167276479Sdim return nullptr; 168276479Sdim 169314564Sdim std::string OutputFile = CI.getFrontendOpts().OutputFile; 170314564Sdim std::string Sysroot; 171314564Sdim 172288943Sdim auto Buffer = std::make_shared<PCHBuffer>(); 173288943Sdim std::vector<std::unique_ptr<ASTConsumer>> Consumers; 174296417Sdim 175360784Sdim Consumers.push_back(std::make_unique<PCHGenerator>( 176353358Sdim CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, 177353358Sdim CI.getFrontendOpts().ModuleFileExtensions, 178353358Sdim /*AllowASTWithErrors=*/false, 179353358Sdim /*IncludeTimestamps=*/ 180353358Sdim +CI.getFrontendOpts().BuildingImplicitModule, 181353358Sdim /*ShouldCacheASTInMemory=*/ 182353358Sdim +CI.getFrontendOpts().BuildingImplicitModule)); 183296417Sdim Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( 184309124Sdim CI, InFile, OutputFile, std::move(OS), Buffer)); 185360784Sdim return std::make_unique<MultiplexConsumer>(std::move(Consumers)); 186234353Sdim} 187234353Sdim 188314564Sdimbool GenerateModuleFromModuleMapAction::BeginSourceFileAction( 189321369Sdim CompilerInstance &CI) { 190321369Sdim if (!CI.getLangOpts().Modules) { 191321369Sdim CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules); 192314564Sdim return false; 193234353Sdim } 194276479Sdim 195321369Sdim return GenerateModuleAction::BeginSourceFileAction(CI); 196234353Sdim} 197234353Sdim 198309124Sdimstd::unique_ptr<raw_pwrite_stream> 199314564SdimGenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, 200314564Sdim StringRef InFile) { 201234353Sdim // If no output file was provided, figure out where this module would go 202234353Sdim // in the module cache. 203234353Sdim if (CI.getFrontendOpts().OutputFile.empty()) { 204321369Sdim StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap; 205321369Sdim if (ModuleMapFile.empty()) 206321369Sdim ModuleMapFile = InFile; 207321369Sdim 208234353Sdim HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); 209276479Sdim CI.getFrontendOpts().OutputFile = 210327952Sdim HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule, 211327952Sdim ModuleMapFile); 212234353Sdim } 213288943Sdim 214234353Sdim // We use createOutputFile here because this is exposed via libclang, and we 215234353Sdim // must disable the RemoveFileOnSignal behavior. 216234353Sdim // We use a temporary to avoid race conditions. 217314564Sdim return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, 218314564Sdim /*RemoveFileOnSignal=*/false, InFile, 219353358Sdim /*Extension=*/"", /*UseTemporary=*/true, 220314564Sdim /*CreateMissingDirectories=*/true); 221314564Sdim} 222288943Sdim 223321369Sdimbool GenerateModuleInterfaceAction::BeginSourceFileAction( 224321369Sdim CompilerInstance &CI) { 225353358Sdim if (!CI.getLangOpts().ModulesTS && !CI.getLangOpts().CPlusPlusModules) { 226353358Sdim CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules); 227314564Sdim return false; 228314564Sdim } 229314564Sdim 230314564Sdim CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface); 231314564Sdim 232321369Sdim return GenerateModuleAction::BeginSourceFileAction(CI); 233234353Sdim} 234234353Sdim 235314564Sdimstd::unique_ptr<raw_pwrite_stream> 236314564SdimGenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, 237314564Sdim StringRef InFile) { 238314564Sdim return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); 239314564Sdim} 240314564Sdim 241344779Sdimbool GenerateHeaderModuleAction::PrepareToExecuteAction( 242344779Sdim CompilerInstance &CI) { 243353358Sdim if (!CI.getLangOpts().Modules) { 244344779Sdim CI.getDiagnostics().Report(diag::err_header_module_requires_modules); 245344779Sdim return false; 246344779Sdim } 247344779Sdim 248344779Sdim auto &Inputs = CI.getFrontendOpts().Inputs; 249344779Sdim if (Inputs.empty()) 250344779Sdim return GenerateModuleAction::BeginInvocation(CI); 251344779Sdim 252344779Sdim auto Kind = Inputs[0].getKind(); 253344779Sdim 254344779Sdim // Convert the header file inputs into a single module input buffer. 255344779Sdim SmallString<256> HeaderContents; 256344779Sdim ModuleHeaders.reserve(Inputs.size()); 257344779Sdim for (const FrontendInputFile &FIF : Inputs) { 258344779Sdim // FIXME: We should support re-compiling from an AST file. 259344779Sdim if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) { 260344779Sdim CI.getDiagnostics().Report(diag::err_module_header_file_not_found) 261344779Sdim << (FIF.isFile() ? FIF.getFile() 262344779Sdim : FIF.getBuffer()->getBufferIdentifier()); 263344779Sdim return true; 264344779Sdim } 265344779Sdim 266344779Sdim HeaderContents += "#include \""; 267344779Sdim HeaderContents += FIF.getFile(); 268344779Sdim HeaderContents += "\"\n"; 269344779Sdim ModuleHeaders.push_back(FIF.getFile()); 270344779Sdim } 271344779Sdim Buffer = llvm::MemoryBuffer::getMemBufferCopy( 272344779Sdim HeaderContents, Module::getModuleInputBufferName()); 273344779Sdim 274344779Sdim // Set that buffer up as our "real" input. 275344779Sdim Inputs.clear(); 276344779Sdim Inputs.push_back(FrontendInputFile(Buffer.get(), Kind, /*IsSystem*/false)); 277344779Sdim 278344779Sdim return GenerateModuleAction::PrepareToExecuteAction(CI); 279344779Sdim} 280344779Sdim 281344779Sdimbool GenerateHeaderModuleAction::BeginSourceFileAction( 282344779Sdim CompilerInstance &CI) { 283344779Sdim CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule); 284344779Sdim 285344779Sdim // Synthesize a Module object for the given headers. 286344779Sdim auto &HS = CI.getPreprocessor().getHeaderSearchInfo(); 287344779Sdim SmallVector<Module::Header, 16> Headers; 288344779Sdim for (StringRef Name : ModuleHeaders) { 289344779Sdim const DirectoryLookup *CurDir = nullptr; 290360784Sdim Optional<FileEntryRef> FE = HS.LookupFile( 291360784Sdim Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir, None, 292360784Sdim nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); 293344779Sdim if (!FE) { 294344779Sdim CI.getDiagnostics().Report(diag::err_module_header_file_not_found) 295344779Sdim << Name; 296344779Sdim continue; 297344779Sdim } 298360784Sdim Headers.push_back({Name, &FE->getFileEntry()}); 299344779Sdim } 300344779Sdim HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers); 301344779Sdim 302344779Sdim return GenerateModuleAction::BeginSourceFileAction(CI); 303344779Sdim} 304344779Sdim 305344779Sdimstd::unique_ptr<raw_pwrite_stream> 306344779SdimGenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI, 307344779Sdim StringRef InFile) { 308344779Sdim return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm"); 309344779Sdim} 310344779Sdim 311309124SdimSyntaxOnlyAction::~SyntaxOnlyAction() { 312309124Sdim} 313309124Sdim 314280031Sdimstd::unique_ptr<ASTConsumer> 315280031SdimSyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 316360784Sdim return std::make_unique<ASTConsumer>(); 317199482Srdivacky} 318199482Srdivacky 319280031Sdimstd::unique_ptr<ASTConsumer> 320280031SdimDumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI, 321280031Sdim StringRef InFile) { 322360784Sdim return std::make_unique<ASTConsumer>(); 323249423Sdim} 324249423Sdim 325280031Sdimstd::unique_ptr<ASTConsumer> 326280031SdimVerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 327360784Sdim return std::make_unique<ASTConsumer>(); 328276479Sdim} 329276479Sdim 330276479Sdimvoid VerifyPCHAction::ExecuteAction() { 331276479Sdim CompilerInstance &CI = getCompilerInstance(); 332276479Sdim bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; 333276479Sdim const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; 334288943Sdim std::unique_ptr<ASTReader> Reader(new ASTReader( 335353358Sdim CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(), 336353358Sdim CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions, 337288943Sdim Sysroot.empty() ? "" : Sysroot.c_str(), 338288943Sdim /*DisableValidation*/ false, 339288943Sdim /*AllowPCHWithCompilerErrors*/ false, 340288943Sdim /*AllowConfigurationMismatch*/ true, 341288943Sdim /*ValidateSystemInputs*/ true)); 342276479Sdim 343276479Sdim Reader->ReadAST(getCurrentFile(), 344276479Sdim Preamble ? serialization::MK_Preamble 345276479Sdim : serialization::MK_PCH, 346276479Sdim SourceLocation(), 347276479Sdim ASTReader::ARR_ConfigurationMismatch); 348276479Sdim} 349276479Sdim 350249423Sdimnamespace { 351341825Sdimstruct TemplightEntry { 352341825Sdim std::string Name; 353341825Sdim std::string Kind; 354341825Sdim std::string Event; 355341825Sdim std::string DefinitionLocation; 356341825Sdim std::string PointOfInstantiation; 357341825Sdim}; 358341825Sdim} // namespace 359341825Sdim 360341825Sdimnamespace llvm { 361341825Sdimnamespace yaml { 362341825Sdimtemplate <> struct MappingTraits<TemplightEntry> { 363341825Sdim static void mapping(IO &io, TemplightEntry &fields) { 364341825Sdim io.mapRequired("name", fields.Name); 365341825Sdim io.mapRequired("kind", fields.Kind); 366341825Sdim io.mapRequired("event", fields.Event); 367341825Sdim io.mapRequired("orig", fields.DefinitionLocation); 368341825Sdim io.mapRequired("poi", fields.PointOfInstantiation); 369341825Sdim } 370341825Sdim}; 371341825Sdim} // namespace yaml 372341825Sdim} // namespace llvm 373341825Sdim 374341825Sdimnamespace { 375341825Sdimclass DefaultTemplateInstCallback : public TemplateInstantiationCallback { 376341825Sdim using CodeSynthesisContext = Sema::CodeSynthesisContext; 377341825Sdim 378341825Sdimpublic: 379341825Sdim void initialize(const Sema &) override {} 380341825Sdim 381341825Sdim void finalize(const Sema &) override {} 382341825Sdim 383341825Sdim void atTemplateBegin(const Sema &TheSema, 384341825Sdim const CodeSynthesisContext &Inst) override { 385341825Sdim displayTemplightEntry<true>(llvm::outs(), TheSema, Inst); 386341825Sdim } 387341825Sdim 388341825Sdim void atTemplateEnd(const Sema &TheSema, 389341825Sdim const CodeSynthesisContext &Inst) override { 390341825Sdim displayTemplightEntry<false>(llvm::outs(), TheSema, Inst); 391341825Sdim } 392341825Sdim 393341825Sdimprivate: 394341825Sdim static std::string toString(CodeSynthesisContext::SynthesisKind Kind) { 395341825Sdim switch (Kind) { 396341825Sdim case CodeSynthesisContext::TemplateInstantiation: 397341825Sdim return "TemplateInstantiation"; 398341825Sdim case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: 399341825Sdim return "DefaultTemplateArgumentInstantiation"; 400341825Sdim case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: 401341825Sdim return "DefaultFunctionArgumentInstantiation"; 402341825Sdim case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: 403341825Sdim return "ExplicitTemplateArgumentSubstitution"; 404341825Sdim case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: 405341825Sdim return "DeducedTemplateArgumentSubstitution"; 406341825Sdim case CodeSynthesisContext::PriorTemplateArgumentSubstitution: 407341825Sdim return "PriorTemplateArgumentSubstitution"; 408341825Sdim case CodeSynthesisContext::DefaultTemplateArgumentChecking: 409341825Sdim return "DefaultTemplateArgumentChecking"; 410344779Sdim case CodeSynthesisContext::ExceptionSpecEvaluation: 411344779Sdim return "ExceptionSpecEvaluation"; 412341825Sdim case CodeSynthesisContext::ExceptionSpecInstantiation: 413341825Sdim return "ExceptionSpecInstantiation"; 414341825Sdim case CodeSynthesisContext::DeclaringSpecialMember: 415341825Sdim return "DeclaringSpecialMember"; 416360784Sdim case CodeSynthesisContext::DeclaringImplicitEqualityComparison: 417360784Sdim return "DeclaringImplicitEqualityComparison"; 418341825Sdim case CodeSynthesisContext::DefiningSynthesizedFunction: 419341825Sdim return "DefiningSynthesizedFunction"; 420360784Sdim case CodeSynthesisContext::RewritingOperatorAsSpaceship: 421360784Sdim return "RewritingOperatorAsSpaceship"; 422341825Sdim case CodeSynthesisContext::Memoization: 423341825Sdim return "Memoization"; 424360784Sdim case CodeSynthesisContext::ConstraintsCheck: 425360784Sdim return "ConstraintsCheck"; 426360784Sdim case CodeSynthesisContext::ConstraintSubstitution: 427360784Sdim return "ConstraintSubstitution"; 428360784Sdim case CodeSynthesisContext::ConstraintNormalization: 429360784Sdim return "ConstraintNormalization"; 430360784Sdim case CodeSynthesisContext::ParameterMappingSubstitution: 431360784Sdim return "ParameterMappingSubstitution"; 432360784Sdim case CodeSynthesisContext::RequirementInstantiation: 433360784Sdim return "RequirementInstantiation"; 434360784Sdim case CodeSynthesisContext::NestedRequirementConstraintsCheck: 435360784Sdim return "NestedRequirementConstraintsCheck"; 436341825Sdim } 437341825Sdim return ""; 438341825Sdim } 439341825Sdim 440341825Sdim template <bool BeginInstantiation> 441341825Sdim static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema, 442341825Sdim const CodeSynthesisContext &Inst) { 443341825Sdim std::string YAML; 444341825Sdim { 445341825Sdim llvm::raw_string_ostream OS(YAML); 446341825Sdim llvm::yaml::Output YO(OS); 447341825Sdim TemplightEntry Entry = 448341825Sdim getTemplightEntry<BeginInstantiation>(TheSema, Inst); 449341825Sdim llvm::yaml::EmptyContext Context; 450341825Sdim llvm::yaml::yamlize(YO, Entry, true, Context); 451341825Sdim } 452341825Sdim Out << "---" << YAML << "\n"; 453341825Sdim } 454341825Sdim 455341825Sdim template <bool BeginInstantiation> 456341825Sdim static TemplightEntry getTemplightEntry(const Sema &TheSema, 457341825Sdim const CodeSynthesisContext &Inst) { 458341825Sdim TemplightEntry Entry; 459341825Sdim Entry.Kind = toString(Inst.Kind); 460341825Sdim Entry.Event = BeginInstantiation ? "Begin" : "End"; 461341825Sdim if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) { 462341825Sdim llvm::raw_string_ostream OS(Entry.Name); 463341825Sdim NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true); 464341825Sdim const PresumedLoc DefLoc = 465341825Sdim TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation()); 466341825Sdim if(!DefLoc.isInvalid()) 467341825Sdim Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" + 468341825Sdim std::to_string(DefLoc.getLine()) + ":" + 469341825Sdim std::to_string(DefLoc.getColumn()); 470341825Sdim } 471341825Sdim const PresumedLoc PoiLoc = 472341825Sdim TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation); 473341825Sdim if (!PoiLoc.isInvalid()) { 474341825Sdim Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" + 475341825Sdim std::to_string(PoiLoc.getLine()) + ":" + 476341825Sdim std::to_string(PoiLoc.getColumn()); 477341825Sdim } 478341825Sdim return Entry; 479341825Sdim } 480341825Sdim}; 481341825Sdim} // namespace 482341825Sdim 483341825Sdimstd::unique_ptr<ASTConsumer> 484341825SdimTemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 485360784Sdim return std::make_unique<ASTConsumer>(); 486341825Sdim} 487341825Sdim 488341825Sdimvoid TemplightDumpAction::ExecuteAction() { 489341825Sdim CompilerInstance &CI = getCompilerInstance(); 490341825Sdim 491341825Sdim // This part is normally done by ASTFrontEndAction, but needs to happen 492341825Sdim // before Templight observers can be created 493341825Sdim // FIXME: Move the truncation aspect of this into Sema, we delayed this till 494341825Sdim // here so the source manager would be initialized. 495341825Sdim EnsureSemaIsCreated(CI, *this); 496341825Sdim 497341825Sdim CI.getSema().TemplateInstCallbacks.push_back( 498360784Sdim std::make_unique<DefaultTemplateInstCallback>()); 499341825Sdim ASTFrontendAction::ExecuteAction(); 500341825Sdim} 501341825Sdim 502341825Sdimnamespace { 503341825Sdim /// AST reader listener that dumps module information for a module 504249423Sdim /// file. 505249423Sdim class DumpModuleInfoListener : public ASTReaderListener { 506249423Sdim llvm::raw_ostream &Out; 507249423Sdim 508249423Sdim public: 509249423Sdim DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { } 510249423Sdim 511249423Sdim#define DUMP_BOOLEAN(Value, Text) \ 512249423Sdim Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n" 513249423Sdim 514276479Sdim bool ReadFullVersionInformation(StringRef FullVersion) override { 515249423Sdim Out.indent(2) 516249423Sdim << "Generated by " 517249423Sdim << (FullVersion == getClangFullRepositoryVersion()? "this" 518249423Sdim : "a different") 519249423Sdim << " Clang: " << FullVersion << "\n"; 520249423Sdim return ASTReaderListener::ReadFullVersionInformation(FullVersion); 521249423Sdim } 522249423Sdim 523276479Sdim void ReadModuleName(StringRef ModuleName) override { 524276479Sdim Out.indent(2) << "Module name: " << ModuleName << "\n"; 525276479Sdim } 526276479Sdim void ReadModuleMapFile(StringRef ModuleMapPath) override { 527276479Sdim Out.indent(2) << "Module map file: " << ModuleMapPath << "\n"; 528276479Sdim } 529276479Sdim 530280031Sdim bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, 531280031Sdim bool AllowCompatibleDifferences) override { 532249423Sdim Out.indent(2) << "Language options:\n"; 533249423Sdim#define LANGOPT(Name, Bits, Default, Description) \ 534249423Sdim DUMP_BOOLEAN(LangOpts.Name, Description); 535249423Sdim#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ 536249423Sdim Out.indent(4) << Description << ": " \ 537249423Sdim << static_cast<unsigned>(LangOpts.get##Name()) << "\n"; 538249423Sdim#define VALUE_LANGOPT(Name, Bits, Default, Description) \ 539249423Sdim Out.indent(4) << Description << ": " << LangOpts.Name << "\n"; 540249423Sdim#define BENIGN_LANGOPT(Name, Bits, Default, Description) 541249423Sdim#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) 542249423Sdim#include "clang/Basic/LangOptions.def" 543288943Sdim 544288943Sdim if (!LangOpts.ModuleFeatures.empty()) { 545288943Sdim Out.indent(4) << "Module features:\n"; 546288943Sdim for (StringRef Feature : LangOpts.ModuleFeatures) 547288943Sdim Out.indent(6) << Feature << "\n"; 548288943Sdim } 549288943Sdim 550249423Sdim return false; 551249423Sdim } 552249423Sdim 553288943Sdim bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, 554288943Sdim bool AllowCompatibleDifferences) override { 555249423Sdim Out.indent(2) << "Target options:\n"; 556249423Sdim Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n"; 557249423Sdim Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n"; 558249423Sdim Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n"; 559249423Sdim 560249423Sdim if (!TargetOpts.FeaturesAsWritten.empty()) { 561249423Sdim Out.indent(4) << "Target features:\n"; 562249423Sdim for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); 563249423Sdim I != N; ++I) { 564249423Sdim Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n"; 565249423Sdim } 566249423Sdim } 567249423Sdim 568249423Sdim return false; 569249423Sdim } 570249423Sdim 571288943Sdim bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, 572288943Sdim bool Complain) override { 573276479Sdim Out.indent(2) << "Diagnostic options:\n"; 574276479Sdim#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name); 575276479Sdim#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ 576276479Sdim Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n"; 577276479Sdim#define VALUE_DIAGOPT(Name, Bits, Default) \ 578276479Sdim Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n"; 579276479Sdim#include "clang/Basic/DiagnosticOptions.def" 580276479Sdim 581276479Sdim Out.indent(4) << "Diagnostic flags:\n"; 582276479Sdim for (const std::string &Warning : DiagOpts->Warnings) 583276479Sdim Out.indent(6) << "-W" << Warning << "\n"; 584276479Sdim for (const std::string &Remark : DiagOpts->Remarks) 585276479Sdim Out.indent(6) << "-R" << Remark << "\n"; 586276479Sdim 587276479Sdim return false; 588276479Sdim } 589276479Sdim 590276479Sdim bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, 591288943Sdim StringRef SpecificModuleCachePath, 592276479Sdim bool Complain) override { 593249423Sdim Out.indent(2) << "Header search options:\n"; 594249423Sdim Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n"; 595321369Sdim Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n"; 596288943Sdim Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n"; 597249423Sdim DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes, 598249423Sdim "Use builtin include directories [-nobuiltininc]"); 599249423Sdim DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes, 600249423Sdim "Use standard system include directories [-nostdinc]"); 601249423Sdim DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes, 602249423Sdim "Use standard C++ include directories [-nostdinc++]"); 603249423Sdim DUMP_BOOLEAN(HSOpts.UseLibcxx, 604249423Sdim "Use libc++ (rather than libstdc++) [-stdlib=]"); 605249423Sdim return false; 606249423Sdim } 607249423Sdim 608276479Sdim bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, 609276479Sdim bool Complain, 610276479Sdim std::string &SuggestedPredefines) override { 611249423Sdim Out.indent(2) << "Preprocessor options:\n"; 612249423Sdim DUMP_BOOLEAN(PPOpts.UsePredefines, 613249423Sdim "Uses compiler/target-specific predefines [-undef]"); 614249423Sdim DUMP_BOOLEAN(PPOpts.DetailedRecord, 615249423Sdim "Uses detailed preprocessing record (for indexing)"); 616249423Sdim 617249423Sdim if (!PPOpts.Macros.empty()) { 618249423Sdim Out.indent(4) << "Predefined macros:\n"; 619249423Sdim } 620249423Sdim 621249423Sdim for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator 622249423Sdim I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end(); 623249423Sdim I != IEnd; ++I) { 624249423Sdim Out.indent(6); 625249423Sdim if (I->second) 626249423Sdim Out << "-U"; 627249423Sdim else 628249423Sdim Out << "-D"; 629249423Sdim Out << I->first << "\n"; 630249423Sdim } 631249423Sdim return false; 632249423Sdim } 633296417Sdim 634296417Sdim /// Indicates that a particular module file extension has been read. 635296417Sdim void readModuleFileExtension( 636296417Sdim const ModuleFileExtensionMetadata &Metadata) override { 637296417Sdim Out.indent(2) << "Module file extension '" 638296417Sdim << Metadata.BlockName << "' " << Metadata.MajorVersion 639296417Sdim << "." << Metadata.MinorVersion; 640296417Sdim if (!Metadata.UserInfo.empty()) { 641296417Sdim Out << ": "; 642296417Sdim Out.write_escaped(Metadata.UserInfo); 643296417Sdim } 644296417Sdim 645296417Sdim Out << "\n"; 646296417Sdim } 647341825Sdim 648341825Sdim /// Tells the \c ASTReaderListener that we want to receive the 649341825Sdim /// input files of the AST file via \c visitInputFile. 650341825Sdim bool needsInputFileVisitation() override { return true; } 651341825Sdim 652341825Sdim /// Tells the \c ASTReaderListener that we want to receive the 653341825Sdim /// input files of the AST file via \c visitInputFile. 654341825Sdim bool needsSystemInputFileVisitation() override { return true; } 655341825Sdim 656341825Sdim /// Indicates that the AST file contains particular input file. 657341825Sdim /// 658341825Sdim /// \returns true to continue receiving the next input file, false to stop. 659341825Sdim bool visitInputFile(StringRef Filename, bool isSystem, 660341825Sdim bool isOverridden, bool isExplicitModule) override { 661341825Sdim 662341825Sdim Out.indent(2) << "Input file: " << Filename; 663341825Sdim 664341825Sdim if (isSystem || isOverridden || isExplicitModule) { 665341825Sdim Out << " ["; 666341825Sdim if (isSystem) { 667341825Sdim Out << "System"; 668341825Sdim if (isOverridden || isExplicitModule) 669341825Sdim Out << ", "; 670341825Sdim } 671341825Sdim if (isOverridden) { 672341825Sdim Out << "Overridden"; 673341825Sdim if (isExplicitModule) 674341825Sdim Out << ", "; 675341825Sdim } 676341825Sdim if (isExplicitModule) 677341825Sdim Out << "ExplicitModule"; 678341825Sdim 679341825Sdim Out << "]"; 680341825Sdim } 681341825Sdim 682341825Sdim Out << "\n"; 683341825Sdim 684341825Sdim return true; 685341825Sdim } 686344779Sdim 687344779Sdim /// Returns true if this \c ASTReaderListener wants to receive the 688344779Sdim /// imports of the AST file via \c visitImport, false otherwise. 689344779Sdim bool needsImportVisitation() const override { return true; } 690344779Sdim 691344779Sdim /// If needsImportVisitation returns \c true, this is called for each 692344779Sdim /// AST file imported by this AST file. 693344779Sdim void visitImport(StringRef ModuleName, StringRef Filename) override { 694344779Sdim Out.indent(2) << "Imports module '" << ModuleName 695344779Sdim << "': " << Filename.str() << "\n"; 696344779Sdim } 697249423Sdim#undef DUMP_BOOLEAN 698249423Sdim }; 699249423Sdim} 700249423Sdim 701314564Sdimbool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) { 702314564Sdim // The Object file reader also supports raw ast files and there is no point in 703314564Sdim // being strict about the module file format in -module-file-info mode. 704314564Sdim CI.getHeaderSearchOpts().ModuleFormat = "obj"; 705314564Sdim return true; 706314564Sdim} 707314564Sdim 708249423Sdimvoid DumpModuleInfoAction::ExecuteAction() { 709249423Sdim // Set up the output file. 710276479Sdim std::unique_ptr<llvm::raw_fd_ostream> OutFile; 711249423Sdim StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile; 712249423Sdim if (!OutputFileName.empty() && OutputFileName != "-") { 713280031Sdim std::error_code EC; 714280031Sdim OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC, 715360784Sdim llvm::sys::fs::OF_Text)); 716249423Sdim } 717249423Sdim llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs(); 718249423Sdim 719249423Sdim Out << "Information for module file '" << getCurrentFile() << "':\n"; 720314564Sdim auto &FileMgr = getCompilerInstance().getFileManager(); 721314564Sdim auto Buffer = FileMgr.getBufferForFile(getCurrentFile()); 722314564Sdim StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer(); 723314564Sdim bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C' && Magic[1] == 'P' && 724314564Sdim Magic[2] == 'C' && Magic[3] == 'H'); 725314564Sdim Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n"; 726314564Sdim 727314564Sdim Preprocessor &PP = getCompilerInstance().getPreprocessor(); 728249423Sdim DumpModuleInfoListener Listener(Out); 729314564Sdim HeaderSearchOptions &HSOpts = 730314564Sdim PP.getHeaderSearchInfo().getHeaderSearchOpts(); 731288943Sdim ASTReader::readASTFileControlBlock( 732314564Sdim getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(), 733314564Sdim /*FindModuleFileExtensions=*/true, Listener, 734314564Sdim HSOpts.ModulesValidateDiagnosticOptions); 735249423Sdim} 736249423Sdim 737199482Srdivacky//===----------------------------------------------------------------------===// 738199482Srdivacky// Preprocessor Actions 739199482Srdivacky//===----------------------------------------------------------------------===// 740199482Srdivacky 741199482Srdivackyvoid DumpRawTokensAction::ExecuteAction() { 742199482Srdivacky Preprocessor &PP = getCompilerInstance().getPreprocessor(); 743199482Srdivacky SourceManager &SM = PP.getSourceManager(); 744199482Srdivacky 745199482Srdivacky // Start lexing the specified input file. 746199990Srdivacky const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 747234353Sdim Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts()); 748199482Srdivacky RawLex.SetKeepWhitespaceMode(true); 749199482Srdivacky 750199482Srdivacky Token RawTok; 751199482Srdivacky RawLex.LexFromRawLexer(RawTok); 752199482Srdivacky while (RawTok.isNot(tok::eof)) { 753199482Srdivacky PP.DumpToken(RawTok, true); 754199990Srdivacky llvm::errs() << "\n"; 755199482Srdivacky RawLex.LexFromRawLexer(RawTok); 756199482Srdivacky } 757199482Srdivacky} 758199482Srdivacky 759199482Srdivackyvoid DumpTokensAction::ExecuteAction() { 760199482Srdivacky Preprocessor &PP = getCompilerInstance().getPreprocessor(); 761199482Srdivacky // Start preprocessing the specified input file. 762199482Srdivacky Token Tok; 763207619Srdivacky PP.EnterMainSourceFile(); 764199482Srdivacky do { 765199482Srdivacky PP.Lex(Tok); 766199482Srdivacky PP.DumpToken(Tok, true); 767199990Srdivacky llvm::errs() << "\n"; 768199482Srdivacky } while (Tok.isNot(tok::eof)); 769199482Srdivacky} 770199482Srdivacky 771199482Srdivackyvoid PreprocessOnlyAction::ExecuteAction() { 772199482Srdivacky Preprocessor &PP = getCompilerInstance().getPreprocessor(); 773199482Srdivacky 774210299Sed // Ignore unknown pragmas. 775276479Sdim PP.IgnorePragmas(); 776210299Sed 777199482Srdivacky Token Tok; 778199482Srdivacky // Start parsing the specified input file. 779207619Srdivacky PP.EnterMainSourceFile(); 780199482Srdivacky do { 781199482Srdivacky PP.Lex(Tok); 782199482Srdivacky } while (Tok.isNot(tok::eof)); 783199482Srdivacky} 784199482Srdivacky 785199482Srdivackyvoid PrintPreprocessedAction::ExecuteAction() { 786199482Srdivacky CompilerInstance &CI = getCompilerInstance(); 787226633Sdim // Output file may need to be set to 'Binary', to avoid converting Unix style 788202379Srdivacky // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). 789226633Sdim // 790226633Sdim // Look to see what type of line endings the file uses. If there's a 791226633Sdim // CRLF, then we won't open the file up in binary mode. If there is 792226633Sdim // just an LF or CR, then we will open the file up in binary mode. 793226633Sdim // In this fashion, the output format should match the input format, unless 794226633Sdim // the input format has inconsistent line endings. 795226633Sdim // 796226633Sdim // This should be a relatively fast operation since most files won't have 797341825Sdim // all of their source code on a single line. However, that is still a 798226633Sdim // concern, so if we scan for too long, we'll just assume the file should 799226633Sdim // be opened in binary mode. 800226633Sdim bool BinaryMode = true; 801226633Sdim bool InvalidFile = false; 802226633Sdim const SourceManager& SM = CI.getSourceManager(); 803341825Sdim const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(), 804226633Sdim &InvalidFile); 805226633Sdim if (!InvalidFile) { 806226633Sdim const char *cur = Buffer->getBufferStart(); 807226633Sdim const char *end = Buffer->getBufferEnd(); 808226633Sdim const char *next = (cur != end) ? cur + 1 : end; 809226633Sdim 810226633Sdim // Limit ourselves to only scanning 256 characters into the source 811341825Sdim // file. This is mostly a sanity check in case the file has no 812226633Sdim // newlines whatsoever. 813226633Sdim if (end - cur > 256) end = cur + 256; 814321369Sdim 815226633Sdim while (next < end) { 816226633Sdim if (*cur == 0x0D) { // CR 817226633Sdim if (*next == 0x0A) // CRLF 818226633Sdim BinaryMode = false; 819226633Sdim 820226633Sdim break; 821226633Sdim } else if (*cur == 0x0A) // LF 822226633Sdim break; 823226633Sdim 824309124Sdim ++cur; 825309124Sdim ++next; 826226633Sdim } 827226633Sdim } 828226633Sdim 829309124Sdim std::unique_ptr<raw_ostream> OS = 830344779Sdim CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName()); 831200583Srdivacky if (!OS) return; 832200583Srdivacky 833321369Sdim // If we're preprocessing a module map, start by dumping the contents of the 834321369Sdim // module itself before switching to the input buffer. 835321369Sdim auto &Input = getCurrentInput(); 836321369Sdim if (Input.getKind().getFormat() == InputKind::ModuleMap) { 837321369Sdim if (Input.isFile()) { 838321369Sdim (*OS) << "# 1 \""; 839321369Sdim OS->write_escaped(Input.getFile()); 840321369Sdim (*OS) << "\"\n"; 841321369Sdim } 842321369Sdim getCurrentModule()->print(*OS); 843321369Sdim (*OS) << "#pragma clang module contents\n"; 844321369Sdim } 845321369Sdim 846309124Sdim DoPrintPreprocessedInput(CI.getPreprocessor(), OS.get(), 847199482Srdivacky CI.getPreprocessorOutputOpts()); 848199482Srdivacky} 849212904Sdim 850212904Sdimvoid PrintPreambleAction::ExecuteAction() { 851321369Sdim switch (getCurrentFileKind().getLanguage()) { 852360784Sdim case Language::C: 853360784Sdim case Language::CXX: 854360784Sdim case Language::ObjC: 855360784Sdim case Language::ObjCXX: 856360784Sdim case Language::OpenCL: 857360784Sdim case Language::CUDA: 858360784Sdim case Language::HIP: 859212904Sdim break; 860341825Sdim 861360784Sdim case Language::Unknown: 862360784Sdim case Language::Asm: 863360784Sdim case Language::LLVM_IR: 864360784Sdim case Language::RenderScript: 865212904Sdim // We can't do anything with these. 866212904Sdim return; 867212904Sdim } 868280031Sdim 869321369Sdim // We don't expect to find any #include directives in a preprocessed input. 870321369Sdim if (getCurrentFileKind().isPreprocessed()) 871321369Sdim return; 872321369Sdim 873218893Sdim CompilerInstance &CI = getCompilerInstance(); 874280031Sdim auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile()); 875212904Sdim if (Buffer) { 876280031Sdim unsigned Preamble = 877327952Sdim Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size; 878280031Sdim llvm::outs().write((*Buffer)->getBufferStart(), Preamble); 879212904Sdim } 880212904Sdim} 881341825Sdim 882341825Sdimvoid DumpCompilerOptionsAction::ExecuteAction() { 883341825Sdim CompilerInstance &CI = getCompilerInstance(); 884341825Sdim std::unique_ptr<raw_ostream> OSP = 885341825Sdim CI.createDefaultOutputFile(false, getCurrentFile()); 886341825Sdim if (!OSP) 887341825Sdim return; 888341825Sdim 889341825Sdim raw_ostream &OS = *OSP; 890341825Sdim const Preprocessor &PP = CI.getPreprocessor(); 891341825Sdim const LangOptions &LangOpts = PP.getLangOpts(); 892341825Sdim 893341825Sdim // FIXME: Rather than manually format the JSON (which is awkward due to 894341825Sdim // needing to remove trailing commas), this should make use of a JSON library. 895341825Sdim // FIXME: Instead of printing enums as an integral value and specifying the 896341825Sdim // type as a separate field, use introspection to print the enumerator. 897341825Sdim 898341825Sdim OS << "{\n"; 899341825Sdim OS << "\n\"features\" : [\n"; 900341825Sdim { 901341825Sdim llvm::SmallString<128> Str; 902341825Sdim#define FEATURE(Name, Predicate) \ 903341825Sdim ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ 904341825Sdim .toVector(Str); 905341825Sdim#include "clang/Basic/Features.def" 906341825Sdim#undef FEATURE 907341825Sdim // Remove the newline and comma from the last entry to ensure this remains 908341825Sdim // valid JSON. 909341825Sdim OS << Str.substr(0, Str.size() - 2); 910341825Sdim } 911341825Sdim OS << "\n],\n"; 912341825Sdim 913341825Sdim OS << "\n\"extensions\" : [\n"; 914341825Sdim { 915341825Sdim llvm::SmallString<128> Str; 916341825Sdim#define EXTENSION(Name, Predicate) \ 917341825Sdim ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ 918341825Sdim .toVector(Str); 919341825Sdim#include "clang/Basic/Features.def" 920341825Sdim#undef EXTENSION 921341825Sdim // Remove the newline and comma from the last entry to ensure this remains 922341825Sdim // valid JSON. 923341825Sdim OS << Str.substr(0, Str.size() - 2); 924341825Sdim } 925341825Sdim OS << "\n]\n"; 926341825Sdim 927341825Sdim OS << "}"; 928341825Sdim} 929353358Sdim 930353358Sdimvoid PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() { 931353358Sdim CompilerInstance &CI = getCompilerInstance(); 932353358Sdim SourceManager &SM = CI.getPreprocessor().getSourceManager(); 933353358Sdim const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 934353358Sdim 935353358Sdim llvm::SmallString<1024> Output; 936353358Sdim llvm::SmallVector<minimize_source_to_dependency_directives::Token, 32> Toks; 937353358Sdim if (minimizeSourceToDependencyDirectives( 938353358Sdim FromFile->getBuffer(), Output, Toks, &CI.getDiagnostics(), 939353358Sdim SM.getLocForStartOfFile(SM.getMainFileID()))) { 940353358Sdim assert(CI.getDiagnostics().hasErrorOccurred() && 941353358Sdim "no errors reported for failure"); 942353358Sdim 943353358Sdim // Preprocess the source when verifying the diagnostics to capture the 944353358Sdim // 'expected' comments. 945353358Sdim if (CI.getDiagnosticOpts().VerifyDiagnostics) { 946353358Sdim // Make sure we don't emit new diagnostics! 947360784Sdim CI.getDiagnostics().setSuppressAllDiagnostics(true); 948353358Sdim Preprocessor &PP = getCompilerInstance().getPreprocessor(); 949353358Sdim PP.EnterMainSourceFile(); 950353358Sdim Token Tok; 951353358Sdim do { 952353358Sdim PP.Lex(Tok); 953353358Sdim } while (Tok.isNot(tok::eof)); 954353358Sdim } 955353358Sdim return; 956353358Sdim } 957353358Sdim llvm::outs() << Output; 958353358Sdim} 959