clang  9.0.0svn
FrontendActions.cpp
Go to the documentation of this file.
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 
10 #include "clang/AST/ASTConsumer.h"
16 #include "clang/Frontend/Utils.h"
17 #include "clang/Lex/HeaderSearch.h"
18 #include "clang/Lex/Preprocessor.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 
31 using namespace clang;
32 
33 namespace {
34 CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) {
36  : nullptr;
37 }
38 
39 void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) {
40  if (Action.hasCodeCompletionSupport() &&
43 
44  if (!CI.hasSema())
46  GetCodeCompletionConsumer(CI));
47 }
48 } // namespace
49 
50 //===----------------------------------------------------------------------===//
51 // Custom Actions
52 //===----------------------------------------------------------------------===//
53 
54 std::unique_ptr<ASTConsumer>
55 InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
56  return llvm::make_unique<ASTConsumer>();
57 }
58 
59 void InitOnlyAction::ExecuteAction() {
60 }
61 
62 //===----------------------------------------------------------------------===//
63 // AST Consumer Actions
64 //===----------------------------------------------------------------------===//
65 
66 std::unique_ptr<ASTConsumer>
68  if (std::unique_ptr<raw_ostream> OS =
69  CI.createDefaultOutputFile(false, InFile))
70  return CreateASTPrinter(std::move(OS), CI.getFrontendOpts().ASTDumpFilter);
71  return nullptr;
72 }
73 
74 std::unique_ptr<ASTConsumer>
76  return CreateASTDumper(nullptr /*Dump to stdout.*/,
81 }
82 
83 std::unique_ptr<ASTConsumer>
85  return CreateASTDeclNodeLister();
86 }
87 
88 std::unique_ptr<ASTConsumer>
90  return CreateASTViewer();
91 }
92 
93 std::unique_ptr<ASTConsumer>
95  std::string Sysroot;
96  if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot))
97  return nullptr;
98 
99  std::string OutputFile;
100  std::unique_ptr<raw_pwrite_stream> OS =
101  CreateOutputFile(CI, InFile, /*ref*/ OutputFile);
102  if (!OS)
103  return nullptr;
104 
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(), OutputFile, Sysroot,
113  Buffer, FrontendOpts.ModuleFileExtensions,
115  FrontendOpts.IncludeTimestamps));
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 
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 
133 std::unique_ptr<llvm::raw_pwrite_stream>
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_stream> OS =
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 
151  if (getCompilerInstance().getPreprocessorOpts().AllowPCHWithCompilerErrors)
152  return false;
154 }
155 
157  CI.getLangOpts().CompilingPCH = true;
158  return true;
159 }
160 
161 std::unique_ptr<ASTConsumer>
163  StringRef InFile) {
164  std::unique_ptr<raw_pwrite_stream> OS = 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(), OutputFile, Sysroot,
177  /*AllowASTWithErrors=*/false,
178  /*IncludeTimestamps=*/
180  Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
181  CI, InFile, OutputFile, std::move(OS), Buffer));
182  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
183 }
184 
185 bool GenerateModuleFromModuleMapAction::BeginSourceFileAction(
186  CompilerInstance &CI) {
187  if (!CI.getLangOpts().Modules) {
188  CI.getDiagnostics().Report(diag::err_module_build_requires_fmodules);
189  return false;
190  }
191 
193 }
194 
195 std::unique_ptr<raw_pwrite_stream>
196 GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI,
197  StringRef InFile) {
198  // If no output file was provided, figure out where this module would go
199  // in the module cache.
200  if (CI.getFrontendOpts().OutputFile.empty()) {
201  StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap;
202  if (ModuleMapFile.empty())
203  ModuleMapFile = InFile;
204 
208  ModuleMapFile);
209  }
210 
211  // We use createOutputFile here because this is exposed via libclang, and we
212  // must disable the RemoveFileOnSignal behavior.
213  // We use a temporary to avoid race conditions.
214  return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
215  /*RemoveFileOnSignal=*/false, InFile,
216  /*Extension=*/"", /*useTemporary=*/true,
217  /*CreateMissingDirectories=*/true);
218 }
219 
220 bool GenerateModuleInterfaceAction::BeginSourceFileAction(
221  CompilerInstance &CI) {
222  if (!CI.getLangOpts().ModulesTS) {
223  CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts);
224  return false;
225  }
226 
227  CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleInterface);
228 
230 }
231 
232 std::unique_ptr<raw_pwrite_stream>
233 GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
234  StringRef InFile) {
235  return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
236 }
237 
238 bool GenerateHeaderModuleAction::PrepareToExecuteAction(
239  CompilerInstance &CI) {
240  if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) {
241  CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
242  return false;
243  }
244 
245  auto &Inputs = CI.getFrontendOpts().Inputs;
246  if (Inputs.empty())
248 
249  auto Kind = Inputs[0].getKind();
250 
251  // Convert the header file inputs into a single module input buffer.
252  SmallString<256> HeaderContents;
253  ModuleHeaders.reserve(Inputs.size());
254  for (const FrontendInputFile &FIF : Inputs) {
255  // FIXME: We should support re-compiling from an AST file.
256  if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
257  CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
258  << (FIF.isFile() ? FIF.getFile()
259  : FIF.getBuffer()->getBufferIdentifier());
260  return true;
261  }
262 
263  HeaderContents += "#include \"";
264  HeaderContents += FIF.getFile();
265  HeaderContents += "\"\n";
266  ModuleHeaders.push_back(FIF.getFile());
267  }
268  Buffer = llvm::MemoryBuffer::getMemBufferCopy(
269  HeaderContents, Module::getModuleInputBufferName());
270 
271  // Set that buffer up as our "real" input.
272  Inputs.clear();
273  Inputs.push_back(FrontendInputFile(Buffer.get(), Kind, /*IsSystem*/false));
274 
276 }
277 
278 bool GenerateHeaderModuleAction::BeginSourceFileAction(
279  CompilerInstance &CI) {
280  CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule);
281 
282  // Synthesize a Module object for the given headers.
283  auto &HS = CI.getPreprocessor().getHeaderSearchInfo();
285  for (StringRef Name : ModuleHeaders) {
286  const DirectoryLookup *CurDir = nullptr;
287  const FileEntry *FE = HS.LookupFile(
288  Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir,
289  None, nullptr, nullptr, nullptr, nullptr, nullptr);
290  if (!FE) {
291  CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
292  << Name;
293  continue;
294  }
295  Headers.push_back({Name, FE});
296  }
297  HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
298 
300 }
301 
302 std::unique_ptr<raw_pwrite_stream>
303 GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
304  StringRef InFile) {
305  return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
306 }
307 
309 }
310 
311 std::unique_ptr<ASTConsumer>
313  return llvm::make_unique<ASTConsumer>();
314 }
315 
316 std::unique_ptr<ASTConsumer>
318  StringRef InFile) {
319  return llvm::make_unique<ASTConsumer>();
320 }
321 
322 std::unique_ptr<ASTConsumer>
324  return llvm::make_unique<ASTConsumer>();
325 }
326 
330  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
331  std::unique_ptr<ASTReader> Reader(new ASTReader(
334  Sysroot.empty() ? "" : Sysroot.c_str(),
335  /*DisableValidation*/ false,
336  /*AllowPCHWithCompilerErrors*/ false,
337  /*AllowConfigurationMismatch*/ true,
338  /*ValidateSystemInputs*/ true));
339 
340  Reader->ReadAST(getCurrentFile(),
341  Preamble ? serialization::MK_Preamble
343  SourceLocation(),
345 }
346 
347 namespace {
348 struct TemplightEntry {
349  std::string Name;
350  std::string Kind;
351  std::string Event;
352  std::string DefinitionLocation;
353  std::string PointOfInstantiation;
354 };
355 } // namespace
356 
357 namespace llvm {
358 namespace yaml {
359 template <> struct MappingTraits<TemplightEntry> {
360  static void mapping(IO &io, TemplightEntry &fields) {
361  io.mapRequired("name", fields.Name);
362  io.mapRequired("kind", fields.Kind);
363  io.mapRequired("event", fields.Event);
364  io.mapRequired("orig", fields.DefinitionLocation);
365  io.mapRequired("poi", fields.PointOfInstantiation);
366  }
367 };
368 } // namespace yaml
369 } // namespace llvm
370 
371 namespace {
372 class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
373  using CodeSynthesisContext = Sema::CodeSynthesisContext;
374 
375 public:
376  void initialize(const Sema &) override {}
377 
378  void finalize(const Sema &) override {}
379 
380  void atTemplateBegin(const Sema &TheSema,
381  const CodeSynthesisContext &Inst) override {
382  displayTemplightEntry<true>(llvm::outs(), TheSema, Inst);
383  }
384 
385  void atTemplateEnd(const Sema &TheSema,
386  const CodeSynthesisContext &Inst) override {
387  displayTemplightEntry<false>(llvm::outs(), TheSema, Inst);
388  }
389 
390 private:
391  static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
392  switch (Kind) {
393  case CodeSynthesisContext::TemplateInstantiation:
394  return "TemplateInstantiation";
395  case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
396  return "DefaultTemplateArgumentInstantiation";
397  case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
398  return "DefaultFunctionArgumentInstantiation";
399  case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
400  return "ExplicitTemplateArgumentSubstitution";
401  case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
402  return "DeducedTemplateArgumentSubstitution";
403  case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
404  return "PriorTemplateArgumentSubstitution";
405  case CodeSynthesisContext::DefaultTemplateArgumentChecking:
406  return "DefaultTemplateArgumentChecking";
407  case CodeSynthesisContext::ExceptionSpecEvaluation:
408  return "ExceptionSpecEvaluation";
409  case CodeSynthesisContext::ExceptionSpecInstantiation:
410  return "ExceptionSpecInstantiation";
411  case CodeSynthesisContext::DeclaringSpecialMember:
412  return "DeclaringSpecialMember";
413  case CodeSynthesisContext::DefiningSynthesizedFunction:
414  return "DefiningSynthesizedFunction";
415  case CodeSynthesisContext::Memoization:
416  return "Memoization";
417  }
418  return "";
419  }
420 
421  template <bool BeginInstantiation>
422  static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema,
423  const CodeSynthesisContext &Inst) {
424  std::string YAML;
425  {
426  llvm::raw_string_ostream OS(YAML);
427  llvm::yaml::Output YO(OS);
428  TemplightEntry Entry =
429  getTemplightEntry<BeginInstantiation>(TheSema, Inst);
430  llvm::yaml::EmptyContext Context;
431  llvm::yaml::yamlize(YO, Entry, true, Context);
432  }
433  Out << "---" << YAML << "\n";
434  }
435 
436  template <bool BeginInstantiation>
437  static TemplightEntry getTemplightEntry(const Sema &TheSema,
438  const CodeSynthesisContext &Inst) {
439  TemplightEntry Entry;
440  Entry.Kind = toString(Inst.Kind);
441  Entry.Event = BeginInstantiation ? "Begin" : "End";
442  if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) {
443  llvm::raw_string_ostream OS(Entry.Name);
444  NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true);
445  const PresumedLoc DefLoc =
446  TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation());
447  if(!DefLoc.isInvalid())
448  Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" +
449  std::to_string(DefLoc.getLine()) + ":" +
450  std::to_string(DefLoc.getColumn());
451  }
452  const PresumedLoc PoiLoc =
453  TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation);
454  if (!PoiLoc.isInvalid()) {
455  Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" +
456  std::to_string(PoiLoc.getLine()) + ":" +
457  std::to_string(PoiLoc.getColumn());
458  }
459  return Entry;
460  }
461 };
462 } // namespace
463 
464 std::unique_ptr<ASTConsumer>
466  return llvm::make_unique<ASTConsumer>();
467 }
468 
471 
472  // This part is normally done by ASTFrontEndAction, but needs to happen
473  // before Templight observers can be created
474  // FIXME: Move the truncation aspect of this into Sema, we delayed this till
475  // here so the source manager would be initialized.
476  EnsureSemaIsCreated(CI, *this);
477 
478  CI.getSema().TemplateInstCallbacks.push_back(
479  llvm::make_unique<DefaultTemplateInstCallback>());
481 }
482 
483 namespace {
484  /// AST reader listener that dumps module information for a module
485  /// file.
486  class DumpModuleInfoListener : public ASTReaderListener {
487  llvm::raw_ostream &Out;
488 
489  public:
490  DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
491 
492 #define DUMP_BOOLEAN(Value, Text) \
493  Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
494 
495  bool ReadFullVersionInformation(StringRef FullVersion) override {
496  Out.indent(2)
497  << "Generated by "
498  << (FullVersion == getClangFullRepositoryVersion()? "this"
499  : "a different")
500  << " Clang: " << FullVersion << "\n";
502  }
503 
504  void ReadModuleName(StringRef ModuleName) override {
505  Out.indent(2) << "Module name: " << ModuleName << "\n";
506  }
507  void ReadModuleMapFile(StringRef ModuleMapPath) override {
508  Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
509  }
510 
511  bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
512  bool AllowCompatibleDifferences) override {
513  Out.indent(2) << "Language options:\n";
514 #define LANGOPT(Name, Bits, Default, Description) \
515  DUMP_BOOLEAN(LangOpts.Name, Description);
516 #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
517  Out.indent(4) << Description << ": " \
518  << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
519 #define VALUE_LANGOPT(Name, Bits, Default, Description) \
520  Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
521 #define BENIGN_LANGOPT(Name, Bits, Default, Description)
522 #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
523 #include "clang/Basic/LangOptions.def"
524 
525  if (!LangOpts.ModuleFeatures.empty()) {
526  Out.indent(4) << "Module features:\n";
527  for (StringRef Feature : LangOpts.ModuleFeatures)
528  Out.indent(6) << Feature << "\n";
529  }
530 
531  return false;
532  }
533 
534  bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
535  bool AllowCompatibleDifferences) override {
536  Out.indent(2) << "Target options:\n";
537  Out.indent(4) << " Triple: " << TargetOpts.Triple << "\n";
538  Out.indent(4) << " CPU: " << TargetOpts.CPU << "\n";
539  Out.indent(4) << " ABI: " << TargetOpts.ABI << "\n";
540 
541  if (!TargetOpts.FeaturesAsWritten.empty()) {
542  Out.indent(4) << "Target features:\n";
543  for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
544  I != N; ++I) {
545  Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
546  }
547  }
548 
549  return false;
550  }
551 
552  bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
553  bool Complain) override {
554  Out.indent(2) << "Diagnostic options:\n";
555 #define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name);
556 #define ENUM_DIAGOPT(Name, Type, Bits, Default) \
557  Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n";
558 #define VALUE_DIAGOPT(Name, Bits, Default) \
559  Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n";
560 #include "clang/Basic/DiagnosticOptions.def"
561 
562  Out.indent(4) << "Diagnostic flags:\n";
563  for (const std::string &Warning : DiagOpts->Warnings)
564  Out.indent(6) << "-W" << Warning << "\n";
565  for (const std::string &Remark : DiagOpts->Remarks)
566  Out.indent(6) << "-R" << Remark << "\n";
567 
568  return false;
569  }
570 
571  bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
572  StringRef SpecificModuleCachePath,
573  bool Complain) override {
574  Out.indent(2) << "Header search options:\n";
575  Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
576  Out.indent(4) << "Resource dir [ -resource-dir=]: '" << HSOpts.ResourceDir << "'\n";
577  Out.indent(4) << "Module Cache: '" << SpecificModuleCachePath << "'\n";
579  "Use builtin include directories [-nobuiltininc]");
581  "Use standard system include directories [-nostdinc]");
583  "Use standard C++ include directories [-nostdinc++]");
584  DUMP_BOOLEAN(HSOpts.UseLibcxx,
585  "Use libc++ (rather than libstdc++) [-stdlib=]");
586  return false;
587  }
588 
589  bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
590  bool Complain,
591  std::string &SuggestedPredefines) override {
592  Out.indent(2) << "Preprocessor options:\n";
594  "Uses compiler/target-specific predefines [-undef]");
596  "Uses detailed preprocessing record (for indexing)");
597 
598  if (!PPOpts.Macros.empty()) {
599  Out.indent(4) << "Predefined macros:\n";
600  }
601 
602  for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
603  I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
604  I != IEnd; ++I) {
605  Out.indent(6);
606  if (I->second)
607  Out << "-U";
608  else
609  Out << "-D";
610  Out << I->first << "\n";
611  }
612  return false;
613  }
614 
615  /// Indicates that a particular module file extension has been read.
616  void readModuleFileExtension(
617  const ModuleFileExtensionMetadata &Metadata) override {
618  Out.indent(2) << "Module file extension '"
619  << Metadata.BlockName << "' " << Metadata.MajorVersion
620  << "." << Metadata.MinorVersion;
621  if (!Metadata.UserInfo.empty()) {
622  Out << ": ";
623  Out.write_escaped(Metadata.UserInfo);
624  }
625 
626  Out << "\n";
627  }
628 
629  /// Tells the \c ASTReaderListener that we want to receive the
630  /// input files of the AST file via \c visitInputFile.
631  bool needsInputFileVisitation() override { return true; }
632 
633  /// Tells the \c ASTReaderListener that we want to receive the
634  /// input files of the AST file via \c visitInputFile.
635  bool needsSystemInputFileVisitation() override { return true; }
636 
637  /// Indicates that the AST file contains particular input file.
638  ///
639  /// \returns true to continue receiving the next input file, false to stop.
640  bool visitInputFile(StringRef Filename, bool isSystem,
641  bool isOverridden, bool isExplicitModule) override {
642 
643  Out.indent(2) << "Input file: " << Filename;
644 
645  if (isSystem || isOverridden || isExplicitModule) {
646  Out << " [";
647  if (isSystem) {
648  Out << "System";
649  if (isOverridden || isExplicitModule)
650  Out << ", ";
651  }
652  if (isOverridden) {
653  Out << "Overridden";
654  if (isExplicitModule)
655  Out << ", ";
656  }
657  if (isExplicitModule)
658  Out << "ExplicitModule";
659 
660  Out << "]";
661  }
662 
663  Out << "\n";
664 
665  return true;
666  }
667 
668  /// Returns true if this \c ASTReaderListener wants to receive the
669  /// imports of the AST file via \c visitImport, false otherwise.
670  bool needsImportVisitation() const override { return true; }
671 
672  /// If needsImportVisitation returns \c true, this is called for each
673  /// AST file imported by this AST file.
674  void visitImport(StringRef ModuleName, StringRef Filename) override {
675  Out.indent(2) << "Imports module '" << ModuleName
676  << "': " << Filename.str() << "\n";
677  }
678 #undef DUMP_BOOLEAN
679  };
680 }
681 
683  // The Object file reader also supports raw ast files and there is no point in
684  // being strict about the module file format in -module-file-info mode.
685  CI.getHeaderSearchOpts().ModuleFormat = "obj";
686  return true;
687 }
688 
690  // Set up the output file.
691  std::unique_ptr<llvm::raw_fd_ostream> OutFile;
692  StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
693  if (!OutputFileName.empty() && OutputFileName != "-") {
694  std::error_code EC;
695  OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
696  llvm::sys::fs::F_Text));
697  }
698  llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
699 
700  Out << "Information for module file '" << getCurrentFile() << "':\n";
701  auto &FileMgr = getCompilerInstance().getFileManager();
702  auto Buffer = FileMgr.getBufferForFile(getCurrentFile());
703  StringRef Magic = (*Buffer)->getMemBufferRef().getBuffer();
704  bool IsRaw = (Magic.size() >= 4 && Magic[0] == 'C' && Magic[1] == 'P' &&
705  Magic[2] == 'C' && Magic[3] == 'H');
706  Out << " Module format: " << (IsRaw ? "raw" : "obj") << "\n";
707 
709  DumpModuleInfoListener Listener(Out);
710  HeaderSearchOptions &HSOpts =
711  PP.getHeaderSearchInfo().getHeaderSearchOpts();
713  getCurrentFile(), FileMgr, getCompilerInstance().getPCHContainerReader(),
714  /*FindModuleFileExtensions=*/true, Listener,
716 }
717 
718 //===----------------------------------------------------------------------===//
719 // Preprocessor Actions
720 //===----------------------------------------------------------------------===//
721 
725 
726  // Start lexing the specified input file.
727  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
728  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
729  RawLex.SetKeepWhitespaceMode(true);
730 
731  Token RawTok;
732  RawLex.LexFromRawLexer(RawTok);
733  while (RawTok.isNot(tok::eof)) {
734  PP.DumpToken(RawTok, true);
735  llvm::errs() << "\n";
736  RawLex.LexFromRawLexer(RawTok);
737  }
738 }
739 
742  // Start preprocessing the specified input file.
743  Token Tok;
744  PP.EnterMainSourceFile();
745  do {
746  PP.Lex(Tok);
747  PP.DumpToken(Tok, true);
748  llvm::errs() << "\n";
749  } while (Tok.isNot(tok::eof));
750 }
751 
754 
755  // Ignore unknown pragmas.
756  PP.IgnorePragmas();
757 
758  Token Tok;
759  // Start parsing the specified input file.
760  PP.EnterMainSourceFile();
761  do {
762  PP.Lex(Tok);
763  } while (Tok.isNot(tok::eof));
764 }
765 
768  // Output file may need to be set to 'Binary', to avoid converting Unix style
769  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
770  //
771  // Look to see what type of line endings the file uses. If there's a
772  // CRLF, then we won't open the file up in binary mode. If there is
773  // just an LF or CR, then we will open the file up in binary mode.
774  // In this fashion, the output format should match the input format, unless
775  // the input format has inconsistent line endings.
776  //
777  // This should be a relatively fast operation since most files won't have
778  // all of their source code on a single line. However, that is still a
779  // concern, so if we scan for too long, we'll just assume the file should
780  // be opened in binary mode.
781  bool BinaryMode = true;
782  bool InvalidFile = false;
783  const SourceManager& SM = CI.getSourceManager();
784  const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
785  &InvalidFile);
786  if (!InvalidFile) {
787  const char *cur = Buffer->getBufferStart();
788  const char *end = Buffer->getBufferEnd();
789  const char *next = (cur != end) ? cur + 1 : end;
790 
791  // Limit ourselves to only scanning 256 characters into the source
792  // file. This is mostly a sanity check in case the file has no
793  // newlines whatsoever.
794  if (end - cur > 256) end = cur + 256;
795 
796  while (next < end) {
797  if (*cur == 0x0D) { // CR
798  if (*next == 0x0A) // CRLF
799  BinaryMode = false;
800 
801  break;
802  } else if (*cur == 0x0A) // LF
803  break;
804 
805  ++cur;
806  ++next;
807  }
808  }
809 
810  std::unique_ptr<raw_ostream> OS =
812  if (!OS) return;
813 
814  // If we're preprocessing a module map, start by dumping the contents of the
815  // module itself before switching to the input buffer.
816  auto &Input = getCurrentInput();
817  if (Input.getKind().getFormat() == InputKind::ModuleMap) {
818  if (Input.isFile()) {
819  (*OS) << "# 1 \"";
820  OS->write_escaped(Input.getFile());
821  (*OS) << "\"\n";
822  }
823  getCurrentModule()->print(*OS);
824  (*OS) << "#pragma clang module contents\n";
825  }
826 
829 }
830 
832  switch (getCurrentFileKind().getLanguage()) {
833  case InputKind::C:
834  case InputKind::CXX:
835  case InputKind::ObjC:
836  case InputKind::ObjCXX:
837  case InputKind::OpenCL:
838  case InputKind::CUDA:
839  case InputKind::HIP:
840  break;
841 
842  case InputKind::Unknown:
843  case InputKind::Asm:
844  case InputKind::LLVM_IR:
846  // We can't do anything with these.
847  return;
848  }
849 
850  // We don't expect to find any #include directives in a preprocessed input.
851  if (getCurrentFileKind().isPreprocessed())
852  return;
853 
855  auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
856  if (Buffer) {
857  unsigned Preamble =
858  Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size;
859  llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
860  }
861 }
862 
863 void DumpCompilerOptionsAction::ExecuteAction() {
865  std::unique_ptr<raw_ostream> OSP =
867  if (!OSP)
868  return;
869 
870  raw_ostream &OS = *OSP;
871  const Preprocessor &PP = CI.getPreprocessor();
872  const LangOptions &LangOpts = PP.getLangOpts();
873 
874  // FIXME: Rather than manually format the JSON (which is awkward due to
875  // needing to remove trailing commas), this should make use of a JSON library.
876  // FIXME: Instead of printing enums as an integral value and specifying the
877  // type as a separate field, use introspection to print the enumerator.
878 
879  OS << "{\n";
880  OS << "\n\"features\" : [\n";
881  {
883 #define FEATURE(Name, Predicate) \
884  ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
885  .toVector(Str);
886 #include "clang/Basic/Features.def"
887 #undef FEATURE
888  // Remove the newline and comma from the last entry to ensure this remains
889  // valid JSON.
890  OS << Str.substr(0, Str.size() - 2);
891  }
892  OS << "\n],\n";
893 
894  OS << "\n\"extensions\" : [\n";
895  {
897 #define EXTENSION(Name, Predicate) \
898  ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \
899  .toVector(Str);
900 #include "clang/Basic/Features.def"
901 #undef EXTENSION
902  // Remove the newline and comma from the last entry to ensure this remains
903  // valid JSON.
904  OS << Str.substr(0, Str.size() - 2);
905  }
906  OS << "\n]\n";
907 
908  OS << "}";
909 }
std::string OutputFile
The output file, if any.
LangOptions & getLangOpts()
std::string OriginalModuleMap
When the input is a module map, the original module map file from which that map was inferred...
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
PreprocessorOptions & getPreprocessorOpts()
bool shouldEraseOutputFiles() override
Callback at the end of processing a single input, to determine if the output files should be erased o...
void createCodeCompletionConsumer()
Create a code completion consumer using the invocation; note that this will cause the source manager ...
std::vector< std::pair< std::string, bool > > Macros
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
Definition: Lexer.h:76
unsigned UseLibcxx
Use libc++ instead of the default libstdc++.
std::vector< std::unique_ptr< TemplateInstantiationCallback > > TemplateInstCallbacks
The template instantiation callbacks to trace or track instantiations (objects can be chained)...
Definition: Sema.h:7348
Defines the clang::FileManager interface and associated types.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:29
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer...
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
void createSema(TranslationUnitKind TUKind, CodeCompleteConsumer *CompletionConsumer)
Create the Sema object to be used for parsing.
Abstract base class for actions which can be performed by the frontend.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1294
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
std::string ASTDumpFilter
If given, filter dumped AST Decl nodes by this substring.
ASTContext & getASTContext() const
Compiling a C++ modules TS module interface unit.
Definition: LangOptions.h:84
void IgnorePragmas()
Install empty handlers for all pragmas (making them ignored).
Definition: Pragma.cpp:1840
Options for controlling the target.
Definition: TargetOptions.h:26
A context in which code is being synthesized (where a source location alone is not sufficient to iden...
Definition: Sema.h:7175
virtual bool hasCodeCompletionSupport() const
Does this action support use with code completion?
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static StringRef getModuleInputBufferName()
Definition: Module.h:573
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
Module * getCurrentModule() const
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
The client can handle an AST file that cannot load because it&#39;s compiled configuration doesn&#39;t match ...
Definition: ASTReader.h:1524
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
const LangOptions & getLangOpts() const
Definition: Preprocessor.h:814
unsigned BuildingImplicitModule
Whether we are performing an implicit module build.
bool BeginSourceFileAction(CompilerInstance &CI) override
Callback at the start of processing a single input.
unsigned RelocatablePCH
When generating PCH files, instruct the AST writer to create relocatable PCH files.
Languages that the frontend can parse and compile.
static bool ComputeASTConsumerArguments(CompilerInstance &CI, std::string &Sysroot)
Compute the AST consumer arguments that will be used to create the PCHGenerator instance returned by ...
This is a base class for callbacks that will be notified at every template instantiation.
CompilerInstance & getCompilerInstance() const
std::string UserInfo
A string containing additional user information that will be stored with the metadata.
const PCHContainerWriter & getPCHContainerWriter() const
Return the appropriate PCHContainerWriter depending on the current CodeGenOptions.
HeaderSearch & getHeaderSearchInfo() const
Definition: Preprocessor.h:820
std::string getCachedModuleFileName(Module *Module)
Retrieve the name of the cached module file that should be used to load the given module...
FrontendOptions & getFrontendOpts()
const FormatToken & Tok
static void mapping(IO &io, TemplightEntry &fields)
StringRef getCurrentFileOrBufferName() const
PreprocessorOutputOptions & getPreprocessorOutputOpts()
std::string ResourceDir
The directory which holds the compiler resource files (builtin includes, etc.).
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
virtual bool BeginInvocation(CompilerInstance &CI)
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
#define DUMP_BOOLEAN(Value, Text)
const LangOptions & getLangOpts() const
Definition: Sema.h:1230
HeaderSearchOptions & getHeaderSearchOpts()
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer...
CodeCompleteConsumer & getCodeCompletionConsumer() const
std::vector< std::string > ModuleFeatures
The names of any features to enable in module &#39;requires&#39; decls in addition to the hard-coded list in ...
Definition: LangOptions.h:232
Encapsulates the information needed to find the file referenced by a #include or #include_next, (sub-)framework lookup, etc.
Definition: HeaderSearch.h:147
bool DetailedRecord
Whether we should maintain a detailed record of all macro definitions and expansions.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:277
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Definition: LangOptions.h:226
StringRef Filename
Definition: Format.cpp:1628
virtual bool shouldEraseOutputFiles()
Callback at the end of processing a single input, to determine if the output files should be erased o...
unsigned ASTDumpAll
Whether we deserialize all decls when forming AST dumps.
std::unique_ptr< ASTConsumer > CreateASTDumper(std::unique_ptr< raw_ostream > OS, StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups)
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts)
DoPrintPreprocessedInput - Implement -E mode.
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer...
static PreambleBounds ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines=0)
Compute the preamble of the given file.
Definition: Lexer.cpp:573
bool isInvalid() const
Return true if this object is invalid or uninitialized.
unsigned getLine() const
Return the presumed line number of this location.
Compiling a module from a list of header files.
Definition: LangOptions.h:81
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc...
void print(raw_ostream &OS, unsigned Indent=0) const
Print the module map for this module to the given stream.
Definition: Module.cpp:404
Defines the clang::Preprocessor interface.
unsigned UseBuiltinIncludes
Include the compiler builtin includes.
Represents an unpacked "presumed" location which can be presented to the user.
An input file for the front end.
InputKind getCurrentFileKind() const
const SourceManager & SM
Definition: Format.cpp:1489
unsigned MajorVersion
The major version of the extension data.
std::unique_ptr< raw_pwrite_stream > createOutputFile(StringRef OutputPath, bool Binary, bool RemoveFileOnSignal, StringRef BaseInput, StringRef Extension, bool UseTemporary, bool CreateMissingDirectories=false)
Create a new output file and add it to the list of tracked output files, optionally deriving the outp...
DirectoryLookup - This class represents one entry in the search list that specifies the search order ...
unsigned MinorVersion
The minor version of the extension data.
bool AllowPCHWithCompilerErrors
When true, a PCH with compiler errors will not be rejected.
std::string CPU
If given, the name of the target CPU to generate code for.
Definition: TargetOptions.h:36
SourceManager & getSourceManager() const
Definition: Preprocessor.h:818
const char * getFilename() const
Return the presumed filename of this location.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Kind
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
std::string ABI
If given, the name of the target ABI to use.
Definition: TargetOptions.h:42
File is a PCH file treated as the preamble.
Definition: Module.h:53
unsigned getColumn() const
Return the presumed column number of this location.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
unsigned UseStandardSystemIncludes
Include the system standard include search directories.
void atTemplateBegin(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema, const Sema::CodeSynthesisContext &Inst)
Assembly: we accept this only so that we can preprocess it.
File is a PCH file treated as such.
Definition: Module.h:50
ParsedSourceLocation CodeCompletionAt
If given, enable code completion at the provided location.
virtual TranslationUnitKind getTranslationUnitKind()
For AST-based actions, the kind of translation unit we&#39;re handling.
LLVM IR: we accept this so that we can run the optimizer on it, and compile it to assembly or object ...
std::vector< FrontendInputFile > Inputs
The input files and their types.
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:59
std::string getClangFullRepositoryVersion()
Retrieves the full repository version that is an amalgamation of the information in getClangRepositor...
Definition: Version.cpp:89
void Lex(Token &Result)
Lex the next token for this preprocessor.
virtual bool PrepareToExecuteAction(CompilerInstance &CI)
Prepare to execute the action on the given CompilerInstance.
virtual bool ReadFullVersionInformation(StringRef FullVersion)
Receives the full Clang version information.
Definition: ASTReader.h:134
unsigned ASTDumpLookups
Whether we include lookup table dumps in AST dumps.
std::vector< std::string > FeaturesAsWritten
The list of target specific features to enable or disable, as written on the command line...
Definition: TargetOptions.h:51
void DumpToken(const Token &Tok, bool DumpFlags=false) const
Print the token to stderr, used for debugging.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
Abstract interface for a consumer of code-completion information.
bool isNot(tok::TokenKind K) const
Definition: Token.h:95
Dataflow Directional Tag Classes.
FileManager & getFileManager() const
Return the current file manager to the caller.
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
const FrontendInputFile & getCurrentInput() const
bool UsePredefines
Initialize the preprocessor with the compiler and target specific predefines.
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:354
FileID getMainFileID() const
Returns the FileID of the main source file.
StringRef getCurrentFile() const
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool ShouldCloseOpenFile=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
virtual std::unique_ptr< ASTConsumer > CreatePCHContainerGenerator(CompilerInstance &CI, const std::string &MainFileName, const std::string &OutputFileName, std::unique_ptr< llvm::raw_pwrite_stream > OS, std::shared_ptr< PCHBuffer > Buffer) const =0
Return an ASTConsumer that can be chained with a PCHGenerator that produces a wrapper file format con...
SourceManager & getSourceManager() const
Return the current source manager.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
std::string BlockName
The name used to identify this particular extension block within the resulting module file...
Abstract interface for callback invocations by the ASTReader.
Definition: ASTReader.h:126
std::vector< std::shared_ptr< ModuleFileExtension > > ModuleFileExtensions
The list of module file extensions.
std::unique_ptr< raw_pwrite_stream > createDefaultOutputFile(bool Binary=true, StringRef BaseInput="", StringRef Extension="")
Create the default output file (from the invocation&#39;s options) and add it to the list of tracked outp...
std::unique_ptr< ASTConsumer > CreateASTViewer()
Metadata for a module file extension.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
bool hasCodeCompletionConsumer() const
std::unique_ptr< ASTConsumer > CreateASTDeclNodeLister()
virtual bool BeginSourceFileAction(CompilerInstance &CI)
Callback at the start of processing a single input.
unsigned ASTDumpDecls
Whether we include declaration dumps in AST dumps.
void atTemplateEnd(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema, const Sema::CodeSynthesisContext &Inst)
const PCHContainerReader & getPCHContainerReader() const
Return the appropriate PCHContainerReader depending on the current CodeGenOptions.
SourceManager & getSourceManager() const
Definition: Sema.h:1235
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
std::pair< unsigned, bool > PrecompiledPreambleBytes
If non-zero, the implicit PCH include is actually a precompiled preamble that covers this number of b...
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
HeaderSearchOptions - Helper class for storing options related to the initialization of the HeaderSea...
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
static bool readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions)
Read the control block for the named AST file.
Definition: ASTReader.cpp:4717
std::string Sysroot
If non-empty, the directory to use as a "virtual system root" for include paths.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static std::unique_ptr< llvm::raw_pwrite_stream > CreateOutputFile(CompilerInstance &CI, StringRef InFile, std::string &OutputFile)
Creates file to write the PCH into and returns a stream to write it into.
std::unique_ptr< ASTConsumer > CreateASTPrinter(std::unique_ptr< raw_ostream > OS, StringRef FilterString)
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
unsigned UseStandardCXXIncludes
Include the system standard C++ library include search directories.
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode...
Definition: Lexer.h:212
std::string Triple
The name of the target triple to compile for.
Definition: TargetOptions.h:29
bool isSystem(CharacteristicKind CK)
Determine whether a file / directory characteristic is for system code.
Definition: SourceManager.h:82
This class handles loading and caching of source files into memory.
std::string ModuleFormat
The module/pch container format.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:124
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer...