1234287Sdim//===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// 2234287Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6234287Sdim// 7234287Sdim//===----------------------------------------------------------------------===// 8234287Sdim 9249423Sdim#include "clang/Frontend/SerializedDiagnosticPrinter.h" 10249423Sdim#include "clang/Basic/Diagnostic.h" 11243830Sdim#include "clang/Basic/DiagnosticOptions.h" 12234287Sdim#include "clang/Basic/SourceManager.h" 13249423Sdim#include "clang/Frontend/DiagnosticRenderer.h" 14280031Sdim#include "clang/Frontend/FrontendDiagnostic.h" 15280031Sdim#include "clang/Frontend/SerializedDiagnosticReader.h" 16280031Sdim#include "clang/Frontend/SerializedDiagnostics.h" 17280031Sdim#include "clang/Frontend/TextDiagnosticPrinter.h" 18234287Sdim#include "clang/Lex/Lexer.h" 19249423Sdim#include "llvm/ADT/DenseSet.h" 20288943Sdim#include "llvm/ADT/STLExtras.h" 21249423Sdim#include "llvm/ADT/SmallString.h" 22249423Sdim#include "llvm/ADT/StringRef.h" 23353358Sdim#include "llvm/Bitstream/BitCodes.h" 24353358Sdim#include "llvm/Bitstream/BitstreamReader.h" 25249423Sdim#include "llvm/Support/raw_ostream.h" 26309124Sdim#include <utility> 27234287Sdim 28234287Sdimusing namespace clang; 29234287Sdimusing namespace clang::serialized_diags; 30234287Sdim 31234287Sdimnamespace { 32341825Sdim 33234287Sdimclass AbbreviationMap { 34234287Sdim llvm::DenseMap<unsigned, unsigned> Abbrevs; 35234287Sdimpublic: 36234287Sdim AbbreviationMap() {} 37341825Sdim 38234287Sdim void set(unsigned recordID, unsigned abbrevID) { 39341825Sdim assert(Abbrevs.find(recordID) == Abbrevs.end() 40234287Sdim && "Abbreviation already set."); 41234287Sdim Abbrevs[recordID] = abbrevID; 42234287Sdim } 43341825Sdim 44234287Sdim unsigned get(unsigned recordID) { 45234287Sdim assert(Abbrevs.find(recordID) != Abbrevs.end() && 46234287Sdim "Abbreviation not set."); 47234287Sdim return Abbrevs[recordID]; 48234287Sdim } 49234287Sdim}; 50341825Sdim 51249423Sdimtypedef SmallVector<uint64_t, 64> RecordData; 52249423Sdimtypedef SmallVectorImpl<uint64_t> RecordDataImpl; 53296417Sdimtypedef ArrayRef<uint64_t> RecordDataRef; 54234287Sdim 55234287Sdimclass SDiagsWriter; 56341825Sdim 57234287Sdimclass SDiagsRenderer : public DiagnosticNoteRenderer { 58234287Sdim SDiagsWriter &Writer; 59234287Sdimpublic: 60243830Sdim SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts, 61243830Sdim DiagnosticOptions *DiagOpts) 62243830Sdim : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {} 63234287Sdim 64288943Sdim ~SDiagsRenderer() override {} 65288943Sdim 66234287Sdimprotected: 67321369Sdim void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, 68321369Sdim DiagnosticsEngine::Level Level, StringRef Message, 69276479Sdim ArrayRef<CharSourceRange> Ranges, 70276479Sdim DiagOrStoredDiag D) override; 71243830Sdim 72321369Sdim void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, 73276479Sdim DiagnosticsEngine::Level Level, 74321369Sdim ArrayRef<CharSourceRange> Ranges) override {} 75243830Sdim 76321369Sdim void emitNote(FullSourceLoc Loc, StringRef Message) override; 77243830Sdim 78321369Sdim void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, 79321369Sdim SmallVectorImpl<CharSourceRange> &Ranges, 80321369Sdim ArrayRef<FixItHint> Hints) override; 81276479Sdim 82276479Sdim void beginDiagnostic(DiagOrStoredDiag D, 83276479Sdim DiagnosticsEngine::Level Level) override; 84276479Sdim void endDiagnostic(DiagOrStoredDiag D, 85276479Sdim DiagnosticsEngine::Level Level) override; 86234287Sdim}; 87280031Sdim 88280031Sdimtypedef llvm::DenseMap<unsigned, unsigned> AbbrevLookup; 89280031Sdim 90280031Sdimclass SDiagsMerger : SerializedDiagnosticReader { 91280031Sdim SDiagsWriter &Writer; 92280031Sdim AbbrevLookup FileLookup; 93280031Sdim AbbrevLookup CategoryLookup; 94280031Sdim AbbrevLookup DiagFlagLookup; 95280031Sdim 96280031Sdimpublic: 97280031Sdim SDiagsMerger(SDiagsWriter &Writer) 98280031Sdim : SerializedDiagnosticReader(), Writer(Writer) {} 99280031Sdim 100280031Sdim std::error_code mergeRecordsFromFile(const char *File) { 101280031Sdim return readDiagnostics(File); 102280031Sdim } 103280031Sdim 104280031Sdimprotected: 105280031Sdim std::error_code visitStartOfDiagnostic() override; 106280031Sdim std::error_code visitEndOfDiagnostic() override; 107280031Sdim std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override; 108280031Sdim std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override; 109280031Sdim std::error_code visitDiagnosticRecord( 110280031Sdim unsigned Severity, const serialized_diags::Location &Location, 111280031Sdim unsigned Category, unsigned Flag, StringRef Message) override; 112280031Sdim std::error_code visitFilenameRecord(unsigned ID, unsigned Size, 113280031Sdim unsigned Timestamp, 114280031Sdim StringRef Name) override; 115280031Sdim std::error_code visitFixitRecord(const serialized_diags::Location &Start, 116280031Sdim const serialized_diags::Location &End, 117280031Sdim StringRef CodeToInsert) override; 118280031Sdim std::error_code 119280031Sdim visitSourceRangeRecord(const serialized_diags::Location &Start, 120280031Sdim const serialized_diags::Location &End) override; 121280031Sdim 122280031Sdimprivate: 123280031Sdim std::error_code adjustSourceLocFilename(RecordData &Record, 124280031Sdim unsigned int offset); 125280031Sdim 126280031Sdim void adjustAbbrevID(RecordData &Record, AbbrevLookup &Lookup, 127280031Sdim unsigned NewAbbrev); 128280031Sdim 129280031Sdim void writeRecordWithAbbrev(unsigned ID, RecordData &Record); 130280031Sdim 131280031Sdim void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob); 132280031Sdim}; 133280031Sdim 134234287Sdimclass SDiagsWriter : public DiagnosticConsumer { 135234287Sdim friend class SDiagsRenderer; 136280031Sdim friend class SDiagsMerger; 137249423Sdim 138249423Sdim struct SharedState; 139249423Sdim 140314564Sdim explicit SDiagsWriter(std::shared_ptr<SharedState> State) 141280031Sdim : LangOpts(nullptr), OriginalInstance(false), MergeChildRecords(false), 142309124Sdim State(std::move(State)) {} 143249423Sdim 144249423Sdimpublic: 145280031Sdim SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords) 146280031Sdim : LangOpts(nullptr), OriginalInstance(true), 147280031Sdim MergeChildRecords(MergeChildRecords), 148314564Sdim State(std::make_shared<SharedState>(File, Diags)) { 149280031Sdim if (MergeChildRecords) 150280031Sdim RemoveOldDiagnostics(); 151234287Sdim EmitPreamble(); 152234287Sdim } 153243830Sdim 154288943Sdim ~SDiagsWriter() override {} 155276479Sdim 156234287Sdim void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 157276479Sdim const Diagnostic &Info) override; 158276479Sdim 159276479Sdim void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { 160234287Sdim LangOpts = &LO; 161234287Sdim } 162234287Sdim 163276479Sdim void finish() override; 164234287Sdim 165234287Sdimprivate: 166341825Sdim /// Build a DiagnosticsEngine to emit diagnostics about the diagnostics 167280031Sdim DiagnosticsEngine *getMetaDiags(); 168280031Sdim 169341825Sdim /// Remove old copies of the serialized diagnostics. This is necessary 170280031Sdim /// so that we can detect when subprocesses write diagnostics that we should 171280031Sdim /// merge into our own. 172280031Sdim void RemoveOldDiagnostics(); 173280031Sdim 174341825Sdim /// Emit the preamble for the serialized diagnostics. 175234287Sdim void EmitPreamble(); 176341825Sdim 177341825Sdim /// Emit the BLOCKINFO block. 178234287Sdim void EmitBlockInfoBlock(); 179234287Sdim 180341825Sdim /// Emit the META data block. 181234287Sdim void EmitMetaBlock(); 182243830Sdim 183341825Sdim /// Start a DIAG block. 184243830Sdim void EnterDiagBlock(); 185243830Sdim 186341825Sdim /// End a DIAG block. 187243830Sdim void ExitDiagBlock(); 188243830Sdim 189341825Sdim /// Emit a DIAG record. 190321369Sdim void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, 191321369Sdim DiagnosticsEngine::Level Level, StringRef Message, 192243830Sdim DiagOrStoredDiag D); 193243830Sdim 194341825Sdim /// Emit FIXIT and SOURCE_RANGE records for a diagnostic. 195243830Sdim void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, 196243830Sdim ArrayRef<FixItHint> Hints, 197243830Sdim const SourceManager &SM); 198243830Sdim 199341825Sdim /// Emit a record for a CharSourceRange. 200234287Sdim void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM); 201341825Sdim 202341825Sdim /// Emit the string information for the category. 203234287Sdim unsigned getEmitCategory(unsigned category = 0); 204341825Sdim 205341825Sdim /// Emit the string information for diagnostic flags. 206234287Sdim unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 207234287Sdim unsigned DiagID = 0); 208280031Sdim 209280031Sdim unsigned getEmitDiagnosticFlag(StringRef DiagName); 210280031Sdim 211341825Sdim /// Emit (lazily) the file string and retrieved the file identifier. 212234287Sdim unsigned getEmitFile(const char *Filename); 213234287Sdim 214341825Sdim /// Add SourceLocation information the specified record. 215321369Sdim void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, 216321369Sdim RecordDataImpl &Record, unsigned TokSize = 0); 217234287Sdim 218341825Sdim /// Add SourceLocation information the specified record. 219321369Sdim void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record, 220234287Sdim unsigned TokSize = 0) { 221321369Sdim AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(), 222239462Sdim Record, TokSize); 223234287Sdim } 224234287Sdim 225341825Sdim /// Add CharSourceRange information the specified record. 226234287Sdim void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record, 227234287Sdim const SourceManager &SM); 228234287Sdim 229341825Sdim /// Language options, which can differ from one clone of this client 230249423Sdim /// to another. 231234287Sdim const LangOptions *LangOpts; 232234287Sdim 233341825Sdim /// Whether this is the original instance (rather than one of its 234249423Sdim /// clones), responsible for writing the file at the end. 235249423Sdim bool OriginalInstance; 236234287Sdim 237341825Sdim /// Whether this instance should aggregate diagnostics that are 238280031Sdim /// generated from child processes. 239280031Sdim bool MergeChildRecords; 240280031Sdim 241341825Sdim /// State that is shared among the various clones of this diagnostic 242249423Sdim /// consumer. 243314564Sdim struct SharedState { 244280031Sdim SharedState(StringRef File, DiagnosticOptions *Diags) 245280031Sdim : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()), 246280031Sdim EmittedAnyDiagBlocks(false) {} 247234287Sdim 248341825Sdim /// Diagnostic options. 249249423Sdim IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 250234287Sdim 251341825Sdim /// The byte buffer for the serialized content. 252249423Sdim SmallString<1024> Buffer; 253234287Sdim 254341825Sdim /// The BitStreamWriter for the serialized diagnostics. 255249423Sdim llvm::BitstreamWriter Stream; 256234287Sdim 257341825Sdim /// The name of the diagnostics file. 258280031Sdim std::string OutputFile; 259243830Sdim 260341825Sdim /// The set of constructed record abbreviations. 261249423Sdim AbbreviationMap Abbrevs; 262249423Sdim 263341825Sdim /// A utility buffer for constructing record content. 264249423Sdim RecordData Record; 265249423Sdim 266341825Sdim /// A text buffer for rendering diagnostic text. 267249423Sdim SmallString<256> diagBuf; 268249423Sdim 269341825Sdim /// The collection of diagnostic categories used. 270249423Sdim llvm::DenseSet<unsigned> Categories; 271249423Sdim 272341825Sdim /// The collection of files used. 273249423Sdim llvm::DenseMap<const char *, unsigned> Files; 274249423Sdim 275249423Sdim typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> > 276249423Sdim DiagFlagsTy; 277249423Sdim 278341825Sdim /// Map for uniquing strings. 279249423Sdim DiagFlagsTy DiagFlags; 280249423Sdim 281341825Sdim /// Whether we have already started emission of any DIAG blocks. Once 282249423Sdim /// this becomes \c true, we never close a DIAG block until we know that we're 283249423Sdim /// starting another one or we're done. 284249423Sdim bool EmittedAnyDiagBlocks; 285280031Sdim 286341825Sdim /// Engine for emitting diagnostics about the diagnostics. 287280031Sdim std::unique_ptr<DiagnosticsEngine> MetaDiagnostics; 288249423Sdim }; 289249423Sdim 290341825Sdim /// State shared among the various clones of this diagnostic consumer. 291314564Sdim std::shared_ptr<SharedState> State; 292234287Sdim}; 293234287Sdim} // end anonymous namespace 294234287Sdim 295234287Sdimnamespace clang { 296234287Sdimnamespace serialized_diags { 297280031Sdimstd::unique_ptr<DiagnosticConsumer> 298280031Sdimcreate(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) { 299360784Sdim return std::make_unique<SDiagsWriter>(OutputFile, Diags, MergeChildRecords); 300234287Sdim} 301280031Sdim 302234287Sdim} // end namespace serialized_diags 303234287Sdim} // end namespace clang 304234287Sdim 305234287Sdim//===----------------------------------------------------------------------===// 306234287Sdim// Serialization methods. 307234287Sdim//===----------------------------------------------------------------------===// 308234287Sdim 309341825Sdim/// Emits a block ID in the BLOCKINFO block. 310234287Sdimstatic void EmitBlockID(unsigned ID, const char *Name, 311234287Sdim llvm::BitstreamWriter &Stream, 312234287Sdim RecordDataImpl &Record) { 313234287Sdim Record.clear(); 314234287Sdim Record.push_back(ID); 315234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 316341825Sdim 317234287Sdim // Emit the block name if present. 318276479Sdim if (!Name || Name[0] == 0) 319234287Sdim return; 320234287Sdim 321234287Sdim Record.clear(); 322234287Sdim 323234287Sdim while (*Name) 324234287Sdim Record.push_back(*Name++); 325234287Sdim 326234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 327234287Sdim} 328234287Sdim 329341825Sdim/// Emits a record ID in the BLOCKINFO block. 330234287Sdimstatic void EmitRecordID(unsigned ID, const char *Name, 331234287Sdim llvm::BitstreamWriter &Stream, 332234287Sdim RecordDataImpl &Record){ 333234287Sdim Record.clear(); 334234287Sdim Record.push_back(ID); 335234287Sdim 336234287Sdim while (*Name) 337234287Sdim Record.push_back(*Name++); 338234287Sdim 339234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 340234287Sdim} 341234287Sdim 342321369Sdimvoid SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, 343321369Sdim RecordDataImpl &Record, unsigned TokSize) { 344234287Sdim if (PLoc.isInvalid()) { 345234287Sdim // Emit a "sentinel" location. 346234287Sdim Record.push_back((unsigned)0); // File. 347234287Sdim Record.push_back((unsigned)0); // Line. 348234287Sdim Record.push_back((unsigned)0); // Column. 349234287Sdim Record.push_back((unsigned)0); // Offset. 350234287Sdim return; 351234287Sdim } 352234287Sdim 353234287Sdim Record.push_back(getEmitFile(PLoc.getFilename())); 354234287Sdim Record.push_back(PLoc.getLine()); 355234287Sdim Record.push_back(PLoc.getColumn()+TokSize); 356321369Sdim Record.push_back(Loc.getFileOffset()); 357234287Sdim} 358234287Sdim 359234287Sdimvoid SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, 360234287Sdim RecordDataImpl &Record, 361234287Sdim const SourceManager &SM) { 362321369Sdim AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record); 363234287Sdim unsigned TokSize = 0; 364234287Sdim if (Range.isTokenRange()) 365234287Sdim TokSize = Lexer::MeasureTokenLength(Range.getEnd(), 366234287Sdim SM, *LangOpts); 367321369Sdim 368321369Sdim AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize); 369234287Sdim} 370234287Sdim 371234287Sdimunsigned SDiagsWriter::getEmitFile(const char *FileName){ 372234287Sdim if (!FileName) 373234287Sdim return 0; 374341825Sdim 375249423Sdim unsigned &entry = State->Files[FileName]; 376234287Sdim if (entry) 377234287Sdim return entry; 378341825Sdim 379234287Sdim // Lazily generate the record for the file. 380249423Sdim entry = State->Files.size(); 381234287Sdim StringRef Name(FileName); 382296417Sdim RecordData::value_type Record[] = {RECORD_FILENAME, entry, 0 /* For legacy */, 383296417Sdim 0 /* For legacy */, Name.size()}; 384249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record, 385249423Sdim Name); 386234287Sdim 387234287Sdim return entry; 388234287Sdim} 389234287Sdim 390234287Sdimvoid SDiagsWriter::EmitCharSourceRange(CharSourceRange R, 391234287Sdim const SourceManager &SM) { 392249423Sdim State->Record.clear(); 393249423Sdim State->Record.push_back(RECORD_SOURCE_RANGE); 394249423Sdim AddCharSourceRangeToRecord(R, State->Record, SM); 395249423Sdim State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE), 396249423Sdim State->Record); 397234287Sdim} 398234287Sdim 399341825Sdim/// Emits the preamble of the diagnostics file. 400234287Sdimvoid SDiagsWriter::EmitPreamble() { 401234287Sdim // Emit the file header. 402249423Sdim State->Stream.Emit((unsigned)'D', 8); 403249423Sdim State->Stream.Emit((unsigned)'I', 8); 404249423Sdim State->Stream.Emit((unsigned)'A', 8); 405249423Sdim State->Stream.Emit((unsigned)'G', 8); 406234287Sdim 407234287Sdim EmitBlockInfoBlock(); 408234287Sdim EmitMetaBlock(); 409234287Sdim} 410234287Sdim 411314564Sdimstatic void AddSourceLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) { 412234287Sdim using namespace llvm; 413314564Sdim Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID. 414314564Sdim Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line. 415314564Sdim Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column. 416314564Sdim Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset; 417234287Sdim} 418234287Sdim 419314564Sdimstatic void AddRangeLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) { 420234287Sdim AddSourceLocationAbbrev(Abbrev); 421341825Sdim AddSourceLocationAbbrev(Abbrev); 422234287Sdim} 423234287Sdim 424234287Sdimvoid SDiagsWriter::EmitBlockInfoBlock() { 425314564Sdim State->Stream.EnterBlockInfoBlock(); 426234287Sdim 427234287Sdim using namespace llvm; 428249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 429249423Sdim RecordData &Record = State->Record; 430249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 431234287Sdim 432234287Sdim // ==---------------------------------------------------------------------==// 433234287Sdim // The subsequent records and Abbrevs are for the "Meta" block. 434234287Sdim // ==---------------------------------------------------------------------==// 435234287Sdim 436234287Sdim EmitBlockID(BLOCK_META, "Meta", Stream, Record); 437234287Sdim EmitRecordID(RECORD_VERSION, "Version", Stream, Record); 438314564Sdim auto Abbrev = std::make_shared<BitCodeAbbrev>(); 439234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION)); 440234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 441234287Sdim Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev)); 442234287Sdim 443234287Sdim // ==---------------------------------------------------------------------==// 444234287Sdim // The subsequent records and Abbrevs are for the "Diagnostic" block. 445234287Sdim // ==---------------------------------------------------------------------==// 446234287Sdim 447234287Sdim EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record); 448234287Sdim EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record); 449234287Sdim EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record); 450234287Sdim EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record); 451234287Sdim EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record); 452234287Sdim EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record); 453234287Sdim EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record); 454234287Sdim 455234287Sdim // Emit abbreviation for RECORD_DIAG. 456314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 457234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 458234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 459314564Sdim AddSourceLocationAbbrev(*Abbrev); 460341825Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category. 461234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 462296417Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Text size. 463234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 464234287Sdim Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 465341825Sdim 466341825Sdim // Emit abbreviation for RECORD_CATEGORY. 467314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 468234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); 469234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID. 470234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size. 471234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. 472234287Sdim Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 473234287Sdim 474341825Sdim // Emit abbreviation for RECORD_SOURCE_RANGE. 475314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 476234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE)); 477314564Sdim AddRangeLocationAbbrev(*Abbrev); 478234287Sdim Abbrevs.set(RECORD_SOURCE_RANGE, 479234287Sdim Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 480341825Sdim 481234287Sdim // Emit the abbreviation for RECORD_DIAG_FLAG. 482314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 483234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 484234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 485234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 486234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 487234287Sdim Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 488234287Sdim Abbrev)); 489341825Sdim 490234287Sdim // Emit the abbreviation for RECORD_FILENAME. 491314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 492234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); 493234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID. 494234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size. 495341825Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modification time. 496234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 497234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. 498234287Sdim Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 499234287Sdim Abbrev)); 500341825Sdim 501234287Sdim // Emit the abbreviation for RECORD_FIXIT. 502314564Sdim Abbrev = std::make_shared<BitCodeAbbrev>(); 503234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT)); 504314564Sdim AddRangeLocationAbbrev(*Abbrev); 505234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 506234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text. 507234287Sdim Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 508234287Sdim Abbrev)); 509234287Sdim 510234287Sdim Stream.ExitBlock(); 511234287Sdim} 512234287Sdim 513234287Sdimvoid SDiagsWriter::EmitMetaBlock() { 514249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 515249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 516249423Sdim 517234287Sdim Stream.EnterSubblock(BLOCK_META, 3); 518296417Sdim RecordData::value_type Record[] = {RECORD_VERSION, VersionNumber}; 519296417Sdim Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record); 520234287Sdim Stream.ExitBlock(); 521234287Sdim} 522234287Sdim 523234287Sdimunsigned SDiagsWriter::getEmitCategory(unsigned int category) { 524280031Sdim if (!State->Categories.insert(category).second) 525234287Sdim return category; 526280031Sdim 527234287Sdim // We use a local version of 'Record' so that we can be generating 528234287Sdim // another record when we lazily generate one for the category entry. 529234287Sdim StringRef catName = DiagnosticIDs::getCategoryNameFromID(category); 530296417Sdim RecordData::value_type Record[] = {RECORD_CATEGORY, category, catName.size()}; 531249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record, 532249423Sdim catName); 533341825Sdim 534234287Sdim return category; 535234287Sdim} 536234287Sdim 537234287Sdimunsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 538234287Sdim unsigned DiagID) { 539234287Sdim if (DiagLevel == DiagnosticsEngine::Note) 540234287Sdim return 0; // No flag for notes. 541341825Sdim 542234287Sdim StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID); 543280031Sdim return getEmitDiagnosticFlag(FlagName); 544280031Sdim} 545280031Sdim 546280031Sdimunsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) { 547234287Sdim if (FlagName.empty()) 548234287Sdim return 0; 549234287Sdim 550234287Sdim // Here we assume that FlagName points to static data whose pointer 551234287Sdim // value is fixed. This allows us to unique by diagnostic groups. 552234287Sdim const void *data = FlagName.data(); 553249423Sdim std::pair<unsigned, StringRef> &entry = State->DiagFlags[data]; 554234287Sdim if (entry.first == 0) { 555249423Sdim entry.first = State->DiagFlags.size(); 556234287Sdim entry.second = FlagName; 557341825Sdim 558234287Sdim // Lazily emit the string in a separate record. 559296417Sdim RecordData::value_type Record[] = {RECORD_DIAG_FLAG, entry.first, 560296417Sdim FlagName.size()}; 561249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG), 562249423Sdim Record, FlagName); 563234287Sdim } 564234287Sdim 565234287Sdim return entry.first; 566234287Sdim} 567234287Sdim 568234287Sdimvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 569234287Sdim const Diagnostic &Info) { 570243830Sdim // Enter the block for a non-note diagnostic immediately, rather than waiting 571243830Sdim // for beginDiagnostic, in case associated notes are emitted before we get 572243830Sdim // there. 573234287Sdim if (DiagLevel != DiagnosticsEngine::Note) { 574249423Sdim if (State->EmittedAnyDiagBlocks) 575243830Sdim ExitDiagBlock(); 576243830Sdim 577243830Sdim EnterDiagBlock(); 578249423Sdim State->EmittedAnyDiagBlocks = true; 579234287Sdim } 580234287Sdim 581234287Sdim // Compute the diagnostic text. 582249423Sdim State->diagBuf.clear(); 583249423Sdim Info.FormatDiagnostic(State->diagBuf); 584234287Sdim 585243830Sdim if (Info.getLocation().isInvalid()) { 586243830Sdim // Special-case diagnostics with no location. We may not have entered a 587243830Sdim // source file in this case, so we can't use the normal DiagnosticsRenderer 588243830Sdim // machinery. 589249423Sdim 590249423Sdim // Make sure we bracket all notes as "sub-diagnostics". This matches 591249423Sdim // the behavior in SDiagsRenderer::emitDiagnostic(). 592249423Sdim if (DiagLevel == DiagnosticsEngine::Note) 593249423Sdim EnterDiagBlock(); 594249423Sdim 595321369Sdim EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel, 596321369Sdim State->diagBuf, &Info); 597249423Sdim 598249423Sdim if (DiagLevel == DiagnosticsEngine::Note) 599249423Sdim ExitDiagBlock(); 600249423Sdim 601243830Sdim return; 602243830Sdim } 603243830Sdim 604243830Sdim assert(Info.hasSourceManager() && LangOpts && 605243830Sdim "Unexpected diagnostic with valid location outside of a source file"); 606249423Sdim SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts); 607321369Sdim Renderer.emitDiagnostic( 608321369Sdim FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel, 609321369Sdim State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info); 610234287Sdim} 611234287Sdim 612276479Sdimstatic serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { 613276479Sdim switch (Level) { 614276479Sdim#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X; 615276479Sdim CASE(Ignored) 616276479Sdim CASE(Note) 617276479Sdim CASE(Remark) 618276479Sdim CASE(Warning) 619276479Sdim CASE(Error) 620276479Sdim CASE(Fatal) 621276479Sdim#undef CASE 622276479Sdim } 623276479Sdim 624276479Sdim llvm_unreachable("invalid diagnostic level"); 625276479Sdim} 626276479Sdim 627321369Sdimvoid SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, 628243830Sdim DiagnosticsEngine::Level Level, 629243830Sdim StringRef Message, 630243830Sdim DiagOrStoredDiag D) { 631249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 632249423Sdim RecordData &Record = State->Record; 633249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 634341825Sdim 635243830Sdim // Emit the RECORD_DIAG record. 636243830Sdim Record.clear(); 637243830Sdim Record.push_back(RECORD_DIAG); 638276479Sdim Record.push_back(getStableLevel(Level)); 639321369Sdim AddLocToRecord(Loc, PLoc, Record); 640243830Sdim 641243830Sdim if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { 642243830Sdim // Emit the category string lazily and get the category ID. 643243830Sdim unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); 644243830Sdim Record.push_back(getEmitCategory(DiagID)); 645243830Sdim // Emit the diagnostic flag string lazily and get the mapped ID. 646243830Sdim Record.push_back(getEmitDiagnosticFlag(Level, Info->getID())); 647243830Sdim } else { 648243830Sdim Record.push_back(getEmitCategory()); 649243830Sdim Record.push_back(getEmitDiagnosticFlag(Level)); 650243830Sdim } 651243830Sdim 652243830Sdim Record.push_back(Message.size()); 653243830Sdim Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message); 654243830Sdim} 655243830Sdim 656321369Sdimvoid SDiagsRenderer::emitDiagnosticMessage( 657321369Sdim FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, 658321369Sdim StringRef Message, ArrayRef<clang::CharSourceRange> Ranges, 659321369Sdim DiagOrStoredDiag D) { 660321369Sdim Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D); 661243830Sdim} 662234287Sdim 663243830Sdimvoid SDiagsWriter::EnterDiagBlock() { 664249423Sdim State->Stream.EnterSubblock(BLOCK_DIAG, 4); 665243830Sdim} 666234287Sdim 667243830Sdimvoid SDiagsWriter::ExitDiagBlock() { 668249423Sdim State->Stream.ExitBlock(); 669234287Sdim} 670234287Sdim 671234287Sdimvoid SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, 672234287Sdim DiagnosticsEngine::Level Level) { 673243830Sdim if (Level == DiagnosticsEngine::Note) 674243830Sdim Writer.EnterDiagBlock(); 675234287Sdim} 676234287Sdim 677234287Sdimvoid SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, 678234287Sdim DiagnosticsEngine::Level Level) { 679243830Sdim // Only end note diagnostics here, because we can't be sure when we've seen 680243830Sdim // the last note associated with a non-note diagnostic. 681243830Sdim if (Level == DiagnosticsEngine::Note) 682243830Sdim Writer.ExitDiagBlock(); 683234287Sdim} 684234287Sdim 685243830Sdimvoid SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, 686243830Sdim ArrayRef<FixItHint> Hints, 687243830Sdim const SourceManager &SM) { 688249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 689249423Sdim RecordData &Record = State->Record; 690249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 691249423Sdim 692234287Sdim // Emit Source Ranges. 693243830Sdim for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); 694243830Sdim I != E; ++I) 695243830Sdim if (I->isValid()) 696243830Sdim EmitCharSourceRange(*I, SM); 697243830Sdim 698234287Sdim // Emit FixIts. 699243830Sdim for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 700243830Sdim I != E; ++I) { 701243830Sdim const FixItHint &Fix = *I; 702243830Sdim if (Fix.isNull()) 703234287Sdim continue; 704243830Sdim Record.clear(); 705243830Sdim Record.push_back(RECORD_FIXIT); 706243830Sdim AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM); 707243830Sdim Record.push_back(Fix.CodeToInsert.size()); 708243830Sdim Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record, 709243830Sdim Fix.CodeToInsert); 710234287Sdim } 711234287Sdim} 712234287Sdim 713321369Sdimvoid SDiagsRenderer::emitCodeContext(FullSourceLoc Loc, 714243830Sdim DiagnosticsEngine::Level Level, 715243830Sdim SmallVectorImpl<CharSourceRange> &Ranges, 716321369Sdim ArrayRef<FixItHint> Hints) { 717321369Sdim Writer.EmitCodeContext(Ranges, Hints, Loc.getManager()); 718243830Sdim} 719243830Sdim 720321369Sdimvoid SDiagsRenderer::emitNote(FullSourceLoc Loc, StringRef Message) { 721243830Sdim Writer.EnterDiagBlock(); 722321369Sdim PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(); 723321369Sdim Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message, 724321369Sdim DiagOrStoredDiag()); 725243830Sdim Writer.ExitDiagBlock(); 726234287Sdim} 727234287Sdim 728280031SdimDiagnosticsEngine *SDiagsWriter::getMetaDiags() { 729280031Sdim // FIXME: It's slightly absurd to create a new diagnostics engine here, but 730280031Sdim // the other options that are available today are worse: 731280031Sdim // 732280031Sdim // 1. Teach DiagnosticsConsumers to emit diagnostics to the engine they are a 733280031Sdim // part of. The DiagnosticsEngine would need to know not to send 734280031Sdim // diagnostics back to the consumer that failed. This would require us to 735280031Sdim // rework ChainedDiagnosticsConsumer and teach the engine about multiple 736280031Sdim // consumers, which is difficult today because most APIs interface with 737280031Sdim // consumers rather than the engine itself. 738280031Sdim // 739280031Sdim // 2. Pass a DiagnosticsEngine to SDiagsWriter on creation - this would need 740280031Sdim // to be distinct from the engine the writer was being added to and would 741280031Sdim // normally not be used. 742280031Sdim if (!State->MetaDiagnostics) { 743280031Sdim IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs()); 744280031Sdim auto Client = 745280031Sdim new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get()); 746360784Sdim State->MetaDiagnostics = std::make_unique<DiagnosticsEngine>( 747280031Sdim IDs, State->DiagOpts.get(), Client); 748280031Sdim } 749280031Sdim return State->MetaDiagnostics.get(); 750280031Sdim} 751280031Sdim 752280031Sdimvoid SDiagsWriter::RemoveOldDiagnostics() { 753280031Sdim if (!llvm::sys::fs::remove(State->OutputFile)) 754280031Sdim return; 755280031Sdim 756280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure); 757280031Sdim // Disable merging child records, as whatever is in this file may be 758280031Sdim // misleading. 759280031Sdim MergeChildRecords = false; 760280031Sdim} 761280031Sdim 762234287Sdimvoid SDiagsWriter::finish() { 763249423Sdim // The original instance is responsible for writing the file. 764249423Sdim if (!OriginalInstance) 765249423Sdim return; 766249423Sdim 767243830Sdim // Finish off any diagnostic we were in the process of emitting. 768249423Sdim if (State->EmittedAnyDiagBlocks) 769243830Sdim ExitDiagBlock(); 770234287Sdim 771280031Sdim if (MergeChildRecords) { 772280031Sdim if (!State->EmittedAnyDiagBlocks) 773280031Sdim // We have no diagnostics of our own, so we can just leave the child 774280031Sdim // process' output alone 775280031Sdim return; 776280031Sdim 777280031Sdim if (llvm::sys::fs::exists(State->OutputFile)) 778280031Sdim if (SDiagsMerger(*this).mergeRecordsFromFile(State->OutputFile.c_str())) 779280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure); 780280031Sdim } 781280031Sdim 782280031Sdim std::error_code EC; 783360784Sdim auto OS = std::make_unique<llvm::raw_fd_ostream>(State->OutputFile.c_str(), 784360784Sdim EC, llvm::sys::fs::OF_None); 785280031Sdim if (EC) { 786280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure) 787280031Sdim << State->OutputFile << EC.message(); 788280031Sdim return; 789280031Sdim } 790280031Sdim 791234287Sdim // Write the generated bitstream to "Out". 792280031Sdim OS->write((char *)&State->Buffer.front(), State->Buffer.size()); 793280031Sdim OS->flush(); 794280031Sdim} 795243830Sdim 796280031Sdimstd::error_code SDiagsMerger::visitStartOfDiagnostic() { 797280031Sdim Writer.EnterDiagBlock(); 798280031Sdim return std::error_code(); 799234287Sdim} 800280031Sdim 801280031Sdimstd::error_code SDiagsMerger::visitEndOfDiagnostic() { 802280031Sdim Writer.ExitDiagBlock(); 803280031Sdim return std::error_code(); 804280031Sdim} 805280031Sdim 806280031Sdimstd::error_code 807280031SdimSDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start, 808280031Sdim const serialized_diags::Location &End) { 809296417Sdim RecordData::value_type Record[] = { 810296417Sdim RECORD_SOURCE_RANGE, FileLookup[Start.FileID], Start.Line, Start.Col, 811296417Sdim Start.Offset, FileLookup[End.FileID], End.Line, End.Col, End.Offset}; 812280031Sdim Writer.State->Stream.EmitRecordWithAbbrev( 813280031Sdim Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record); 814280031Sdim return std::error_code(); 815280031Sdim} 816280031Sdim 817280031Sdimstd::error_code SDiagsMerger::visitDiagnosticRecord( 818280031Sdim unsigned Severity, const serialized_diags::Location &Location, 819280031Sdim unsigned Category, unsigned Flag, StringRef Message) { 820296417Sdim RecordData::value_type Record[] = { 821296417Sdim RECORD_DIAG, Severity, FileLookup[Location.FileID], Location.Line, 822296417Sdim Location.Col, Location.Offset, CategoryLookup[Category], 823296417Sdim Flag ? DiagFlagLookup[Flag] : 0, Message.size()}; 824280031Sdim 825280031Sdim Writer.State->Stream.EmitRecordWithBlob( 826296417Sdim Writer.State->Abbrevs.get(RECORD_DIAG), Record, Message); 827280031Sdim return std::error_code(); 828280031Sdim} 829280031Sdim 830280031Sdimstd::error_code 831280031SdimSDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start, 832280031Sdim const serialized_diags::Location &End, 833280031Sdim StringRef Text) { 834296417Sdim RecordData::value_type Record[] = {RECORD_FIXIT, FileLookup[Start.FileID], 835296417Sdim Start.Line, Start.Col, Start.Offset, 836296417Sdim FileLookup[End.FileID], End.Line, End.Col, 837296417Sdim End.Offset, Text.size()}; 838280031Sdim 839280031Sdim Writer.State->Stream.EmitRecordWithBlob( 840280031Sdim Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text); 841280031Sdim return std::error_code(); 842280031Sdim} 843280031Sdim 844280031Sdimstd::error_code SDiagsMerger::visitFilenameRecord(unsigned ID, unsigned Size, 845280031Sdim unsigned Timestamp, 846280031Sdim StringRef Name) { 847280031Sdim FileLookup[ID] = Writer.getEmitFile(Name.str().c_str()); 848280031Sdim return std::error_code(); 849280031Sdim} 850280031Sdim 851280031Sdimstd::error_code SDiagsMerger::visitCategoryRecord(unsigned ID, StringRef Name) { 852280031Sdim CategoryLookup[ID] = Writer.getEmitCategory(ID); 853280031Sdim return std::error_code(); 854280031Sdim} 855280031Sdim 856280031Sdimstd::error_code SDiagsMerger::visitDiagFlagRecord(unsigned ID, StringRef Name) { 857280031Sdim DiagFlagLookup[ID] = Writer.getEmitDiagnosticFlag(Name); 858280031Sdim return std::error_code(); 859280031Sdim} 860