Coverage Report

Created: 2021-09-21 08:58

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