SerializedDiagnosticPrinter.cpp revision 288943
1234287Sdim//===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// 2234287Sdim// 3234287Sdim// The LLVM Compiler Infrastructure 4234287Sdim// 5234287Sdim// This file is distributed under the University of Illinois Open Source 6234287Sdim// License. See LICENSE.TXT for details. 7234287Sdim// 8234287Sdim//===----------------------------------------------------------------------===// 9234287Sdim 10249423Sdim#include "clang/Frontend/SerializedDiagnosticPrinter.h" 11249423Sdim#include "clang/Basic/Diagnostic.h" 12243830Sdim#include "clang/Basic/DiagnosticOptions.h" 13249423Sdim#include "clang/Basic/FileManager.h" 14234287Sdim#include "clang/Basic/SourceManager.h" 15234287Sdim#include "clang/Basic/Version.h" 16249423Sdim#include "clang/Frontend/DiagnosticRenderer.h" 17280031Sdim#include "clang/Frontend/FrontendDiagnostic.h" 18280031Sdim#include "clang/Frontend/SerializedDiagnosticReader.h" 19280031Sdim#include "clang/Frontend/SerializedDiagnostics.h" 20280031Sdim#include "clang/Frontend/TextDiagnosticPrinter.h" 21234287Sdim#include "clang/Lex/Lexer.h" 22249423Sdim#include "llvm/ADT/DenseSet.h" 23288943Sdim#include "llvm/ADT/STLExtras.h" 24249423Sdim#include "llvm/ADT/SmallString.h" 25249423Sdim#include "llvm/ADT/StringRef.h" 26249423Sdim#include "llvm/Support/raw_ostream.h" 27249423Sdim#include <vector> 28234287Sdim 29234287Sdimusing namespace clang; 30234287Sdimusing namespace clang::serialized_diags; 31234287Sdim 32234287Sdimnamespace { 33234287Sdim 34234287Sdimclass AbbreviationMap { 35234287Sdim llvm::DenseMap<unsigned, unsigned> Abbrevs; 36234287Sdimpublic: 37234287Sdim AbbreviationMap() {} 38234287Sdim 39234287Sdim void set(unsigned recordID, unsigned abbrevID) { 40234287Sdim assert(Abbrevs.find(recordID) == Abbrevs.end() 41234287Sdim && "Abbreviation already set."); 42234287Sdim Abbrevs[recordID] = abbrevID; 43234287Sdim } 44234287Sdim 45234287Sdim unsigned get(unsigned recordID) { 46234287Sdim assert(Abbrevs.find(recordID) != Abbrevs.end() && 47234287Sdim "Abbreviation not set."); 48234287Sdim return Abbrevs[recordID]; 49234287Sdim } 50234287Sdim}; 51234287Sdim 52249423Sdimtypedef SmallVector<uint64_t, 64> RecordData; 53249423Sdimtypedef SmallVectorImpl<uint64_t> RecordDataImpl; 54234287Sdim 55234287Sdimclass SDiagsWriter; 56234287Sdim 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: 67276479Sdim void emitDiagnosticMessage(SourceLocation Loc, 68276479Sdim PresumedLoc PLoc, 69276479Sdim DiagnosticsEngine::Level Level, 70276479Sdim StringRef Message, 71276479Sdim ArrayRef<CharSourceRange> Ranges, 72276479Sdim const SourceManager *SM, 73276479Sdim DiagOrStoredDiag D) override; 74243830Sdim 75276479Sdim void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 76276479Sdim DiagnosticsEngine::Level Level, 77276479Sdim ArrayRef<CharSourceRange> Ranges, 78276479Sdim const SourceManager &SM) override {} 79243830Sdim 80276479Sdim void emitNote(SourceLocation Loc, StringRef Message, 81276479Sdim const SourceManager *SM) override; 82243830Sdim 83276479Sdim void emitCodeContext(SourceLocation Loc, 84276479Sdim DiagnosticsEngine::Level Level, 85276479Sdim SmallVectorImpl<CharSourceRange>& Ranges, 86276479Sdim ArrayRef<FixItHint> Hints, 87276479Sdim const SourceManager &SM) override; 88276479Sdim 89276479Sdim void beginDiagnostic(DiagOrStoredDiag D, 90276479Sdim DiagnosticsEngine::Level Level) override; 91276479Sdim void endDiagnostic(DiagOrStoredDiag D, 92276479Sdim DiagnosticsEngine::Level Level) override; 93234287Sdim}; 94280031Sdim 95280031Sdimtypedef llvm::DenseMap<unsigned, unsigned> AbbrevLookup; 96280031Sdim 97280031Sdimclass SDiagsMerger : SerializedDiagnosticReader { 98280031Sdim SDiagsWriter &Writer; 99280031Sdim AbbrevLookup FileLookup; 100280031Sdim AbbrevLookup CategoryLookup; 101280031Sdim AbbrevLookup DiagFlagLookup; 102280031Sdim 103280031Sdimpublic: 104280031Sdim SDiagsMerger(SDiagsWriter &Writer) 105280031Sdim : SerializedDiagnosticReader(), Writer(Writer) {} 106280031Sdim 107280031Sdim std::error_code mergeRecordsFromFile(const char *File) { 108280031Sdim return readDiagnostics(File); 109280031Sdim } 110280031Sdim 111280031Sdimprotected: 112280031Sdim std::error_code visitStartOfDiagnostic() override; 113280031Sdim std::error_code visitEndOfDiagnostic() override; 114280031Sdim std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override; 115280031Sdim std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override; 116280031Sdim std::error_code visitDiagnosticRecord( 117280031Sdim unsigned Severity, const serialized_diags::Location &Location, 118280031Sdim unsigned Category, unsigned Flag, StringRef Message) override; 119280031Sdim std::error_code visitFilenameRecord(unsigned ID, unsigned Size, 120280031Sdim unsigned Timestamp, 121280031Sdim StringRef Name) override; 122280031Sdim std::error_code visitFixitRecord(const serialized_diags::Location &Start, 123280031Sdim const serialized_diags::Location &End, 124280031Sdim StringRef CodeToInsert) override; 125280031Sdim std::error_code 126280031Sdim visitSourceRangeRecord(const serialized_diags::Location &Start, 127280031Sdim const serialized_diags::Location &End) override; 128280031Sdim 129280031Sdimprivate: 130280031Sdim std::error_code adjustSourceLocFilename(RecordData &Record, 131280031Sdim unsigned int offset); 132280031Sdim 133280031Sdim void adjustAbbrevID(RecordData &Record, AbbrevLookup &Lookup, 134280031Sdim unsigned NewAbbrev); 135280031Sdim 136280031Sdim void writeRecordWithAbbrev(unsigned ID, RecordData &Record); 137280031Sdim 138280031Sdim void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob); 139280031Sdim}; 140280031Sdim 141234287Sdimclass SDiagsWriter : public DiagnosticConsumer { 142234287Sdim friend class SDiagsRenderer; 143280031Sdim friend class SDiagsMerger; 144249423Sdim 145249423Sdim struct SharedState; 146249423Sdim 147249423Sdim explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State) 148280031Sdim : LangOpts(nullptr), OriginalInstance(false), MergeChildRecords(false), 149280031Sdim State(State) {} 150249423Sdim 151249423Sdimpublic: 152280031Sdim SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords) 153280031Sdim : LangOpts(nullptr), OriginalInstance(true), 154280031Sdim MergeChildRecords(MergeChildRecords), 155280031Sdim State(new SharedState(File, Diags)) { 156280031Sdim if (MergeChildRecords) 157280031Sdim RemoveOldDiagnostics(); 158234287Sdim EmitPreamble(); 159234287Sdim } 160243830Sdim 161288943Sdim ~SDiagsWriter() override {} 162276479Sdim 163234287Sdim void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 164276479Sdim const Diagnostic &Info) override; 165276479Sdim 166276479Sdim void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { 167234287Sdim LangOpts = &LO; 168234287Sdim } 169234287Sdim 170276479Sdim void finish() override; 171234287Sdim 172234287Sdimprivate: 173280031Sdim /// \brief Build a DiagnosticsEngine to emit diagnostics about the diagnostics 174280031Sdim DiagnosticsEngine *getMetaDiags(); 175280031Sdim 176280031Sdim /// \brief Remove old copies of the serialized diagnostics. This is necessary 177280031Sdim /// so that we can detect when subprocesses write diagnostics that we should 178280031Sdim /// merge into our own. 179280031Sdim void RemoveOldDiagnostics(); 180280031Sdim 181234287Sdim /// \brief Emit the preamble for the serialized diagnostics. 182234287Sdim void EmitPreamble(); 183234287Sdim 184234287Sdim /// \brief Emit the BLOCKINFO block. 185234287Sdim void EmitBlockInfoBlock(); 186234287Sdim 187234287Sdim /// \brief Emit the META data block. 188234287Sdim void EmitMetaBlock(); 189243830Sdim 190243830Sdim /// \brief Start a DIAG block. 191243830Sdim void EnterDiagBlock(); 192243830Sdim 193243830Sdim /// \brief End a DIAG block. 194243830Sdim void ExitDiagBlock(); 195243830Sdim 196243830Sdim /// \brief Emit a DIAG record. 197243830Sdim void EmitDiagnosticMessage(SourceLocation Loc, 198243830Sdim PresumedLoc PLoc, 199243830Sdim DiagnosticsEngine::Level Level, 200243830Sdim StringRef Message, 201243830Sdim const SourceManager *SM, 202243830Sdim DiagOrStoredDiag D); 203243830Sdim 204243830Sdim /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic. 205243830Sdim void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, 206243830Sdim ArrayRef<FixItHint> Hints, 207243830Sdim const SourceManager &SM); 208243830Sdim 209234287Sdim /// \brief Emit a record for a CharSourceRange. 210234287Sdim void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM); 211234287Sdim 212234287Sdim /// \brief Emit the string information for the category. 213234287Sdim unsigned getEmitCategory(unsigned category = 0); 214234287Sdim 215234287Sdim /// \brief Emit the string information for diagnostic flags. 216234287Sdim unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 217234287Sdim unsigned DiagID = 0); 218280031Sdim 219280031Sdim unsigned getEmitDiagnosticFlag(StringRef DiagName); 220280031Sdim 221234287Sdim /// \brief Emit (lazily) the file string and retrieved the file identifier. 222234287Sdim unsigned getEmitFile(const char *Filename); 223234287Sdim 224234287Sdim /// \brief Add SourceLocation information the specified record. 225239462Sdim void AddLocToRecord(SourceLocation Loc, const SourceManager *SM, 226234287Sdim PresumedLoc PLoc, RecordDataImpl &Record, 227234287Sdim unsigned TokSize = 0); 228234287Sdim 229234287Sdim /// \brief Add SourceLocation information the specified record. 230234287Sdim void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, 231239462Sdim const SourceManager *SM, 232234287Sdim unsigned TokSize = 0) { 233239462Sdim AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(), 234239462Sdim Record, TokSize); 235234287Sdim } 236234287Sdim 237234287Sdim /// \brief Add CharSourceRange information the specified record. 238234287Sdim void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record, 239234287Sdim const SourceManager &SM); 240234287Sdim 241249423Sdim /// \brief Language options, which can differ from one clone of this client 242249423Sdim /// to another. 243234287Sdim const LangOptions *LangOpts; 244234287Sdim 245249423Sdim /// \brief Whether this is the original instance (rather than one of its 246249423Sdim /// clones), responsible for writing the file at the end. 247249423Sdim bool OriginalInstance; 248234287Sdim 249280031Sdim /// \brief Whether this instance should aggregate diagnostics that are 250280031Sdim /// generated from child processes. 251280031Sdim bool MergeChildRecords; 252280031Sdim 253249423Sdim /// \brief State that is shared among the various clones of this diagnostic 254249423Sdim /// consumer. 255249423Sdim struct SharedState : RefCountedBase<SharedState> { 256280031Sdim SharedState(StringRef File, DiagnosticOptions *Diags) 257280031Sdim : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()), 258280031Sdim EmittedAnyDiagBlocks(false) {} 259234287Sdim 260249423Sdim /// \brief Diagnostic options. 261249423Sdim IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 262234287Sdim 263249423Sdim /// \brief The byte buffer for the serialized content. 264249423Sdim SmallString<1024> Buffer; 265234287Sdim 266249423Sdim /// \brief The BitStreamWriter for the serialized diagnostics. 267249423Sdim llvm::BitstreamWriter Stream; 268234287Sdim 269249423Sdim /// \brief The name of the diagnostics file. 270280031Sdim std::string OutputFile; 271243830Sdim 272249423Sdim /// \brief The set of constructed record abbreviations. 273249423Sdim AbbreviationMap Abbrevs; 274249423Sdim 275249423Sdim /// \brief A utility buffer for constructing record content. 276249423Sdim RecordData Record; 277249423Sdim 278249423Sdim /// \brief A text buffer for rendering diagnostic text. 279249423Sdim SmallString<256> diagBuf; 280249423Sdim 281249423Sdim /// \brief The collection of diagnostic categories used. 282249423Sdim llvm::DenseSet<unsigned> Categories; 283249423Sdim 284249423Sdim /// \brief The collection of files used. 285249423Sdim llvm::DenseMap<const char *, unsigned> Files; 286249423Sdim 287249423Sdim typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> > 288249423Sdim DiagFlagsTy; 289249423Sdim 290249423Sdim /// \brief Map for uniquing strings. 291249423Sdim DiagFlagsTy DiagFlags; 292249423Sdim 293249423Sdim /// \brief Whether we have already started emission of any DIAG blocks. Once 294249423Sdim /// this becomes \c true, we never close a DIAG block until we know that we're 295249423Sdim /// starting another one or we're done. 296249423Sdim bool EmittedAnyDiagBlocks; 297280031Sdim 298280031Sdim /// \brief Engine for emitting diagnostics about the diagnostics. 299280031Sdim std::unique_ptr<DiagnosticsEngine> MetaDiagnostics; 300249423Sdim }; 301249423Sdim 302249423Sdim /// \brief State shared among the various clones of this diagnostic consumer. 303249423Sdim IntrusiveRefCntPtr<SharedState> State; 304234287Sdim}; 305234287Sdim} // end anonymous namespace 306234287Sdim 307234287Sdimnamespace clang { 308234287Sdimnamespace serialized_diags { 309280031Sdimstd::unique_ptr<DiagnosticConsumer> 310280031Sdimcreate(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) { 311280031Sdim return llvm::make_unique<SDiagsWriter>(OutputFile, Diags, MergeChildRecords); 312234287Sdim} 313280031Sdim 314234287Sdim} // end namespace serialized_diags 315234287Sdim} // end namespace clang 316234287Sdim 317234287Sdim//===----------------------------------------------------------------------===// 318234287Sdim// Serialization methods. 319234287Sdim//===----------------------------------------------------------------------===// 320234287Sdim 321234287Sdim/// \brief Emits a block ID in the BLOCKINFO block. 322234287Sdimstatic void EmitBlockID(unsigned ID, const char *Name, 323234287Sdim llvm::BitstreamWriter &Stream, 324234287Sdim RecordDataImpl &Record) { 325234287Sdim Record.clear(); 326234287Sdim Record.push_back(ID); 327234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); 328234287Sdim 329234287Sdim // Emit the block name if present. 330276479Sdim if (!Name || Name[0] == 0) 331234287Sdim return; 332234287Sdim 333234287Sdim Record.clear(); 334234287Sdim 335234287Sdim while (*Name) 336234287Sdim Record.push_back(*Name++); 337234287Sdim 338234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); 339234287Sdim} 340234287Sdim 341234287Sdim/// \brief Emits a record ID in the BLOCKINFO block. 342234287Sdimstatic void EmitRecordID(unsigned ID, const char *Name, 343234287Sdim llvm::BitstreamWriter &Stream, 344234287Sdim RecordDataImpl &Record){ 345234287Sdim Record.clear(); 346234287Sdim Record.push_back(ID); 347234287Sdim 348234287Sdim while (*Name) 349234287Sdim Record.push_back(*Name++); 350234287Sdim 351234287Sdim Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); 352234287Sdim} 353234287Sdim 354234287Sdimvoid SDiagsWriter::AddLocToRecord(SourceLocation Loc, 355239462Sdim const SourceManager *SM, 356234287Sdim PresumedLoc PLoc, 357234287Sdim RecordDataImpl &Record, 358234287Sdim unsigned TokSize) { 359234287Sdim if (PLoc.isInvalid()) { 360234287Sdim // Emit a "sentinel" location. 361234287Sdim Record.push_back((unsigned)0); // File. 362234287Sdim Record.push_back((unsigned)0); // Line. 363234287Sdim Record.push_back((unsigned)0); // Column. 364234287Sdim Record.push_back((unsigned)0); // Offset. 365234287Sdim return; 366234287Sdim } 367234287Sdim 368234287Sdim Record.push_back(getEmitFile(PLoc.getFilename())); 369234287Sdim Record.push_back(PLoc.getLine()); 370234287Sdim Record.push_back(PLoc.getColumn()+TokSize); 371239462Sdim Record.push_back(SM->getFileOffset(Loc)); 372234287Sdim} 373234287Sdim 374234287Sdimvoid SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, 375234287Sdim RecordDataImpl &Record, 376234287Sdim const SourceManager &SM) { 377239462Sdim AddLocToRecord(Range.getBegin(), Record, &SM); 378234287Sdim unsigned TokSize = 0; 379234287Sdim if (Range.isTokenRange()) 380234287Sdim TokSize = Lexer::MeasureTokenLength(Range.getEnd(), 381234287Sdim SM, *LangOpts); 382234287Sdim 383239462Sdim AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); 384234287Sdim} 385234287Sdim 386234287Sdimunsigned SDiagsWriter::getEmitFile(const char *FileName){ 387234287Sdim if (!FileName) 388234287Sdim return 0; 389234287Sdim 390249423Sdim unsigned &entry = State->Files[FileName]; 391234287Sdim if (entry) 392234287Sdim return entry; 393234287Sdim 394234287Sdim // Lazily generate the record for the file. 395249423Sdim entry = State->Files.size(); 396234287Sdim RecordData Record; 397234287Sdim Record.push_back(RECORD_FILENAME); 398234287Sdim Record.push_back(entry); 399234287Sdim Record.push_back(0); // For legacy. 400234287Sdim Record.push_back(0); // For legacy. 401234287Sdim StringRef Name(FileName); 402234287Sdim Record.push_back(Name.size()); 403249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record, 404249423Sdim Name); 405234287Sdim 406234287Sdim return entry; 407234287Sdim} 408234287Sdim 409234287Sdimvoid SDiagsWriter::EmitCharSourceRange(CharSourceRange R, 410234287Sdim const SourceManager &SM) { 411249423Sdim State->Record.clear(); 412249423Sdim State->Record.push_back(RECORD_SOURCE_RANGE); 413249423Sdim AddCharSourceRangeToRecord(R, State->Record, SM); 414249423Sdim State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE), 415249423Sdim State->Record); 416234287Sdim} 417234287Sdim 418234287Sdim/// \brief Emits the preamble of the diagnostics file. 419234287Sdimvoid SDiagsWriter::EmitPreamble() { 420234287Sdim // Emit the file header. 421249423Sdim State->Stream.Emit((unsigned)'D', 8); 422249423Sdim State->Stream.Emit((unsigned)'I', 8); 423249423Sdim State->Stream.Emit((unsigned)'A', 8); 424249423Sdim State->Stream.Emit((unsigned)'G', 8); 425234287Sdim 426234287Sdim EmitBlockInfoBlock(); 427234287Sdim EmitMetaBlock(); 428234287Sdim} 429234287Sdim 430234287Sdimstatic void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 431234287Sdim using namespace llvm; 432234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID. 433234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line. 434234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column. 435234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset; 436234287Sdim} 437234287Sdim 438234287Sdimstatic void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) { 439234287Sdim AddSourceLocationAbbrev(Abbrev); 440234287Sdim AddSourceLocationAbbrev(Abbrev); 441234287Sdim} 442234287Sdim 443234287Sdimvoid SDiagsWriter::EmitBlockInfoBlock() { 444249423Sdim State->Stream.EnterBlockInfoBlock(3); 445234287Sdim 446234287Sdim using namespace llvm; 447249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 448249423Sdim RecordData &Record = State->Record; 449249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 450234287Sdim 451234287Sdim // ==---------------------------------------------------------------------==// 452234287Sdim // The subsequent records and Abbrevs are for the "Meta" block. 453234287Sdim // ==---------------------------------------------------------------------==// 454234287Sdim 455234287Sdim EmitBlockID(BLOCK_META, "Meta", Stream, Record); 456234287Sdim EmitRecordID(RECORD_VERSION, "Version", Stream, Record); 457234287Sdim BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); 458234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION)); 459234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); 460234287Sdim Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev)); 461234287Sdim 462234287Sdim // ==---------------------------------------------------------------------==// 463234287Sdim // The subsequent records and Abbrevs are for the "Diagnostic" block. 464234287Sdim // ==---------------------------------------------------------------------==// 465234287Sdim 466234287Sdim EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record); 467234287Sdim EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record); 468234287Sdim EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record); 469234287Sdim EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record); 470234287Sdim EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record); 471234287Sdim EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record); 472234287Sdim EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record); 473234287Sdim 474234287Sdim // Emit abbreviation for RECORD_DIAG. 475234287Sdim Abbrev = new BitCodeAbbrev(); 476234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG)); 477234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level. 478234287Sdim AddSourceLocationAbbrev(Abbrev); 479234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category. 480234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 481234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 482234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. 483234287Sdim Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 484234287Sdim 485234287Sdim // Emit abbrevation for RECORD_CATEGORY. 486234287Sdim Abbrev = new BitCodeAbbrev(); 487234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); 488234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID. 489234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size. 490234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. 491234287Sdim Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 492234287Sdim 493234287Sdim // Emit abbrevation for RECORD_SOURCE_RANGE. 494234287Sdim Abbrev = new BitCodeAbbrev(); 495234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE)); 496234287Sdim AddRangeLocationAbbrev(Abbrev); 497234287Sdim Abbrevs.set(RECORD_SOURCE_RANGE, 498234287Sdim Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); 499234287Sdim 500234287Sdim // Emit the abbreviation for RECORD_DIAG_FLAG. 501234287Sdim Abbrev = new BitCodeAbbrev(); 502234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG)); 503234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID. 504234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 505234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text. 506234287Sdim Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 507234287Sdim Abbrev)); 508234287Sdim 509234287Sdim // Emit the abbreviation for RECORD_FILENAME. 510234287Sdim Abbrev = new BitCodeAbbrev(); 511234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME)); 512234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID. 513234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size. 514234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time. 515234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 516234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text. 517234287Sdim Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 518234287Sdim Abbrev)); 519234287Sdim 520234287Sdim // Emit the abbreviation for RECORD_FIXIT. 521234287Sdim Abbrev = new BitCodeAbbrev(); 522234287Sdim Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT)); 523234287Sdim AddRangeLocationAbbrev(Abbrev); 524234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size. 525234287Sdim Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text. 526234287Sdim Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, 527234287Sdim Abbrev)); 528234287Sdim 529234287Sdim Stream.ExitBlock(); 530234287Sdim} 531234287Sdim 532234287Sdimvoid SDiagsWriter::EmitMetaBlock() { 533249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 534249423Sdim RecordData &Record = State->Record; 535249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 536249423Sdim 537234287Sdim Stream.EnterSubblock(BLOCK_META, 3); 538234287Sdim Record.clear(); 539234287Sdim Record.push_back(RECORD_VERSION); 540280031Sdim Record.push_back(VersionNumber); 541234287Sdim Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record); 542234287Sdim Stream.ExitBlock(); 543234287Sdim} 544234287Sdim 545234287Sdimunsigned SDiagsWriter::getEmitCategory(unsigned int category) { 546280031Sdim if (!State->Categories.insert(category).second) 547234287Sdim return category; 548280031Sdim 549234287Sdim // We use a local version of 'Record' so that we can be generating 550234287Sdim // another record when we lazily generate one for the category entry. 551234287Sdim RecordData Record; 552234287Sdim Record.push_back(RECORD_CATEGORY); 553234287Sdim Record.push_back(category); 554234287Sdim StringRef catName = DiagnosticIDs::getCategoryNameFromID(category); 555234287Sdim Record.push_back(catName.size()); 556249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record, 557249423Sdim catName); 558234287Sdim 559234287Sdim return category; 560234287Sdim} 561234287Sdim 562234287Sdimunsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, 563234287Sdim unsigned DiagID) { 564234287Sdim if (DiagLevel == DiagnosticsEngine::Note) 565234287Sdim return 0; // No flag for notes. 566234287Sdim 567234287Sdim StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID); 568280031Sdim return getEmitDiagnosticFlag(FlagName); 569280031Sdim} 570280031Sdim 571280031Sdimunsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) { 572234287Sdim if (FlagName.empty()) 573234287Sdim return 0; 574234287Sdim 575234287Sdim // Here we assume that FlagName points to static data whose pointer 576234287Sdim // value is fixed. This allows us to unique by diagnostic groups. 577234287Sdim const void *data = FlagName.data(); 578249423Sdim std::pair<unsigned, StringRef> &entry = State->DiagFlags[data]; 579234287Sdim if (entry.first == 0) { 580249423Sdim entry.first = State->DiagFlags.size(); 581234287Sdim entry.second = FlagName; 582234287Sdim 583234287Sdim // Lazily emit the string in a separate record. 584234287Sdim RecordData Record; 585234287Sdim Record.push_back(RECORD_DIAG_FLAG); 586234287Sdim Record.push_back(entry.first); 587234287Sdim Record.push_back(FlagName.size()); 588249423Sdim State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG), 589249423Sdim Record, FlagName); 590234287Sdim } 591234287Sdim 592234287Sdim return entry.first; 593234287Sdim} 594234287Sdim 595234287Sdimvoid SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 596234287Sdim const Diagnostic &Info) { 597243830Sdim // Enter the block for a non-note diagnostic immediately, rather than waiting 598243830Sdim // for beginDiagnostic, in case associated notes are emitted before we get 599243830Sdim // there. 600234287Sdim if (DiagLevel != DiagnosticsEngine::Note) { 601249423Sdim if (State->EmittedAnyDiagBlocks) 602243830Sdim ExitDiagBlock(); 603243830Sdim 604243830Sdim EnterDiagBlock(); 605249423Sdim State->EmittedAnyDiagBlocks = true; 606234287Sdim } 607234287Sdim 608234287Sdim // Compute the diagnostic text. 609249423Sdim State->diagBuf.clear(); 610249423Sdim Info.FormatDiagnostic(State->diagBuf); 611234287Sdim 612243830Sdim if (Info.getLocation().isInvalid()) { 613243830Sdim // Special-case diagnostics with no location. We may not have entered a 614243830Sdim // source file in this case, so we can't use the normal DiagnosticsRenderer 615243830Sdim // machinery. 616249423Sdim 617249423Sdim // Make sure we bracket all notes as "sub-diagnostics". This matches 618249423Sdim // the behavior in SDiagsRenderer::emitDiagnostic(). 619249423Sdim if (DiagLevel == DiagnosticsEngine::Note) 620249423Sdim EnterDiagBlock(); 621249423Sdim 622243830Sdim EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel, 623276479Sdim State->diagBuf, nullptr, &Info); 624249423Sdim 625249423Sdim if (DiagLevel == DiagnosticsEngine::Note) 626249423Sdim ExitDiagBlock(); 627249423Sdim 628243830Sdim return; 629243830Sdim } 630243830Sdim 631243830Sdim assert(Info.hasSourceManager() && LangOpts && 632243830Sdim "Unexpected diagnostic with valid location outside of a source file"); 633249423Sdim SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts); 634234287Sdim Renderer.emitDiagnostic(Info.getLocation(), DiagLevel, 635288943Sdim State->diagBuf, 636234287Sdim Info.getRanges(), 637276479Sdim Info.getFixItHints(), 638243830Sdim &Info.getSourceManager(), 639234287Sdim &Info); 640234287Sdim} 641234287Sdim 642276479Sdimstatic serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) { 643276479Sdim switch (Level) { 644276479Sdim#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X; 645276479Sdim CASE(Ignored) 646276479Sdim CASE(Note) 647276479Sdim CASE(Remark) 648276479Sdim CASE(Warning) 649276479Sdim CASE(Error) 650276479Sdim CASE(Fatal) 651276479Sdim#undef CASE 652276479Sdim } 653276479Sdim 654276479Sdim llvm_unreachable("invalid diagnostic level"); 655276479Sdim} 656276479Sdim 657243830Sdimvoid SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc, 658243830Sdim PresumedLoc PLoc, 659243830Sdim DiagnosticsEngine::Level Level, 660243830Sdim StringRef Message, 661243830Sdim const SourceManager *SM, 662243830Sdim DiagOrStoredDiag D) { 663249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 664249423Sdim RecordData &Record = State->Record; 665249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 666249423Sdim 667243830Sdim // Emit the RECORD_DIAG record. 668243830Sdim Record.clear(); 669243830Sdim Record.push_back(RECORD_DIAG); 670276479Sdim Record.push_back(getStableLevel(Level)); 671243830Sdim AddLocToRecord(Loc, SM, PLoc, Record); 672243830Sdim 673243830Sdim if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) { 674243830Sdim // Emit the category string lazily and get the category ID. 675243830Sdim unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID()); 676243830Sdim Record.push_back(getEmitCategory(DiagID)); 677243830Sdim // Emit the diagnostic flag string lazily and get the mapped ID. 678243830Sdim Record.push_back(getEmitDiagnosticFlag(Level, Info->getID())); 679243830Sdim } else { 680243830Sdim Record.push_back(getEmitCategory()); 681243830Sdim Record.push_back(getEmitDiagnosticFlag(Level)); 682243830Sdim } 683243830Sdim 684243830Sdim Record.push_back(Message.size()); 685243830Sdim Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message); 686243830Sdim} 687243830Sdim 688234287Sdimvoid 689234287SdimSDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc, 690234287Sdim PresumedLoc PLoc, 691234287Sdim DiagnosticsEngine::Level Level, 692234287Sdim StringRef Message, 693234287Sdim ArrayRef<clang::CharSourceRange> Ranges, 694239462Sdim const SourceManager *SM, 695234287Sdim DiagOrStoredDiag D) { 696243830Sdim Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D); 697243830Sdim} 698234287Sdim 699243830Sdimvoid SDiagsWriter::EnterDiagBlock() { 700249423Sdim State->Stream.EnterSubblock(BLOCK_DIAG, 4); 701243830Sdim} 702234287Sdim 703243830Sdimvoid SDiagsWriter::ExitDiagBlock() { 704249423Sdim State->Stream.ExitBlock(); 705234287Sdim} 706234287Sdim 707234287Sdimvoid SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D, 708234287Sdim DiagnosticsEngine::Level Level) { 709243830Sdim if (Level == DiagnosticsEngine::Note) 710243830Sdim Writer.EnterDiagBlock(); 711234287Sdim} 712234287Sdim 713234287Sdimvoid SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D, 714234287Sdim DiagnosticsEngine::Level Level) { 715243830Sdim // Only end note diagnostics here, because we can't be sure when we've seen 716243830Sdim // the last note associated with a non-note diagnostic. 717243830Sdim if (Level == DiagnosticsEngine::Note) 718243830Sdim Writer.ExitDiagBlock(); 719234287Sdim} 720234287Sdim 721243830Sdimvoid SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, 722243830Sdim ArrayRef<FixItHint> Hints, 723243830Sdim const SourceManager &SM) { 724249423Sdim llvm::BitstreamWriter &Stream = State->Stream; 725249423Sdim RecordData &Record = State->Record; 726249423Sdim AbbreviationMap &Abbrevs = State->Abbrevs; 727249423Sdim 728234287Sdim // Emit Source Ranges. 729243830Sdim for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); 730243830Sdim I != E; ++I) 731243830Sdim if (I->isValid()) 732243830Sdim EmitCharSourceRange(*I, SM); 733243830Sdim 734234287Sdim // Emit FixIts. 735243830Sdim for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 736243830Sdim I != E; ++I) { 737243830Sdim const FixItHint &Fix = *I; 738243830Sdim if (Fix.isNull()) 739234287Sdim continue; 740243830Sdim Record.clear(); 741243830Sdim Record.push_back(RECORD_FIXIT); 742243830Sdim AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM); 743243830Sdim Record.push_back(Fix.CodeToInsert.size()); 744243830Sdim Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record, 745243830Sdim Fix.CodeToInsert); 746234287Sdim } 747234287Sdim} 748234287Sdim 749243830Sdimvoid SDiagsRenderer::emitCodeContext(SourceLocation Loc, 750243830Sdim DiagnosticsEngine::Level Level, 751243830Sdim SmallVectorImpl<CharSourceRange> &Ranges, 752243830Sdim ArrayRef<FixItHint> Hints, 753243830Sdim const SourceManager &SM) { 754243830Sdim Writer.EmitCodeContext(Ranges, Hints, SM); 755243830Sdim} 756243830Sdim 757239462Sdimvoid SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message, 758239462Sdim const SourceManager *SM) { 759243830Sdim Writer.EnterDiagBlock(); 760243830Sdim PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc(); 761243830Sdim Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, 762243830Sdim Message, SM, DiagOrStoredDiag()); 763243830Sdim Writer.ExitDiagBlock(); 764234287Sdim} 765234287Sdim 766280031SdimDiagnosticsEngine *SDiagsWriter::getMetaDiags() { 767280031Sdim // FIXME: It's slightly absurd to create a new diagnostics engine here, but 768280031Sdim // the other options that are available today are worse: 769280031Sdim // 770280031Sdim // 1. Teach DiagnosticsConsumers to emit diagnostics to the engine they are a 771280031Sdim // part of. The DiagnosticsEngine would need to know not to send 772280031Sdim // diagnostics back to the consumer that failed. This would require us to 773280031Sdim // rework ChainedDiagnosticsConsumer and teach the engine about multiple 774280031Sdim // consumers, which is difficult today because most APIs interface with 775280031Sdim // consumers rather than the engine itself. 776280031Sdim // 777280031Sdim // 2. Pass a DiagnosticsEngine to SDiagsWriter on creation - this would need 778280031Sdim // to be distinct from the engine the writer was being added to and would 779280031Sdim // normally not be used. 780280031Sdim if (!State->MetaDiagnostics) { 781280031Sdim IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs()); 782280031Sdim auto Client = 783280031Sdim new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get()); 784280031Sdim State->MetaDiagnostics = llvm::make_unique<DiagnosticsEngine>( 785280031Sdim IDs, State->DiagOpts.get(), Client); 786280031Sdim } 787280031Sdim return State->MetaDiagnostics.get(); 788280031Sdim} 789280031Sdim 790280031Sdimvoid SDiagsWriter::RemoveOldDiagnostics() { 791280031Sdim if (!llvm::sys::fs::remove(State->OutputFile)) 792280031Sdim return; 793280031Sdim 794280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure); 795280031Sdim // Disable merging child records, as whatever is in this file may be 796280031Sdim // misleading. 797280031Sdim MergeChildRecords = false; 798280031Sdim} 799280031Sdim 800234287Sdimvoid SDiagsWriter::finish() { 801249423Sdim // The original instance is responsible for writing the file. 802249423Sdim if (!OriginalInstance) 803249423Sdim return; 804249423Sdim 805243830Sdim // Finish off any diagnostic we were in the process of emitting. 806249423Sdim if (State->EmittedAnyDiagBlocks) 807243830Sdim ExitDiagBlock(); 808234287Sdim 809280031Sdim if (MergeChildRecords) { 810280031Sdim if (!State->EmittedAnyDiagBlocks) 811280031Sdim // We have no diagnostics of our own, so we can just leave the child 812280031Sdim // process' output alone 813280031Sdim return; 814280031Sdim 815280031Sdim if (llvm::sys::fs::exists(State->OutputFile)) 816280031Sdim if (SDiagsMerger(*this).mergeRecordsFromFile(State->OutputFile.c_str())) 817280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure); 818280031Sdim } 819280031Sdim 820280031Sdim std::error_code EC; 821280031Sdim auto OS = llvm::make_unique<llvm::raw_fd_ostream>(State->OutputFile.c_str(), 822280031Sdim EC, llvm::sys::fs::F_None); 823280031Sdim if (EC) { 824280031Sdim getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure) 825280031Sdim << State->OutputFile << EC.message(); 826280031Sdim return; 827280031Sdim } 828280031Sdim 829234287Sdim // Write the generated bitstream to "Out". 830280031Sdim OS->write((char *)&State->Buffer.front(), State->Buffer.size()); 831280031Sdim OS->flush(); 832280031Sdim} 833243830Sdim 834280031Sdimstd::error_code SDiagsMerger::visitStartOfDiagnostic() { 835280031Sdim Writer.EnterDiagBlock(); 836280031Sdim return std::error_code(); 837234287Sdim} 838280031Sdim 839280031Sdimstd::error_code SDiagsMerger::visitEndOfDiagnostic() { 840280031Sdim Writer.ExitDiagBlock(); 841280031Sdim return std::error_code(); 842280031Sdim} 843280031Sdim 844280031Sdimstd::error_code 845280031SdimSDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start, 846280031Sdim const serialized_diags::Location &End) { 847280031Sdim RecordData Record; 848280031Sdim Record.push_back(RECORD_SOURCE_RANGE); 849280031Sdim Record.push_back(FileLookup[Start.FileID]); 850280031Sdim Record.push_back(Start.Line); 851280031Sdim Record.push_back(Start.Col); 852280031Sdim Record.push_back(Start.Offset); 853280031Sdim Record.push_back(FileLookup[End.FileID]); 854280031Sdim Record.push_back(End.Line); 855280031Sdim Record.push_back(End.Col); 856280031Sdim Record.push_back(End.Offset); 857280031Sdim 858280031Sdim Writer.State->Stream.EmitRecordWithAbbrev( 859280031Sdim Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record); 860280031Sdim return std::error_code(); 861280031Sdim} 862280031Sdim 863280031Sdimstd::error_code SDiagsMerger::visitDiagnosticRecord( 864280031Sdim unsigned Severity, const serialized_diags::Location &Location, 865280031Sdim unsigned Category, unsigned Flag, StringRef Message) { 866280031Sdim RecordData MergedRecord; 867280031Sdim MergedRecord.push_back(RECORD_DIAG); 868280031Sdim MergedRecord.push_back(Severity); 869280031Sdim MergedRecord.push_back(FileLookup[Location.FileID]); 870280031Sdim MergedRecord.push_back(Location.Line); 871280031Sdim MergedRecord.push_back(Location.Col); 872280031Sdim MergedRecord.push_back(Location.Offset); 873280031Sdim MergedRecord.push_back(CategoryLookup[Category]); 874280031Sdim MergedRecord.push_back(Flag ? DiagFlagLookup[Flag] : 0); 875280031Sdim MergedRecord.push_back(Message.size()); 876280031Sdim 877280031Sdim Writer.State->Stream.EmitRecordWithBlob( 878280031Sdim Writer.State->Abbrevs.get(RECORD_DIAG), MergedRecord, Message); 879280031Sdim return std::error_code(); 880280031Sdim} 881280031Sdim 882280031Sdimstd::error_code 883280031SdimSDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start, 884280031Sdim const serialized_diags::Location &End, 885280031Sdim StringRef Text) { 886280031Sdim RecordData Record; 887280031Sdim Record.push_back(RECORD_FIXIT); 888280031Sdim Record.push_back(FileLookup[Start.FileID]); 889280031Sdim Record.push_back(Start.Line); 890280031Sdim Record.push_back(Start.Col); 891280031Sdim Record.push_back(Start.Offset); 892280031Sdim Record.push_back(FileLookup[End.FileID]); 893280031Sdim Record.push_back(End.Line); 894280031Sdim Record.push_back(End.Col); 895280031Sdim Record.push_back(End.Offset); 896280031Sdim Record.push_back(Text.size()); 897280031Sdim 898280031Sdim Writer.State->Stream.EmitRecordWithBlob( 899280031Sdim Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text); 900280031Sdim return std::error_code(); 901280031Sdim} 902280031Sdim 903280031Sdimstd::error_code SDiagsMerger::visitFilenameRecord(unsigned ID, unsigned Size, 904280031Sdim unsigned Timestamp, 905280031Sdim StringRef Name) { 906280031Sdim FileLookup[ID] = Writer.getEmitFile(Name.str().c_str()); 907280031Sdim return std::error_code(); 908280031Sdim} 909280031Sdim 910280031Sdimstd::error_code SDiagsMerger::visitCategoryRecord(unsigned ID, StringRef Name) { 911280031Sdim CategoryLookup[ID] = Writer.getEmitCategory(ID); 912280031Sdim return std::error_code(); 913280031Sdim} 914280031Sdim 915280031Sdimstd::error_code SDiagsMerger::visitDiagFlagRecord(unsigned ID, StringRef Name) { 916280031Sdim DiagFlagLookup[ID] = Writer.getEmitDiagnosticFlag(Name); 917280031Sdim return std::error_code(); 918280031Sdim} 919