Coverage Report

Created: 2019-07-24 05:18

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