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