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(Message.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 (s.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.