Clang Project

clang_source_code/lib/Frontend/FrontendActions.cpp
1//===--- FrontendActions.cpp ----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Frontend/FrontendActions.h"
10#include "clang/AST/ASTConsumer.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Frontend/ASTConsumers.h"
13#include "clang/Frontend/CompilerInstance.h"
14#include "clang/Frontend/FrontendDiagnostic.h"
15#include "clang/Frontend/MultiplexConsumer.h"
16#include "clang/Frontend/Utils.h"
17#include "clang/Lex/HeaderSearch.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Lex/PreprocessorOptions.h"
20#include "clang/Sema/TemplateInstCallback.h"
21#include "clang/Serialization/ASTReader.h"
22#include "clang/Serialization/ASTWriter.h"
23#include "llvm/Support/FileSystem.h"
24#include "llvm/Support/MemoryBuffer.h"
25#include "llvm/Support/Path.h"
26#include "llvm/Support/raw_ostream.h"
27#include "llvm/Support/YAMLTraits.h"
28#include <memory>
29#include <system_error>
30
31using namespace clang;
32
33namespace {
34CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
35  return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer()
36                                        : nullptr;
37}
38
39void EnsureSemaIsCreated(CompilerInstance &CIFrontendAction &Action) {
40  if (Action.hasCodeCompletionSupport() &&
41      !CI.getFrontendOpts().CodeCompletionAt.FileName.empty())
42    CI.createCodeCompletionConsumer();
43
44  if (!CI.hasSema())
45    CI.createSema(Action.getTranslationUnitKind(),
46                  GetCodeCompletionConsumer(CI));
47}
48// namespace
49
50//===----------------------------------------------------------------------===//
51// Custom Actions
52//===----------------------------------------------------------------------===//
53
54std::unique_ptr<ASTConsumer>
55InitOnlyAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
56  return llvm::make_unique<ASTConsumer>();
57}
58
59void InitOnlyAction::ExecuteAction() {
60}
61
62//===----------------------------------------------------------------------===//
63// AST Consumer Actions
64//===----------------------------------------------------------------------===//
65
66std::unique_ptr<ASTConsumer>
67ASTPrintAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
68  if (std::unique_ptr<raw_ostreamOS =
69          CI.createDefaultOutputFile(false, InFile))
70    return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter);
71  return nullptr;
72}
73
74std::unique_ptr<ASTConsumer>
75ASTDumpAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
76  return CreateASTDumper(nullptr /*Dump to stdout.*/,
77                         CI.getFrontendOpts().ASTDumpFilter,
78                         CI.getFrontendOpts().ASTDumpDecls,
79                         CI.getFrontendOpts().ASTDumpAll,
80                         CI.getFrontendOpts().ASTDumpLookups);
81}
82
83std::unique_ptr<ASTConsumer>
84ASTDeclListAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
85  return CreateASTDeclNodeLister();
86}
87
88std::unique_ptr<ASTConsumer>
89ASTViewAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
90  return CreateASTViewer();
91}
92
93std::unique_ptr<ASTConsumer>
94GeneratePCHAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
95  std::string Sysroot;
96  if (!ComputeASTConsumerArguments(CI/*ref*/ Sysroot))
97    return nullptr;
98
99  std::string OutputFile;
100  std::unique_ptr<raw_pwrite_streamOS =
101      CreateOutputFile(CI, InFile, /*ref*/ OutputFile);
102  if (!OS)
103    return nullptr;
104
105  if (!CI.getFrontendOpts().RelocatablePCH)
106    Sysroot.clear();
107
108  const auto &FrontendOpts = CI.getFrontendOpts();
109  auto Buffer = std::make_shared<PCHBuffer>();
110  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
111  Consumers.push_back(llvm::make_unique<PCHGenerator>(
112      CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
113      FrontendOpts.ModuleFileExtensions,
114      CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
115      FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH));
116  Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
117      CI, InFile, OutputFile, std::move(OS), Buffer));
118
119  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
120}
121
122bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
123                                                    std::string &Sysroot) {
124  Sysroot = CI.getHeaderSearchOpts().Sysroot;
125  if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
126    CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
127    return false;
128  }
129
130  return true;
131}
132
133std::unique_ptr<llvm::raw_pwrite_stream>
134GeneratePCHAction::CreateOutputFile(CompilerInstance &CIStringRef InFile,
135                                    std::string &OutputFile) {
136  // We use createOutputFile here because this is exposed via libclang, and we
137  // must disable the RemoveFileOnSignal behavior.
138  // We use a temporary to avoid race conditions.
139  std::unique_ptr<raw_pwrite_streamOS =
140      CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
141                          /*RemoveFileOnSignal=*/false, InFile,
142                          /*Extension=*/""/*useTemporary=*/true);
143  if (!OS)
144    return nullptr;
145
146  OutputFile = CI.getFrontendOpts().OutputFile;
147  return OS;
148}
149
150bool GeneratePCHAction::shouldEraseOutputFiles() {
151  if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors)
152    return false;
153  return ASTFrontendAction::shouldEraseOutputFiles();
154}
155
156bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
157  CI.getLangOpts().CompilingPCH = true;
158  return true;
159}
160
161std::unique_ptr<ASTConsumer>
162GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
163                                        StringRef InFile) {
164  std::unique_ptr<raw_pwrite_streamOS = CreateOutputFile(CI, InFile);
165  if (!OS)
166    return nullptr;
167
168  std::string OutputFile = CI.getFrontendOpts().OutputFile;
169  std::string Sysroot;
170
171  auto Buffer = std::make_shared<PCHBuffer>();
172  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
173
174  Consumers.push_back(llvm::make_unique<PCHGenerator>(
175      CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer,
176      CI.getFrontendOpts().ModuleFileExtensions,
177      /*AllowASTWithErrors=*/false,
178      /*IncludeTimestamps=*/
179      +CI.getFrontendOpts().BuildingImplicitModule,
180      /*ShouldCacheASTInMemory=*/
181      +CI.getFrontendOpts().BuildingImplicitModule));
182  Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
183      CI, InFile, OutputFile, std::move(OS), Buffer));
184  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
185}
186
187bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
188    CompilerInstance &CI) {
189  if (!CI.getLangOpts().Modules) {
190    CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules);
191    return false;
192  }
193
194  return GenerateModuleAction::BeginSourceFileAction(CI);
195}
196
197std::unique_ptr<raw_pwrite_stream>
198GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
199                                                    StringRef InFile) {
200  // If no output file was provided, figure out where this module would go
201  // in the module cache.
202  if (CI.getFrontendOpts().OutputFile.empty()) {
203    StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;
204    if (ModuleMapFile.empty())
205      ModuleMapFile = InFile;
206
207    HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
208    CI.getFrontendOpts().OutputFile =
209        HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule,
210                                   ModuleMapFile);
211  }
212
213  // We use createOutputFile here because this is exposed via libclang, and we
214  // must disable the RemoveFileOnSignal behavior.
215  // We use a temporary to avoid race conditions.
216  return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
217                             /*RemoveFileOnSignal=*/false, InFile,
218                             /*Extension=*/""/*useTemporary=*/true,
219                             /*CreateMissingDirectories=*/true);
220}
221
222bool GenerateModuleInterfaceAction::BeginSourceFileAction(
223    CompilerInstance &CI) {
224  if (!CI.getLangOpts().ModulesTS) {
225    CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts);
226    return false;
227  }
228
229  CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
230
231  return GenerateModuleAction::BeginSourceFileAction(CI);
232}
233
234std::unique_ptr<raw_pwrite_stream>
235GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
236                                                StringRef InFile) {
237  return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
238}
239
240bool GenerateHeaderModuleAction::PrepareToExecuteAction(
241    CompilerInstance &CI) {
242  if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) {
243    CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
244    return false;
245  }
246
247  auto &Inputs = CI.getFrontendOpts().Inputs;
248  if (Inputs.empty())
249    return GenerateModuleAction::BeginInvocation(CI);
250
251  auto Kind = Inputs[0].getKind();
252
253  // Convert the header file inputs into a single module input buffer.
254  SmallString<256HeaderContents;
255  ModuleHeaders.reserve(Inputs.size());
256  for (const FrontendInputFile &FIF : Inputs) {
257    // FIXME: We should support re-compiling from an AST file.
258    if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
259      CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
260          << (FIF.isFile() ? FIF.getFile()
261                           : FIF.getBuffer()->getBufferIdentifier());
262      return true;
263    }
264
265    HeaderContents += "#include \"";
266    HeaderContents += FIF.getFile();
267    HeaderContents += "\"\n";
268    ModuleHeaders.push_back(FIF.getFile());
269  }
270  Buffer = llvm::MemoryBuffer::getMemBufferCopy(
271      HeaderContents, Module::getModuleInputBufferName());
272
273  // Set that buffer up as our "real" input.
274  Inputs.clear();
275  Inputs.push_back(FrontendInputFile(Buffer.get(), Kind/*IsSystem*/false));
276
277  return GenerateModuleAction::PrepareToExecuteAction(CI);
278}
279
280bool GenerateHeaderModuleAction::BeginSourceFileAction(
281    CompilerInstance &CI) {
282  CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule);
283
284  // Synthesize a Module object for the given headers.
285  auto &HS = CI.getPreprocessor().getHeaderSearchInfo();
286  SmallVector<Module::Header16Headers;
287  for (StringRef Name : ModuleHeaders) {
288    const DirectoryLookup *CurDir = nullptr;
289    const FileEntry *FE = HS.LookupFile(
290        Name, SourceLocation(), /*Angled*/ falsenullptr, CurDir,
291        None, nullptrnullptrnullptrnullptrnullptrnullptr);
292    if (!FE) {
293      CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
294        << Name;
295      continue;
296    }
297    Headers.push_back({Name, FE});
298  }
299  HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
300
301  return GenerateModuleAction::BeginSourceFileAction(CI);
302}
303
304std::unique_ptr<raw_pwrite_stream>
305GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
306                                             StringRef InFile) {
307  return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
308}
309
310SyntaxOnlyAction::~SyntaxOnlyAction() {
311}
312
313std::unique_ptr<ASTConsumer>
314SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
315  return llvm::make_unique<ASTConsumer>();
316}
317
318std::unique_ptr<ASTConsumer>
319DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
320                                        StringRef InFile) {
321  return llvm::make_unique<ASTConsumer>();
322}
323
324std::unique_ptr<ASTConsumer>
325VerifyPCHAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
326  return llvm::make_unique<ASTConsumer>();
327}
328
329void VerifyPCHAction::ExecuteAction() {
330  CompilerInstance &CI = getCompilerInstance();
331  bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
332  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
333  std::unique_ptr<ASTReaderReader(new ASTReader(
334      CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(),
335      CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions,
336      Sysroot.empty() ? "" : Sysroot.c_str(),
337      /*DisableValidation*/ false,
338      /*AllowPCHWithCompilerErrors*/ false,
339      /*AllowConfigurationMismatch*/ true,
340      /*ValidateSystemInputs*/ true));
341
342  Reader->ReadAST(getCurrentFile(),
343                  Preamble ? serialization::MK_Preamble
344                           : serialization::MK_PCH,
345                  SourceLocation(),
346                  ASTReader::ARR_ConfigurationMismatch);
347}
348
349namespace {
350struct TemplightEntry {
351  std::string Name;
352  std::string Kind;
353  std::string Event;
354  std::string DefinitionLocation;
355  std::string PointOfInstantiation;
356};
357// namespace
358
359namespace llvm {
360namespace yaml {
361template <> struct MappingTraits<TemplightEntry> {
362  static void mapping(IO &ioTemplightEntry &fields) {
363    io.mapRequired("name", fields.Name);
364    io.mapRequired("kind", fields.Kind);
365    io.mapRequired("event", fields.Event);
366    io.mapRequired("orig", fields.DefinitionLocation);
367    io.mapRequired("poi", fields.PointOfInstantiation);
368  }
369};
370// namespace yaml
371// namespace llvm
372
373namespace {
374class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
375  using CodeSynthesisContext = Sema::CodeSynthesisContext;
376
377public:
378  void initialize(const Sema &) override {}
379
380  void finalize(const Sema &) override {}
381
382  void atTemplateBegin(const Sema &TheSema,
383                       const CodeSynthesisContext &Inst) override {
384    displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
385  }
386
387  void atTemplateEnd(const Sema &TheSema,
388                     const CodeSynthesisContext &Inst) override {
389    displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
390  }
391
392private:
393  static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
394    switch (Kind) {
395    case CodeSynthesisContext::TemplateInstantiation:
396      return "TemplateInstantiation";
397    case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
398      return "DefaultTemplateArgumentInstantiation";
399    case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
400      return "DefaultFunctionArgumentInstantiation";
401    case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
402      return "ExplicitTemplateArgumentSubstitution";
403    case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
404      return "DeducedTemplateArgumentSubstitution";
405    case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
406      return "PriorTemplateArgumentSubstitution";
407    case CodeSynthesisContext::DefaultTemplateArgumentChecking:
408      return "DefaultTemplateArgumentChecking";
409    case CodeSynthesisContext::ExceptionSpecEvaluation:
410      return "ExceptionSpecEvaluation";
411    case CodeSynthesisContext::ExceptionSpecInstantiation:
412      return "ExceptionSpecInstantiation";
413    case CodeSynthesisContext::DeclaringSpecialMember:
414      return "DeclaringSpecialMember";
415    case CodeSynthesisContext::DefiningSynthesizedFunction:
416      return "DefiningSynthesizedFunction";
417    case CodeSynthesisContext::Memoization:
418      return "Memoization";
419    }
420    return "";
421  }
422
423  template <bool BeginInstantiation>
424  static void displayTemplightEntry(llvm::raw_ostream &Outconst Sema &TheSema,
425                                    const CodeSynthesisContext &Inst) {
426    std::string YAML;
427    {
428      llvm::raw_string_ostream OS(YAML);
429      llvm::yaml::Output YO(OS);
430      TemplightEntry Entry =
431          getTemplightEntry<BeginInstantiation>(TheSemaInst);
432      llvm::yaml::EmptyContext Context;
433      llvm::yaml::yamlize(YO, Entry, true, Context);
434    }
435    Out << "---" << YAML << "\n";
436  }
437
438  template <bool BeginInstantiation>
439  static TemplightEntry getTemplightEntry(const Sema &TheSema,
440                                          const CodeSynthesisContext &Inst) {
441    TemplightEntry Entry;
442    Entry.Kind = toString(Inst.Kind);
443    Entry.Event = BeginInstantiation ? "Begin" : "End";
444    if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) {
445      llvm::raw_string_ostream OS(Entry.Name);
446      NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
447      const PresumedLoc DefLoc =
448        TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
449      if(!DefLoc.isInvalid())
450        Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
451                                   std::to_string(DefLoc.getLine()) + ":" +
452                                   std::to_string(DefLoc.getColumn());
453    }
454    const PresumedLoc PoiLoc =
455        TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
456    if (!PoiLoc.isInvalid()) {
457      Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
458                                   std::to_string(PoiLoc.getLine()) + ":" +
459                                   std::to_string(PoiLoc.getColumn());
460    }
461    return Entry;
462  }
463};
464// namespace
465
466std::unique_ptr<ASTConsumer>
467TemplightDumpAction::CreateASTConsumer(CompilerInstance &CIStringRef InFile) {
468  return llvm::make_unique<ASTConsumer>();
469}
470
471void TemplightDumpAction::ExecuteAction() {
472  CompilerInstance &CI = getCompilerInstance();
473
474  // This part is normally done by ASTFrontEndAction, but needs to happen
475  // before Templight observers can be created
476  // FIXME: Move the truncation aspect of this into Sema, we delayed this till
477  // here so the source manager would be initialized.
478  EnsureSemaIsCreated(CI, *this);
479
480  CI.getSema().TemplateInstCallbacks.push_back(
481      llvm::make_unique<DefaultTemplateInstCallback>());
482  ASTFrontendAction::ExecuteAction();
483}
484
485namespace {
486  /// AST reader listener that dumps module information for a module
487  /// file.
488  class DumpModuleInfoListener : public ASTReaderListener {
489    llvm::raw_ostream &Out;
490
491  public:
492    DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
493
494#define DUMP_BOOLEAN(Value, Text)                       \
495    Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
496
497    bool ReadFullVersionInformation(StringRef FullVersion) override {
498      Out.indent(2)
499        << "Generated by "
500        << (FullVersion == getClangFullRepositoryVersion()? "this"
501                                                          : "a different")
502        << " Clang: " << FullVersion << "\n";
503      return ASTReaderListener::ReadFullVersionInformation(FullVersion);
504    }
505
506    void ReadModuleName(StringRef ModuleName) override {
507      Out.indent(2) << "Module name: " << ModuleName << "\n";
508    }
509    void ReadModuleMapFile(StringRef ModuleMapPath) override {
510      Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
511    }
512
513    bool ReadLanguageOptions(const LangOptions &LangOptsbool Complain,
514                             bool AllowCompatibleDifferences) override {
515      Out.indent(2) << "Language options:\n";
516#define LANGOPT(Name, Bits, Default, Description) \
517      DUMP_BOOLEAN(LangOpts.Name, Description);
518#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
519      Out.indent(4) << Description << ": "                   \
520                    << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
521#define VALUE_LANGOPT(Name, Bits, Default, Description) \
522      Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
523#define BENIGN_LANGOPT(Name, Bits, Default, Description)
524#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
525#include "clang/Basic/LangOptions.def"
526
527      if (!LangOpts.ModuleFeatures.empty()) {
528        Out.indent(4) << "Module features:\n";
529        for (StringRef Feature : LangOpts.ModuleFeatures)
530          Out.indent(6) << Feature << "\n";
531      }
532
533      return false;
534    }
535
536    bool ReadTargetOptions(const TargetOptions &TargetOptsbool Complain,
537                           bool AllowCompatibleDifferences) override {
538      Out.indent(2) << "Target options:\n";
539      Out.indent(4) << "  Triple: " << TargetOpts.Triple << "\n";
540      Out.indent(4) << "  CPU: " << TargetOpts.CPU << "\n";
541      Out.indent(4) << "  ABI: " << TargetOpts.ABI << "\n";
542
543      if (!TargetOpts.FeaturesAsWritten.empty()) {
544        Out.indent(4) << "Target features:\n";
545        for (unsigned I = 0N = TargetOpts.FeaturesAsWritten.size();
546             I != N; ++I) {
547          Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
548        }
549      }
550
551      return false;
552    }
553
554    bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptionsDiagOpts,
555                               bool Complain) override {
556      Out.indent(2) << "Diagnostic options:\n";
557#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
558#define ENUM_DIAGOPT(Name, Type, Bits, Default) \
559      Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n";
560#define VALUE_DIAGOPT(Name, Bits, Default) \
561      Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";
562#include "clang/Basic/DiagnosticOptions.def"
563
564      Out.indent(4) << "Diagnostic flags:\n";
565      for (const std::string &Warning : DiagOpts->Warnings)
566        Out.indent(6) << "-W" << Warning << "\n";
567      for (const std::string &Remark : DiagOpts->Remarks)
568        Out.indent(6) << "-R" << Remark << "\n";
569
570      return false;
571    }
572
573    bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
574                                 StringRef SpecificModuleCachePath,
575                                 bool Complain) override {
576      Out.indent(2) << "Header search options:\n";
577      Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
578      Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n";
579      Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
580      DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
581                   "Use builtin include directories [-nobuiltininc]");
582      DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
583                   "Use standard system include directories [-nostdinc]");
584      DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
585                   "Use standard C++ include directories [-nostdinc++]");
586      DUMP_BOOLEAN(HSOpts.UseLibcxx,
587                   "Use libc++ (rather than libstdc++) [-stdlib=]");
588      return false;
589    }
590
591    bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
592                                 bool Complain,
593                                 std::string &SuggestedPredefines) override {
594      Out.indent(2) << "Preprocessor options:\n";
595      DUMP_BOOLEAN(PPOpts.UsePredefines,
596                   "Uses compiler/target-specific predefines [-undef]");
597      DUMP_BOOLEAN(PPOpts.DetailedRecord,
598                   "Uses detailed preprocessing record (for indexing)");
599
600      if (!PPOpts.Macros.empty()) {
601        Out.indent(4) << "Predefined macros:\n";
602      }
603
604      for (std::vector<std::pair<std::stringbool/*isUndef*/> >::const_iterator
605             I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
606           I != IEnd; ++I) {
607        Out.indent(6);
608        if (I->second)
609          Out << "-U";
610        else
611          Out << "-D";
612        Out << I->first << "\n";
613      }
614      return false;
615    }
616
617    /// Indicates that a particular module file extension has been read.
618    void readModuleFileExtension(
619           const ModuleFileExtensionMetadata &Metadata) override {
620      Out.indent(2) << "Module file extension '"
621                    << Metadata.BlockName << "' " << Metadata.MajorVersion
622                    << "." << Metadata.MinorVersion;
623      if (!Metadata.UserInfo.empty()) {
624        Out << ": ";
625        Out.write_escaped(Metadata.UserInfo);
626      }
627
628      Out << "\n";
629    }
630
631    /// Tells the \c ASTReaderListener that we want to receive the
632    /// input files of the AST file via \c visitInputFile.
633    bool needsInputFileVisitation() override { return true; }
634
635    /// Tells the \c ASTReaderListener that we want to receive the
636    /// input files of the AST file via \c visitInputFile.
637    bool needsSystemInputFileVisitation() override { return true; }
638
639    /// Indicates that the AST file contains particular input file.
640    ///
641    /// \returns true to continue receiving the next input file, false to stop.
642    bool visitInputFile(StringRef Filenamebool isSystem,
643                        bool isOverriddenbool isExplicitModule) override {
644
645      Out.indent(2) << "Input file: " << Filename;
646
647      if (isSystem || isOverridden || isExplicitModule) {
648        Out << " [";
649        if (isSystem) {
650          Out << "System";
651          if (isOverridden || isExplicitModule)
652            Out << ", ";
653        }
654        if (isOverridden) {
655          Out << "Overridden";
656          if (isExplicitModule)
657            Out << ", ";
658        }
659        if (isExplicitModule)
660          Out << "ExplicitModule";
661
662        Out << "]";
663      }
664
665      Out << "\n";
666
667      return true;
668    }
669
670    /// Returns true if this \c ASTReaderListener wants to receive the
671    /// imports of the AST file via \c visitImport, false otherwise.
672    bool needsImportVisitation() const override { return true; }
673
674    /// If needsImportVisitation returns \c true, this is called for each
675    /// AST file imported by this AST file.
676    void visitImport(StringRef ModuleNameStringRef Filename) override {
677      Out.indent(2) << "Imports module '" << ModuleName
678                    << "': " << Filename.str() << "\n";
679    }
680#undef DUMP_BOOLEAN
681  };
682}
683
684bool DumpModuleInfoAction::BeginInvocation(CompilerInstance &CI) {
685  // The Object file reader also supports raw ast files and there is no point in
686  // being strict about the module file format in -module-file-info mode.
687  CI.getHeaderSearchOpts().ModuleFormat = "obj";
688  return true;
689}
690
691void DumpModuleInfoAction::ExecuteAction() {
692  // Set up the output file.
693  std::unique_ptr<llvm::raw_fd_ostreamOutFile;
694  StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
695  if (!OutputFileName.empty() && OutputFileName != "-") {
696    std::error_code EC;
697    OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
698                                           llvm::sys::fs::F_Text));
699  }
700  llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
701
702  Out << "Information for module file '" << getCurrentFile() << "':\n";
703  auto &FileMgr = getCompilerInstance().getFileManager();
704  auto Buffer = FileMgr.getBufferForFile(getCurrentFile());
705  StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();
706  bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C' && Magic[1] == 'P' &&
707                Magic[2] == 'C' && Magic[3] == 'H');
708  Out << "  Module format: " << (IsRaw ? "raw" : "obj") << "\n";
709
710  Preprocessor &PP = getCompilerInstance().getPreprocessor();
711  DumpModuleInfoListener Listener(Out);
712  HeaderSearchOptions &HSOpts =
713      PP.getHeaderSearchInfo().getHeaderSearchOpts();
714  ASTReader::readASTFileControlBlock(
715      getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(),
716      /*FindModuleFileExtensions=*/true, Listener,
717      HSOpts.ModulesValidateDiagnosticOptions);
718}
719
720//===----------------------------------------------------------------------===//
721// Preprocessor Actions
722//===----------------------------------------------------------------------===//
723
724void DumpRawTokensAction::ExecuteAction() {
725  Preprocessor &PP = getCompilerInstance().getPreprocessor();
726  SourceManager &SM = PP.getSourceManager();
727
728  // Start lexing the specified input file.
729  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
730  Lexer RawLex(SM.getMainFileID(), FromFileSMPP.getLangOpts());
731  RawLex.SetKeepWhitespaceMode(true);
732
733  Token RawTok;
734  RawLex.LexFromRawLexer(RawTok);
735  while (RawTok.isNot(tok::eof)) {
736    PP.DumpToken(RawToktrue);
737    llvm::errs() << "\n";
738    RawLex.LexFromRawLexer(RawTok);
739  }
740}
741
742void DumpTokensAction::ExecuteAction() {
743  Preprocessor &PP = getCompilerInstance().getPreprocessor();
744  // Start preprocessing the specified input file.
745  Token Tok;
746  PP.EnterMainSourceFile();
747  do {
748    PP.Lex(Tok);
749    PP.DumpToken(Toktrue);
750    llvm::errs() << "\n";
751  } while (Tok.isNot(tok::eof));
752}
753
754void PreprocessOnlyAction::ExecuteAction() {
755  Preprocessor &PP = getCompilerInstance().getPreprocessor();
756
757  // Ignore unknown pragmas.
758  PP.IgnorePragmas();
759
760  Token Tok;
761  // Start parsing the specified input file.
762  PP.EnterMainSourceFile();
763  do {
764    PP.Lex(Tok);
765  } while (Tok.isNot(tok::eof));
766}
767
768void PrintPreprocessedAction::ExecuteAction() {
769  CompilerInstance &CI = getCompilerInstance();
770  // Output file may need to be set to 'Binary', to avoid converting Unix style
771  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
772  //
773  // Look to see what type of line endings the file uses. If there's a
774  // CRLF, then we won't open the file up in binary mode. If there is
775  // just an LF or CR, then we will open the file up in binary mode.
776  // In this fashion, the output format should match the input format, unless
777  // the input format has inconsistent line endings.
778  //
779  // This should be a relatively fast operation since most files won't have
780  // all of their source code on a single line. However, that is still a
781  // concern, so if we scan for too long, we'll just assume the file should
782  // be opened in binary mode.
783  bool BinaryMode = true;
784  bool InvalidFile = false;
785  const SourceManagerSM = CI.getSourceManager();
786  const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
787                                                     &InvalidFile);
788  if (!InvalidFile) {
789    const char *cur = Buffer->getBufferStart();
790    const char *end = Buffer->getBufferEnd();
791    const char *next = (cur != end) ? cur + 1 : end;
792
793    // Limit ourselves to only scanning 256 characters into the source
794    // file.  This is mostly a sanity check in case the file has no
795    // newlines whatsoever.
796    if (end - cur > 256end = cur + 256;
797
798    while (next < end) {
799      if (*cur == 0x0D) {  // CR
800        if (*next == 0x0A)  // CRLF
801          BinaryMode = false;
802
803        break;
804      } else if (*cur == 0x0A)  // LF
805        break;
806
807      ++cur;
808      ++next;
809    }
810  }
811
812  std::unique_ptr<raw_ostreamOS =
813      CI.createDefaultOutputFile(BinaryMode, getCurrentFileOrBufferName());
814  if (!OSreturn;
815
816  // If we're preprocessing a module map, start by dumping the contents of the
817  // module itself before switching to the input buffer.
818  auto &Input = getCurrentInput();
819  if (Input.getKind().getFormat() == InputKind::ModuleMap) {
820    if (Input.isFile()) {
821      (*OS) << "# 1 \"";
822      OS->write_escaped(Input.getFile());
823      (*OS) << "\"\n";
824    }
825    getCurrentModule()->print(*OS);
826    (*OS) << "#pragma clang module contents\n";
827  }
828
829  DoPrintPreprocessedInput(CI.getPreprocessor()OS.get(),
830                           CI.getPreprocessorOutputOpts());
831}
832
833void PrintPreambleAction::ExecuteAction() {
834  switch (getCurrentFileKind().getLanguage()) {
835  case InputKind::C:
836  case InputKind::CXX:
837  case InputKind::ObjC:
838  case InputKind::ObjCXX:
839  case InputKind::OpenCL:
840  case InputKind::CUDA:
841  case InputKind::HIP:
842    break;
843
844  case InputKind::Unknown:
845  case InputKind::Asm:
846  case InputKind::LLVM_IR:
847  case InputKind::RenderScript:
848    // We can't do anything with these.
849    return;
850  }
851
852  // We don't expect to find any #include directives in a preprocessed input.
853  if (getCurrentFileKind().isPreprocessed())
854    return;
855
856  CompilerInstance &CI = getCompilerInstance();
857  auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
858  if (Buffer) {
859    unsigned Preamble =
860        Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;
861    llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
862  }
863}
864
865void DumpCompilerOptionsAction::ExecuteAction() {
866  CompilerInstance &CI = getCompilerInstance();
867  std::unique_ptr<raw_ostreamOSP =
868      CI.createDefaultOutputFile(false, getCurrentFile());
869  if (!OSP)
870    return;
871
872  raw_ostream &OS = *OSP;
873  const Preprocessor &PP = CI.getPreprocessor();
874  const LangOptions &LangOpts = PP.getLangOpts();
875
876  // FIXME: Rather than manually format the JSON (which is awkward due to
877  // needing to remove trailing commas), this should make use of a JSON library.
878  // FIXME: Instead of printing enums as an integral value and specifying the
879  // type as a separate field, use introspection to print the enumerator.
880
881  OS << "{\n";
882  OS << "\n\"features\" : [\n";
883  {
884    llvm::SmallString<128Str;
885#define FEATURE(Name, Predicate)                                               \
886  ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
887      .toVector(Str);
888#include "clang/Basic/Features.def"
889#undef FEATURE
890    // Remove the newline and comma from the last entry to ensure this remains
891    // valid JSON.
892    OS << Str.substr(0, Str.size() - 2);
893  }
894  OS << "\n],\n";
895
896  OS << "\n\"extensions\" : [\n";
897  {
898    llvm::SmallString<128Str;
899#define EXTENSION(Name, Predicate)                                             \
900  ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
901      .toVector(Str);
902#include "clang/Basic/Features.def"
903#undef EXTENSION
904    // Remove the newline and comma from the last entry to ensure this remains
905    // valid JSON.
906    OS << Str.substr(0, Str.size() - 2);
907  }
908  OS << "\n]\n";
909
910  OS << "}";
911}
912
clang::InitOnlyAction::CreateASTConsumer
clang::InitOnlyAction::ExecuteAction
clang::ASTPrintAction::CreateASTConsumer
clang::ASTDumpAction::CreateASTConsumer
clang::ASTDeclListAction::CreateASTConsumer
clang::ASTViewAction::CreateASTConsumer
clang::GeneratePCHAction::CreateASTConsumer
clang::GeneratePCHAction::ComputeASTConsumerArguments
clang::GeneratePCHAction::CreateOutputFile
clang::GeneratePCHAction::shouldEraseOutputFiles
clang::GeneratePCHAction::BeginSourceFileAction
clang::GenerateModuleAction::CreateASTConsumer
clang::GenerateModuleFromModuleMapAction::BeginSourceFileAction
clang::GenerateModuleFromModuleMapAction::CreateOutputFile
clang::GenerateModuleInterfaceAction::BeginSourceFileAction
clang::GenerateModuleInterfaceAction::CreateOutputFile
clang::GenerateHeaderModuleAction::PrepareToExecuteAction
clang::GenerateHeaderModuleAction::BeginSourceFileAction
clang::GenerateHeaderModuleAction::CreateOutputFile
clang::SyntaxOnlyAction::CreateASTConsumer
clang::DumpModuleInfoAction::CreateASTConsumer
clang::VerifyPCHAction::CreateASTConsumer
clang::VerifyPCHAction::ExecuteAction
clang::TemplightDumpAction::CreateASTConsumer
clang::TemplightDumpAction::ExecuteAction
clang::DumpModuleInfoAction::BeginInvocation
clang::DumpModuleInfoAction::ExecuteAction
clang::DumpRawTokensAction::ExecuteAction
clang::DumpTokensAction::ExecuteAction
clang::PreprocessOnlyAction::ExecuteAction
clang::PrintPreprocessedAction::ExecuteAction
clang::PrintPreambleAction::ExecuteAction
clang::DumpCompilerOptionsAction::ExecuteAction