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