clang: lib/StaticAnalyzer/Core/PlistDiagnostics.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/Statistic.h"
28#include
29#include
30
31using namespace clang;
32using namespace ento;
33using namespace markup;
34
35
36
37
38
39
40namespace {
42 PathDiagnosticConsumerOptions DiagOpts;
43 const std::string OutputFile;
44 const Preprocessor &PP;
45 const cross_tu::CrossTranslationUnitContext &CTU;
46 const MacroExpansionContext &MacroExpansions;
47 const bool SupportsCrossFileDiagnostics;
48
49 void printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
50 const PathPieces &Path);
51
52 public:
53 PlistDiagnostics(PathDiagnosticConsumerOptions DiagOpts,
54 const std::string &OutputFile, const Preprocessor &PP,
55 const cross_tu::CrossTranslationUnitContext &CTU,
56 const MacroExpansionContext &MacroExpansions,
57 bool supportsMultipleFiles);
58
59 ~PlistDiagnostics() override {}
60
61 void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
62 FilesMade *filesMade) override;
63
64 StringRef getName() const override {
65 return "PlistDiagnostics";
66 }
67
68 PathGenerationScheme getGenerationScheme() const override {
69 return Extensive;
70 }
71 bool supportsLogicalOpControlFlow() const override { return true; }
72 bool supportsCrossFileDiagnostics() const override {
73 return SupportsCrossFileDiagnostics;
74 }
75 };
76}
77
78namespace {
79
80
81class PlistPrinter {
83 const Preprocessor &PP;
84 const cross_tu::CrossTranslationUnitContext &CTU;
85 const MacroExpansionContext &MacroExpansions;
86 llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
87
88public:
89 PlistPrinter(const FIDMap &FM, const Preprocessor &PP,
90 const cross_tu::CrossTranslationUnitContext &CTU,
91 const MacroExpansionContext &MacroExpansions)
92 : FM(FM), PP(PP), CTU(CTU), MacroExpansions(MacroExpansions) {}
93
94 void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
95 ReportPiece(o, P, 4, 0, true);
96 }
97
98
99
100
101
102
103
104 void ReportMacroExpansions(raw_ostream &o, unsigned indent);
105
106private:
107 void ReportPiece(raw_ostream &o, const PathDiagnosticPiece &P,
108 unsigned indent, unsigned depth, bool includeControlFlow,
109 bool isKeyEvent = false) {
112 if (includeControlFlow)
114 break;
117 depth);
118 break;
121 isKeyEvent);
122 break;
125 depth);
126 break;
129 break;
132 break;
133 }
134 }
135
136 void EmitRanges(raw_ostream &o, const ArrayRef Ranges,
137 unsigned indent);
138 void EmitMessage(raw_ostream &o, StringRef Message, unsigned indent);
139 void EmitFixits(raw_ostream &o, ArrayRef fixits, unsigned indent);
140
141 void ReportControlFlow(raw_ostream &o,
142 const PathDiagnosticControlFlowPiece& P,
143 unsigned indent);
144 void ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
145 unsigned indent, unsigned depth, bool isKeyEvent = false);
146 void ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
147 unsigned indent, unsigned depth);
148 void ReportMacroSubPieces(raw_ostream &o, const PathDiagnosticMacroPiece& P,
149 unsigned indent, unsigned depth);
150 void ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
151 unsigned indent);
152
153 void ReportPopUp(raw_ostream &o, const PathDiagnosticPopUpPiece &P,
154 unsigned indent);
155};
156
157}
158
159
160
162 unsigned InputIndentLevel,
165 llvm::raw_fd_ostream &o);
166
170
171
172
173
174
175void PlistPrinter::EmitRanges(raw_ostream &o,
177 unsigned indent) {
178
179 if (Ranges.empty())
180 return;
181
182 Indent(o, indent) << "ranges\n";
183 Indent(o, indent) << "\n";
184 ++indent;
185
187 const LangOptions &LangOpts = PP.getLangOpts();
188
189 for (auto &R : Ranges)
192 FM, indent + 1);
193 --indent;
194 Indent(o, indent) << "\n";
195}
196
197void PlistPrinter::EmitMessage(raw_ostream &o, StringRef Message,
198 unsigned indent) {
199
200 assert(.empty());
201 Indent(o, indent) << "extended_message\n";
204
205
206
207 Indent(o, indent) << "message\n";
210}
211
212void PlistPrinter::EmitFixits(raw_ostream &o, ArrayRef fixits,
213 unsigned indent) {
214 if (fixits.size() == 0)
215 return;
216
218 const LangOptions &LangOpts = PP.getLangOpts();
219
220 Indent(o, indent) << "fixits\n";
221 Indent(o, indent) << "\n";
222 for (const auto &fixit : fixits) {
223 assert(!fixit.isNull());
224
225 assert(!fixit.InsertFromRange.isValid() && "Not implemented yet!");
226 assert(!fixit.BeforePreviousInsertions && "Not implemented yet!");
227 Indent(o, indent) << " \n";
228 Indent(o, indent) << " remove_range\n";
230 FM, indent + 2);
231 Indent(o, indent) << " insert_string";
233 o << "\n";
234 Indent(o, indent) << " \n";
235 }
236 Indent(o, indent) << "\n";
237}
238
239void PlistPrinter::ReportControlFlow(raw_ostream &o,
240 const PathDiagnosticControlFlowPiece& P,
241 unsigned indent) {
242
244 const LangOptions &LangOpts = PP.getLangOpts();
245
246 Indent(o, indent) << "\n";
247 ++indent;
248
249 Indent(o, indent) << "kindcontrol\n";
250
251
252 Indent(o, indent) << "edges\n";
253 ++indent;
254 Indent(o, indent) << "\n";
255 ++indent;
257 I!=E; ++I) {
258 Indent(o, indent) << "\n";
259 ++indent;
260
261
262
263
264 Indent(o, indent) << "start\n";
265 SourceRange StartEdge(
266 SM.getExpansionLoc(I->getStart().asRange().getBegin()));
268 indent + 1);
269
270 Indent(o, indent) << "end\n";
271 SourceRange EndEdge(SM.getExpansionLoc(I->getEnd().asRange().getBegin()));
273 indent + 1);
274
275 --indent;
276 Indent(o, indent) << "\n";
277 }
278 --indent;
279 Indent(o, indent) << "\n";
280 --indent;
281
282
284 if (.empty()) {
285 Indent(o, indent) << "alternate";
287 }
288
289 assert(P.getFixits().size() == 0 &&
290 "Fixits on constrol flow pieces are not implemented yet!");
291
292 --indent;
293 Indent(o, indent) << "\n";
294}
295
296void PlistPrinter::ReportEvent(raw_ostream &o, const PathDiagnosticEventPiece& P,
297 unsigned indent, unsigned depth,
298 bool isKeyEvent) {
299
301
302 Indent(o, indent) << "\n";
303 ++indent;
304
305 Indent(o, indent) << "kindevent\n";
306
307 if (isKeyEvent) {
308 Indent(o, indent) << "key_event\n";
309 }
310
311
313
314 Indent(o, indent) << "location\n";
316
317
318 ArrayRef Ranges = P.getRanges();
319 EmitRanges(o, Ranges, indent);
320
321
322 Indent(o, indent) << "depth";
324
325
326 EmitMessage(o, P.getString(), indent);
327
328
329 EmitFixits(o, P.getFixits(), indent);
330
331
332 --indent;
333 Indent(o, indent); o << "\n";
334}
335
336void PlistPrinter::ReportCall(raw_ostream &o, const PathDiagnosticCallPiece &P,
337 unsigned indent,
338 unsigned depth) {
339
341 ReportPiece(o, *callEnter, indent, depth, true,
343
344
345 ++depth;
346
348 ReportPiece(o, *callEnterWithinCaller, indent, depth,
349 true);
350
351 for (PathPieces::const_iterator I = P.path.begin(), E = P.path.end();I!=E;++I)
352 ReportPiece(o, **I, indent, depth, true);
353
354 --depth;
355
357 ReportPiece(o, *callExit, indent, depth, true);
358
359 assert(P.getFixits().size() == 0 &&
360 "Fixits on call pieces are not implemented yet!");
361}
362
363void PlistPrinter::ReportMacroSubPieces(raw_ostream &o,
364 const PathDiagnosticMacroPiece& P,
365 unsigned indent, unsigned depth) {
366 MacroPieces.push_back(&P);
367
368 for (const auto &SubPiece : P.subPieces) {
369 ReportPiece(o, *SubPiece, indent, depth, false);
370 }
371
372 assert(P.getFixits().size() == 0 &&
373 "Fixits on constrol flow pieces are not implemented yet!");
374}
375
376void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {
377
378 for (const PathDiagnosticMacroPiece *P : MacroPieces) {
380
381 SourceLocation MacroExpansionLoc =
383
384 const std::optional MacroName =
386 const std::optional ExpansionText =
388
389 if (!MacroName || !ExpansionText)
390 continue;
391
392 Indent(o, indent) << "\n";
393 ++indent;
394
395
397
398 Indent(o, indent) << "location\n";
400
401
402 ArrayRef Ranges = P->getRanges();
403 EmitRanges(o, Ranges, indent);
404
405
406 Indent(o, indent) << "name";
408
409
410 Indent(o, indent) << "expansion";
411 EmitString(o, *ExpansionText) << '\n';
412
413
414 --indent;
416 o << "\n";
417 }
418}
419
420void PlistPrinter::ReportNote(raw_ostream &o, const PathDiagnosticNotePiece& P,
421 unsigned indent) {
422
424
425 Indent(o, indent) << "\n";
426 ++indent;
427
428
430
431 Indent(o, indent) << "location\n";
433
434
435 ArrayRef Ranges = P.getRanges();
436 EmitRanges(o, Ranges, indent);
437
438
439 EmitMessage(o, P.getString(), indent);
440
441
442 EmitFixits(o, P.getFixits(), indent);
443
444
445 --indent;
446 Indent(o, indent); o << "\n";
447}
448
449void PlistPrinter::ReportPopUp(raw_ostream &o,
450 const PathDiagnosticPopUpPiece &P,
451 unsigned indent) {
453
454 Indent(o, indent) << "\n";
455 ++indent;
456
457 Indent(o, indent) << "kindpop-up\n";
458
459
461
462 Indent(o, indent) << "location\n";
464
465
466 ArrayRef Ranges = P.getRanges();
467 EmitRanges(o, Ranges, indent);
468
469
470 EmitMessage(o, P.getString(), indent);
471
472 assert(P.getFixits().size() == 0 &&
473 "Fixits on pop-up pieces are not implemented yet!");
474
475
476 --indent;
477 Indent(o, indent) << "\n";
478}
479
480
481
482
483
484
485
487 unsigned InputIndentLevel,
490 llvm::raw_fd_ostream &o) {
492
496
497
499 for (const auto &[FID, Lines] : ExecutedLines) {
500 unsigned FileKey = AddFID(FM, Fids, FID);
504 for (unsigned LineNo : Lines) {
507 }
510 }
513
515}
516
517
518
519
520
521PlistDiagnostics::PlistDiagnostics(
522 PathDiagnosticConsumerOptions DiagOpts, const std::string &output,
523 const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU,
524 const MacroExpansionContext &MacroExpansions, bool supportsMultipleFiles)
525 : DiagOpts(std::move(DiagOpts)), OutputFile(output), PP(PP), CTU(CTU),
526 MacroExpansions(MacroExpansions),
527 SupportsCrossFileDiagnostics(supportsMultipleFiles) {
528
529 (void)this->CTU;
530}
531
532
533
536 const std::string &OutputFile, const Preprocessor &PP,
539
540
541 if (OutputFile.empty())
542 return;
543
544 C.push_back(std::make_unique(
545 DiagOpts, OutputFile, PP, CTU, MacroExpansions, SupportsMultipleFiles));
546}
547
548void ento::createPlistDiagnosticConsumer(
550 const std::string &OutputFile, const Preprocessor &PP,
553
555 MacroExpansions,
556 false);
557 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
558 PP, CTU, MacroExpansions);
559}
560
561void ento::createPlistMultiFileDiagnosticConsumer(
563 const std::string &OutputFile, const Preprocessor &PP,
566
568 MacroExpansions,
569 true);
570
571 createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
572 PP, CTU, MacroExpansions);
573}
574
575void PlistDiagnostics::printBugPath(llvm::raw_ostream &o, const FIDMap &FM,
577 PlistPrinter Printer(FM, PP, CTU, MacroExpansions);
578 assert(std::is_partitioned(Path.begin(), Path.end(),
580 return E->getKind() == PathDiagnosticPiece::Note;
581 }) &&
582 "PathDiagnostic is not partitioned so that notes precede the rest");
583
584 PathPieces::const_iterator FirstNonNote =
587 });
588
589 PathPieces::const_iterator I = Path.begin();
590
591 if (FirstNonNote != Path.begin()) {
592 o << " notes\n"
593 " \n";
594
595 for (; I != FirstNonNote; ++I)
596 Printer.ReportDiag(o, **I);
597
598 o << " \n";
599 }
600
601 o << " path\n";
602
603 o << " \n";
604
605 for (const auto &Piece : llvm::make_range(I, Path.end()))
606 Printer.ReportDiag(o, *Piece);
607
608 o << " \n";
609
611 return;
612
613 o << " macro_expansions\n"
614 " \n";
615 Printer.ReportMacroExpansions(o, 4);
616 o << " \n";
617}
618
619void PlistDiagnostics::FlushDiagnosticsImpl(
620 std::vector<const PathDiagnostic *> &Diags,
621 FilesMade *filesMade) {
622
623
625 SmallVector<FileID, 10> Fids;
627 const LangOptions &LangOpts = PP.getLangOpts();
628
629 auto AddPieceFID = [&FM, &Fids, &SM](const PathDiagnosticPiece &Piece) {
630 AddFID(FM, Fids, SM, Piece.getLocation().asLocation());
631 ArrayRef Ranges = Piece.getRanges();
632 for (const SourceRange &Range : Ranges) {
635 }
636 };
637
638 for (const PathDiagnostic *D : Diags) {
639
640 SmallVector<const PathPieces *, 5> WorkList;
641 WorkList.push_back(&D->path);
642
643 while (!WorkList.empty()) {
644 const PathPieces &Path = *WorkList.pop_back_val();
645
646 for (const auto &Iter : Path) {
647 const PathDiagnosticPiece &Piece = *Iter;
648 AddPieceFID(Piece);
649
650 if (const PathDiagnosticCallPiece *Call =
651 dyn_cast(&Piece)) {
652 if (auto CallEnterWithin = Call->getCallEnterWithinCallerEvent())
653 AddPieceFID(*CallEnterWithin);
654
655 if (auto CallEnterEvent = Call->getCallEnterEvent())
656 AddPieceFID(*CallEnterEvent);
657
658 WorkList.push_back(&Call->path);
659 } else if (const PathDiagnosticMacroPiece *Macro =
660 dyn_cast(&Piece)) {
661 WorkList.push_back(&Macro->subPieces);
662 }
663 }
664 }
665 }
666
667
668 std::error_code EC;
669 llvm::raw_fd_ostream o(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);
670 if (EC) {
671 llvm::errs() << "warning: could not create file: " << EC.message() << '\n';
672 return;
673 }
674
676
677
678
679
680
681 o << "\n" <<
682 " clang_version\n";
684 o << " diagnostics\n"
685 " \n";
686
687 for (std::vector<const PathDiagnostic*>::iterator DI=Diags.begin(),
688 DE = Diags.end(); DI!=DE; ++DI) {
689
690 o << " \n";
691
692 const PathDiagnostic *D = *DI;
693 printBugPath(o, FM, D->path);
694
695
696 o << " description";
698 o << " category";
700 o << " type";
702 o << " check_name";
704
705 o << " \n";
706 o << " issue_hash_content_of_line_in_context";
708 FullSourceLoc L(SM.getExpansionLoc(UPDLoc.isValid()
712
714
715
716
718
719 if (const NamedDecl *ND = dyn_cast(DeclWithIssue)) {
720 StringRef declKind;
721 switch (ND->getKind()) {
722 case Decl::CXXRecord:
723 declKind = "C++ class";
724 break;
725 case Decl::CXXMethod:
726 declKind = "C++ method";
727 break;
728 case Decl::ObjCMethod:
729 declKind = "Objective-C method";
730 break;
731 case Decl::Function:
732 declKind = "function";
733 break;
734 default:
735 break;
736 }
737 if (!declKind.empty()) {
738 const std::string &declName = ND->getDeclName().getAsString();
739 o << " issue_context_kind";
741 o << " issue_context";
743 }
744
745
746
747 if (const Stmt *Body = DeclWithIssue->getBody()) {
748
749
750
751
752
753
755 FullSourceLoc UFunL(
756 SM.getExpansionLoc(
759 o << " issue_hash_function_offset"
761 << "\n";
762
763
764 } else {
765 FullSourceLoc FunL(SM.getExpansionLoc(Body->getBeginLoc()), SM);
766 o << " issue_hash_function_offset"
768 << "\n";
769 }
770
771 }
772 }
773 }
774
775
776 o << " location\n";
778
779
780 if (!filesMade->empty()) {
781 StringRef lastName;
782 PDFileEntry::ConsumerFiles *files = filesMade->getFiles(*D);
783 if (files) {
784 for (PDFileEntry::ConsumerFiles::const_iterator CI = files->begin(),
785 CE = files->end(); CI != CE; ++CI) {
786 StringRef newName = CI->first;
787 if (newName != lastName) {
788 if (!lastName.empty()) {
789 o << " \n";
790 }
791 lastName = newName;
792 o << " " << lastName << "_files\n";
793 o << " \n";
794 }
795 o << " " << CI->second << "\n";
796 }
797 o << " \n";
798 }
799 }
800
801 printCoverage(D, 2, Fids, FM, o);
802
803
804 o << " \n";
805 }
806
807 o << " \n";
808
809 o << " files\n"
810 " \n";
811 for (FileID FID : Fids)
812 EmitString(o << " ", SM.getFileEntryRefForID(FID)->getName()) << '\n';
813 o << " \n";
814
816 o << " statistics\n";
817 std::string stats;
818 llvm::raw_string_ostream os(stats);
819 llvm::PrintStatisticsJSON(os);
821 }
822
823
824 o << "\n\n";
825}
826
827
828
829
830
831static std::optional
836 if (auto CTUMacroExpCtx =
838 return CTUMacroExpCtx->getExpandedText(MacroExpansionLoc);
839 }
840 return MacroExpansions.getExpandedText(MacroExpansionLoc);
841}
unsigned IndentLevel
The indent level of this token. Copied from the surrounding line.
static void printCoverage(const PathDiagnostic *D, unsigned InputIndentLevel, SmallVectorImpl< FileID > &Fids, FIDMap &FM, llvm::raw_fd_ostream &o)
Print coverage information to output stream o.
Definition PlistDiagnostics.cpp:486
static std::optional< StringRef > getExpandedMacro(SourceLocation MacroLoc, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions, const SourceManager &SM)
Definition PlistDiagnostics.cpp:832
Defines the clang::Preprocessor interface.
Defines the SourceManager interface.
Defines version macros and version-related utility functions for Clang.
__device__ __2f16 float __ockl_bool s
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
FullSourceLoc getExpansionLoc() const
unsigned getExpansionLineNumber(bool *Invalid=nullptr) const
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
MacroExpansionContext tracks the macro expansions processed by the Preprocessor.
std::optional< StringRef > getExpandedText(SourceLocation MacroExpansionLoc) const
std::optional< StringRef > getOriginalText(SourceLocation MacroExpansionLoc) const
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
const LangOptions & getLangOpts() const
Encodes a location in the source.
This class handles loading and caching of source files into memory.
SourceLocation getBeginLoc() const LLVM_READONLY
This class is used for tools that requires cross translation unit capability.
std::optional< clang::MacroExpansionContext > getMacroExpansionContextForSourceLocation(const clang::SourceLocation &ToLoc) const
Returns the MacroExpansionContext for the imported TU to which the given source-location corresponds.
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
FullSourceLoc asLocation() const
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
bool isLastInMainSourceFile() const
StringRef getString() const
ArrayRef< FixItHint > getFixits() const
Return the fix-it hints associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const override
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
StringRef getCheckerName() const
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
const FilesToLineNumsMap & getExecutedLines() const
StringRef getBugType() const
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
StringRef getCategory() const
StringRef getShortDescription() const
SmallString< 32 > getIssueHash(const SourceManager &SrcMgr, const LangOptions &LangOpts) const
Get a hash that identifies the issue.
PathDiagnosticLocation getLocation() const
std::vector< std::unique_ptr< PathDiagnosticConsumer > > PathDiagnosticConsumers
void createPlistDiagnosticConsumerImpl(PathDiagnosticConsumerOptions DiagOpts, PathDiagnosticConsumers &C, const std::string &Output, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions, bool SupportsMultipleFiles)
Creates and registers a Plist diagnostic consumer, without any additional text consumer.
Definition PlistDiagnostics.cpp:534
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
void EscapeText(Rewriter &R, FileID FID, bool EscapeSpaces=false, bool ReplaceTabs=false)
EscapeText - HTMLize a specified file so that special characters are are translated so that they are ...
StringRef getName(const HeaderType T)
void EmitRange(raw_ostream &o, const SourceManager &SM, CharSourceRange R, const FIDMap &FM, unsigned indent)
raw_ostream & EmitString(raw_ostream &o, StringRef s)
llvm::DenseMap< FileID, unsigned > FIDMap
unsigned AddFID(FIDMap &FIDs, SmallVectorImpl< FileID > &V, FileID FID)
raw_ostream & EmitInteger(raw_ostream &o, int64_t value)
raw_ostream & EmitPlistHeader(raw_ostream &o)
void EmitLocation(raw_ostream &o, const SourceManager &SM, SourceLocation L, const FIDMap &FM, unsigned indent)
The JSON file list parser is used to communicate input to InstallAPI.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
U cast(CodeGen::Address addr)
std::string getClangFullVersion()
Retrieves a string representing the complete clang version, which includes the clang version number,...
These options tweak the behavior of path diangostic consumers.
bool ShouldDisplayMacroExpansions
Whether to include additional information about macro expansions with the diagnostics,...
bool ShouldSerializeStats
Whether to include LLVM statistics of the process in the diagnostic.