Coverage Report

Created: 2022-05-17 06:19

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