Coverage Report

Created: 2020-09-22 08:39

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