Coverage Report

Created: 2021-01-23 06:44

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