Home | History | Annotate | Line # | Download | only in Frontend
      1 //===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "clang/Frontend/SerializedDiagnosticPrinter.h"
     10 #include "clang/Basic/Diagnostic.h"
     11 #include "clang/Basic/DiagnosticOptions.h"
     12 #include "clang/Basic/SourceManager.h"
     13 #include "clang/Frontend/DiagnosticRenderer.h"
     14 #include "clang/Frontend/FrontendDiagnostic.h"
     15 #include "clang/Frontend/SerializedDiagnosticReader.h"
     16 #include "clang/Frontend/SerializedDiagnostics.h"
     17 #include "clang/Frontend/TextDiagnosticPrinter.h"
     18 #include "clang/Lex/Lexer.h"
     19 #include "llvm/ADT/DenseSet.h"
     20 #include "llvm/ADT/STLExtras.h"
     21 #include "llvm/ADT/SmallString.h"
     22 #include "llvm/ADT/StringRef.h"
     23 #include "llvm/Bitstream/BitCodes.h"
     24 #include "llvm/Bitstream/BitstreamReader.h"
     25 #include "llvm/Support/FileSystem.h"
     26 #include "llvm/Support/raw_ostream.h"
     27 #include <utility>
     28 
     29 using namespace clang;
     30 using namespace clang::serialized_diags;
     31 
     32 namespace {
     33 
     34 class AbbreviationMap {
     35   llvm::DenseMap<unsigned, unsigned> Abbrevs;
     36 public:
     37   AbbreviationMap() {}
     38 
     39   void set(unsigned recordID, unsigned abbrevID) {
     40     assert(Abbrevs.find(recordID) == Abbrevs.end()
     41            && "Abbreviation already set.");
     42     Abbrevs[recordID] = abbrevID;
     43   }
     44 
     45   unsigned get(unsigned recordID) {
     46     assert(Abbrevs.find(recordID) != Abbrevs.end() &&
     47            "Abbreviation not set.");
     48     return Abbrevs[recordID];
     49   }
     50 };
     51 
     52 typedef SmallVector<uint64_t, 64> RecordData;
     53 typedef SmallVectorImpl<uint64_t> RecordDataImpl;
     54 typedef ArrayRef<uint64_t> RecordDataRef;
     55 
     56 class SDiagsWriter;
     57 
     58 class SDiagsRenderer : public DiagnosticNoteRenderer {
     59   SDiagsWriter &Writer;
     60 public:
     61   SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts,
     62                  DiagnosticOptions *DiagOpts)
     63     : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
     64 
     65   ~SDiagsRenderer() override {}
     66 
     67 protected:
     68   void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
     69                              DiagnosticsEngine::Level Level, StringRef Message,
     70                              ArrayRef<CharSourceRange> Ranges,
     71                              DiagOrStoredDiag D) override;
     72 
     73   void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
     74                          DiagnosticsEngine::Level Level,
     75                          ArrayRef<CharSourceRange> Ranges) override {}
     76 
     77   void emitNote(FullSourceLoc Loc, StringRef Message) override;
     78 
     79   void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
     80                        SmallVectorImpl<CharSourceRange> &Ranges,
     81                        ArrayRef<FixItHint> Hints) override;
     82 
     83   void beginDiagnostic(DiagOrStoredDiag D,
     84                        DiagnosticsEngine::Level Level) override;
     85   void endDiagnostic(DiagOrStoredDiag D,
     86                      DiagnosticsEngine::Level Level) override;
     87 };
     88 
     89 typedef llvm::DenseMap<unsigned, unsigned> AbbrevLookup;
     90 
     91 class SDiagsMerger : SerializedDiagnosticReader {
     92   SDiagsWriter &Writer;
     93   AbbrevLookup FileLookup;
     94   AbbrevLookup CategoryLookup;
     95   AbbrevLookup DiagFlagLookup;
     96 
     97 public:
     98   SDiagsMerger(SDiagsWriter &Writer)
     99       : SerializedDiagnosticReader(), Writer(Writer) {}
    100 
    101   std::error_code mergeRecordsFromFile(const char *File) {
    102     return readDiagnostics(File);
    103   }
    104 
    105 protected:
    106   std::error_code visitStartOfDiagnostic() override;
    107   std::error_code visitEndOfDiagnostic() override;
    108   std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
    109   std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
    110   std::error_code visitDiagnosticRecord(
    111       unsigned Severity, const serialized_diags::Location &Location,
    112       unsigned Category, unsigned Flag, StringRef Message) override;
    113   std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
    114                                       unsigned Timestamp,
    115                                       StringRef Name) override;
    116   std::error_code visitFixitRecord(const serialized_diags::Location &Start,
    117                                    const serialized_diags::Location &End,
    118                                    StringRef CodeToInsert) override;
    119   std::error_code
    120   visitSourceRangeRecord(const serialized_diags::Location &Start,
    121                          const serialized_diags::Location &End) override;
    122 
    123 private:
    124   std::error_code adjustSourceLocFilename(RecordData &Record,
    125                                           unsigned int offset);
    126 
    127   void adjustAbbrevID(RecordData &Record, AbbrevLookup &Lookup,
    128                       unsigned NewAbbrev);
    129 
    130   void writeRecordWithAbbrev(unsigned ID, RecordData &Record);
    131 
    132   void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob);
    133 };
    134 
    135 class SDiagsWriter : public DiagnosticConsumer {
    136   friend class SDiagsRenderer;
    137   friend class SDiagsMerger;
    138 
    139   struct SharedState;
    140 
    141   explicit SDiagsWriter(std::shared_ptr<SharedState> State)
    142       : LangOpts(nullptr), OriginalInstance(false), MergeChildRecords(false),
    143         State(std::move(State)) {}
    144 
    145 public:
    146   SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords)
    147       : LangOpts(nullptr), OriginalInstance(true),
    148         MergeChildRecords(MergeChildRecords),
    149         State(std::make_shared<SharedState>(File, Diags)) {
    150     if (MergeChildRecords)
    151       RemoveOldDiagnostics();
    152     EmitPreamble();
    153   }
    154 
    155   ~SDiagsWriter() override {}
    156 
    157   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
    158                         const Diagnostic &Info) override;
    159 
    160   void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
    161     LangOpts = &LO;
    162   }
    163 
    164   void finish() override;
    165 
    166 private:
    167   /// Build a DiagnosticsEngine to emit diagnostics about the diagnostics
    168   DiagnosticsEngine *getMetaDiags();
    169 
    170   /// Remove old copies of the serialized diagnostics. This is necessary
    171   /// so that we can detect when subprocesses write diagnostics that we should
    172   /// merge into our own.
    173   void RemoveOldDiagnostics();
    174 
    175   /// Emit the preamble for the serialized diagnostics.
    176   void EmitPreamble();
    177 
    178   /// Emit the BLOCKINFO block.
    179   void EmitBlockInfoBlock();
    180 
    181   /// Emit the META data block.
    182   void EmitMetaBlock();
    183 
    184   /// Start a DIAG block.
    185   void EnterDiagBlock();
    186 
    187   /// End a DIAG block.
    188   void ExitDiagBlock();
    189 
    190   /// Emit a DIAG record.
    191   void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
    192                              DiagnosticsEngine::Level Level, StringRef Message,
    193                              DiagOrStoredDiag D);
    194 
    195   /// Emit FIXIT and SOURCE_RANGE records for a diagnostic.
    196   void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
    197                        ArrayRef<FixItHint> Hints,
    198                        const SourceManager &SM);
    199 
    200   /// Emit a record for a CharSourceRange.
    201   void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
    202 
    203   /// Emit the string information for the category.
    204   unsigned getEmitCategory(unsigned category = 0);
    205 
    206   /// Emit the string information for diagnostic flags.
    207   unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
    208                                  unsigned DiagID = 0);
    209 
    210   unsigned getEmitDiagnosticFlag(StringRef DiagName);
    211 
    212   /// Emit (lazily) the file string and retrieved the file identifier.
    213   unsigned getEmitFile(const char *Filename);
    214 
    215   /// Add SourceLocation information the specified record.
    216   void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
    217                       RecordDataImpl &Record, unsigned TokSize = 0);
    218 
    219   /// Add SourceLocation information the specified record.
    220   void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record,
    221                       unsigned TokSize = 0) {
    222     AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(),
    223                    Record, TokSize);
    224   }
    225 
    226   /// Add CharSourceRange information the specified record.
    227   void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
    228                                   const SourceManager &SM);
    229 
    230   /// Language options, which can differ from one clone of this client
    231   /// to another.
    232   const LangOptions *LangOpts;
    233 
    234   /// Whether this is the original instance (rather than one of its
    235   /// clones), responsible for writing the file at the end.
    236   bool OriginalInstance;
    237 
    238   /// Whether this instance should aggregate diagnostics that are
    239   /// generated from child processes.
    240   bool MergeChildRecords;
    241 
    242   /// Whether we've started finishing and tearing down this instance.
    243   bool IsFinishing = false;
    244 
    245   /// State that is shared among the various clones of this diagnostic
    246   /// consumer.
    247   struct SharedState {
    248     SharedState(StringRef File, DiagnosticOptions *Diags)
    249         : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()),
    250           EmittedAnyDiagBlocks(false) {}
    251 
    252     /// Diagnostic options.
    253     IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
    254 
    255     /// The byte buffer for the serialized content.
    256     SmallString<1024> Buffer;
    257 
    258     /// The BitStreamWriter for the serialized diagnostics.
    259     llvm::BitstreamWriter Stream;
    260 
    261     /// The name of the diagnostics file.
    262     std::string OutputFile;
    263 
    264     /// The set of constructed record abbreviations.
    265     AbbreviationMap Abbrevs;
    266 
    267     /// A utility buffer for constructing record content.
    268     RecordData Record;
    269 
    270     /// A text buffer for rendering diagnostic text.
    271     SmallString<256> diagBuf;
    272 
    273     /// The collection of diagnostic categories used.
    274     llvm::DenseSet<unsigned> Categories;
    275 
    276     /// The collection of files used.
    277     llvm::DenseMap<const char *, unsigned> Files;
    278 
    279     typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
    280     DiagFlagsTy;
    281 
    282     /// Map for uniquing strings.
    283     DiagFlagsTy DiagFlags;
    284 
    285     /// Whether we have already started emission of any DIAG blocks. Once
    286     /// this becomes \c true, we never close a DIAG block until we know that we're
    287     /// starting another one or we're done.
    288     bool EmittedAnyDiagBlocks;
    289 
    290     /// Engine for emitting diagnostics about the diagnostics.
    291     std::unique_ptr<DiagnosticsEngine> MetaDiagnostics;
    292   };
    293 
    294   /// State shared among the various clones of this diagnostic consumer.
    295   std::shared_ptr<SharedState> State;
    296 };
    297 } // end anonymous namespace
    298 
    299 namespace clang {
    300 namespace serialized_diags {
    301 std::unique_ptr<DiagnosticConsumer>
    302 create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) {
    303   return std::make_unique<SDiagsWriter>(OutputFile, Diags, MergeChildRecords);
    304 }
    305 
    306 } // end namespace serialized_diags
    307 } // end namespace clang
    308 
    309 //===----------------------------------------------------------------------===//
    310 // Serialization methods.
    311 //===----------------------------------------------------------------------===//
    312 
    313 /// Emits a block ID in the BLOCKINFO block.
    314 static void EmitBlockID(unsigned ID, const char *Name,
    315                         llvm::BitstreamWriter &Stream,
    316                         RecordDataImpl &Record) {
    317   Record.clear();
    318   Record.push_back(ID);
    319   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
    320 
    321   // Emit the block name if present.
    322   if (!Name || Name[0] == 0)
    323     return;
    324 
    325   Record.clear();
    326 
    327   while (*Name)
    328     Record.push_back(*Name++);
    329 
    330   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
    331 }
    332 
    333 /// Emits a record ID in the BLOCKINFO block.
    334 static void EmitRecordID(unsigned ID, const char *Name,
    335                          llvm::BitstreamWriter &Stream,
    336                          RecordDataImpl &Record){
    337   Record.clear();
    338   Record.push_back(ID);
    339 
    340   while (*Name)
    341     Record.push_back(*Name++);
    342 
    343   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
    344 }
    345 
    346 void SDiagsWriter::AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc,
    347                                   RecordDataImpl &Record, unsigned TokSize) {
    348   if (PLoc.isInvalid()) {
    349     // Emit a "sentinel" location.
    350     Record.push_back((unsigned)0); // File.
    351     Record.push_back((unsigned)0); // Line.
    352     Record.push_back((unsigned)0); // Column.
    353     Record.push_back((unsigned)0); // Offset.
    354     return;
    355   }
    356 
    357   Record.push_back(getEmitFile(PLoc.getFilename()));
    358   Record.push_back(PLoc.getLine());
    359   Record.push_back(PLoc.getColumn()+TokSize);
    360   Record.push_back(Loc.getFileOffset());
    361 }
    362 
    363 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
    364                                               RecordDataImpl &Record,
    365                                               const SourceManager &SM) {
    366   AddLocToRecord(FullSourceLoc(Range.getBegin(), SM), Record);
    367   unsigned TokSize = 0;
    368   if (Range.isTokenRange())
    369     TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
    370                                         SM, *LangOpts);
    371 
    372   AddLocToRecord(FullSourceLoc(Range.getEnd(), SM), Record, TokSize);
    373 }
    374 
    375 unsigned SDiagsWriter::getEmitFile(const char *FileName){
    376   if (!FileName)
    377     return 0;
    378 
    379   unsigned &entry = State->Files[FileName];
    380   if (entry)
    381     return entry;
    382 
    383   // Lazily generate the record for the file.
    384   entry = State->Files.size();
    385   StringRef Name(FileName);
    386   RecordData::value_type Record[] = {RECORD_FILENAME, entry, 0 /* For legacy */,
    387                                      0 /* For legacy */, Name.size()};
    388   State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
    389                                    Name);
    390 
    391   return entry;
    392 }
    393 
    394 void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
    395                                        const SourceManager &SM) {
    396   State->Record.clear();
    397   State->Record.push_back(RECORD_SOURCE_RANGE);
    398   AddCharSourceRangeToRecord(R, State->Record, SM);
    399   State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE),
    400                                      State->Record);
    401 }
    402 
    403 /// Emits the preamble of the diagnostics file.
    404 void SDiagsWriter::EmitPreamble() {
    405   // Emit the file header.
    406   State->Stream.Emit((unsigned)'D', 8);
    407   State->Stream.Emit((unsigned)'I', 8);
    408   State->Stream.Emit((unsigned)'A', 8);
    409   State->Stream.Emit((unsigned)'G', 8);
    410 
    411   EmitBlockInfoBlock();
    412   EmitMetaBlock();
    413 }
    414 
    415 static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) {
    416   using namespace llvm;
    417   Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
    418   Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
    419   Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
    420   Abbrev.Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
    421 }
    422 
    423 static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev &Abbrev) {
    424   AddSourceLocationAbbrev(Abbrev);
    425   AddSourceLocationAbbrev(Abbrev);
    426 }
    427 
    428 void SDiagsWriter::EmitBlockInfoBlock() {
    429   State->Stream.EnterBlockInfoBlock();
    430 
    431   using namespace llvm;
    432   llvm::BitstreamWriter &Stream = State->Stream;
    433   RecordData &Record = State->Record;
    434   AbbreviationMap &Abbrevs = State->Abbrevs;
    435 
    436   // ==---------------------------------------------------------------------==//
    437   // The subsequent records and Abbrevs are for the "Meta" block.
    438   // ==---------------------------------------------------------------------==//
    439 
    440   EmitBlockID(BLOCK_META, "Meta", Stream, Record);
    441   EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
    442   auto Abbrev = std::make_shared<BitCodeAbbrev>();
    443   Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
    444   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
    445   Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
    446 
    447   // ==---------------------------------------------------------------------==//
    448   // The subsequent records and Abbrevs are for the "Diagnostic" block.
    449   // ==---------------------------------------------------------------------==//
    450 
    451   EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
    452   EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
    453   EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
    454   EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
    455   EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
    456   EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
    457   EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
    458 
    459   // Emit abbreviation for RECORD_DIAG.
    460   Abbrev = std::make_shared<BitCodeAbbrev>();
    461   Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
    462   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));  // Diag level.
    463   AddSourceLocationAbbrev(*Abbrev);
    464   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
    465   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
    466   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Text size.
    467   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
    468   Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
    469 
    470   // Emit abbreviation for RECORD_CATEGORY.
    471   Abbrev = std::make_shared<BitCodeAbbrev>();
    472   Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
    473   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
    474   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));  // Text size.
    475   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // Category text.
    476   Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
    477 
    478   // Emit abbreviation for RECORD_SOURCE_RANGE.
    479   Abbrev = std::make_shared<BitCodeAbbrev>();
    480   Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
    481   AddRangeLocationAbbrev(*Abbrev);
    482   Abbrevs.set(RECORD_SOURCE_RANGE,
    483               Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
    484 
    485   // Emit the abbreviation for RECORD_DIAG_FLAG.
    486   Abbrev = std::make_shared<BitCodeAbbrev>();
    487   Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
    488   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
    489   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
    490   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
    491   Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
    492                                                            Abbrev));
    493 
    494   // Emit the abbreviation for RECORD_FILENAME.
    495   Abbrev = std::make_shared<BitCodeAbbrev>();
    496   Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
    497   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
    498   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
    499   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modification time.
    500   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
    501   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
    502   Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
    503                                                           Abbrev));
    504 
    505   // Emit the abbreviation for RECORD_FIXIT.
    506   Abbrev = std::make_shared<BitCodeAbbrev>();
    507   Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
    508   AddRangeLocationAbbrev(*Abbrev);
    509   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
    510   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // FixIt text.
    511   Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
    512                                                        Abbrev));
    513 
    514   Stream.ExitBlock();
    515 }
    516 
    517 void SDiagsWriter::EmitMetaBlock() {
    518   llvm::BitstreamWriter &Stream = State->Stream;
    519   AbbreviationMap &Abbrevs = State->Abbrevs;
    520 
    521   Stream.EnterSubblock(BLOCK_META, 3);
    522   RecordData::value_type Record[] = {RECORD_VERSION, VersionNumber};
    523   Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
    524   Stream.ExitBlock();
    525 }
    526 
    527 unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
    528   if (!State->Categories.insert(category).second)
    529     return category;
    530 
    531   // We use a local version of 'Record' so that we can be generating
    532   // another record when we lazily generate one for the category entry.
    533   StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
    534   RecordData::value_type Record[] = {RECORD_CATEGORY, category, catName.size()};
    535   State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
    536                                    catName);
    537 
    538   return category;
    539 }
    540 
    541 unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
    542                                              unsigned DiagID) {
    543   if (DiagLevel == DiagnosticsEngine::Note)
    544     return 0; // No flag for notes.
    545 
    546   StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
    547   return getEmitDiagnosticFlag(FlagName);
    548 }
    549 
    550 unsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) {
    551   if (FlagName.empty())
    552     return 0;
    553 
    554   // Here we assume that FlagName points to static data whose pointer
    555   // value is fixed.  This allows us to unique by diagnostic groups.
    556   const void *data = FlagName.data();
    557   std::pair<unsigned, StringRef> &entry = State->DiagFlags[data];
    558   if (entry.first == 0) {
    559     entry.first = State->DiagFlags.size();
    560     entry.second = FlagName;
    561 
    562     // Lazily emit the string in a separate record.
    563     RecordData::value_type Record[] = {RECORD_DIAG_FLAG, entry.first,
    564                                        FlagName.size()};
    565     State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG),
    566                                      Record, FlagName);
    567   }
    568 
    569   return entry.first;
    570 }
    571 
    572 void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
    573                                     const Diagnostic &Info) {
    574   assert(!IsFinishing &&
    575          "Received a diagnostic after we've already started teardown.");
    576   if (IsFinishing) {
    577     SmallString<256> diagnostic;
    578     Info.FormatDiagnostic(diagnostic);
    579     getMetaDiags()->Report(
    580         diag::warn_fe_serialized_diag_failure_during_finalisation)
    581         << diagnostic;
    582     return;
    583   }
    584 
    585   // Enter the block for a non-note diagnostic immediately, rather than waiting
    586   // for beginDiagnostic, in case associated notes are emitted before we get
    587   // there.
    588   if (DiagLevel != DiagnosticsEngine::Note) {
    589     if (State->EmittedAnyDiagBlocks)
    590       ExitDiagBlock();
    591 
    592     EnterDiagBlock();
    593     State->EmittedAnyDiagBlocks = true;
    594   }
    595 
    596   // Compute the diagnostic text.
    597   State->diagBuf.clear();
    598   Info.FormatDiagnostic(State->diagBuf);
    599 
    600   if (Info.getLocation().isInvalid()) {
    601     // Special-case diagnostics with no location. We may not have entered a
    602     // source file in this case, so we can't use the normal DiagnosticsRenderer
    603     // machinery.
    604 
    605     // Make sure we bracket all notes as "sub-diagnostics".  This matches
    606     // the behavior in SDiagsRenderer::emitDiagnostic().
    607     if (DiagLevel == DiagnosticsEngine::Note)
    608       EnterDiagBlock();
    609 
    610     EmitDiagnosticMessage(FullSourceLoc(), PresumedLoc(), DiagLevel,
    611                           State->diagBuf, &Info);
    612 
    613     if (DiagLevel == DiagnosticsEngine::Note)
    614       ExitDiagBlock();
    615 
    616     return;
    617   }
    618 
    619   assert(Info.hasSourceManager() && LangOpts &&
    620          "Unexpected diagnostic with valid location outside of a source file");
    621   SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
    622   Renderer.emitDiagnostic(
    623       FullSourceLoc(Info.getLocation(), Info.getSourceManager()), DiagLevel,
    624       State->diagBuf, Info.getRanges(), Info.getFixItHints(), &Info);
    625 }
    626 
    627 static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
    628   switch (Level) {
    629 #define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X;
    630   CASE(Ignored)
    631   CASE(Note)
    632   CASE(Remark)
    633   CASE(Warning)
    634   CASE(Error)
    635   CASE(Fatal)
    636 #undef CASE
    637   }
    638 
    639   llvm_unreachable("invalid diagnostic level");
    640 }
    641 
    642 void SDiagsWriter::EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
    643                                          DiagnosticsEngine::Level Level,
    644                                          StringRef Message,
    645                                          DiagOrStoredDiag D) {
    646   llvm::BitstreamWriter &Stream = State->Stream;
    647   RecordData &Record = State->Record;
    648   AbbreviationMap &Abbrevs = State->Abbrevs;
    649 
    650   // Emit the RECORD_DIAG record.
    651   Record.clear();
    652   Record.push_back(RECORD_DIAG);
    653   Record.push_back(getStableLevel(Level));
    654   AddLocToRecord(Loc, PLoc, Record);
    655 
    656   if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
    657     // Emit the category string lazily and get the category ID.
    658     unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
    659     Record.push_back(getEmitCategory(DiagID));
    660     // Emit the diagnostic flag string lazily and get the mapped ID.
    661     Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
    662   } else {
    663     Record.push_back(getEmitCategory());
    664     Record.push_back(getEmitDiagnosticFlag(Level));
    665   }
    666 
    667   Record.push_back(Message.size());
    668   Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
    669 }
    670 
    671 void SDiagsRenderer::emitDiagnosticMessage(
    672     FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level,
    673     StringRef Message, ArrayRef<clang::CharSourceRange> Ranges,
    674     DiagOrStoredDiag D) {
    675   Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, D);
    676 }
    677 
    678 void SDiagsWriter::EnterDiagBlock() {
    679   State->Stream.EnterSubblock(BLOCK_DIAG, 4);
    680 }
    681 
    682 void SDiagsWriter::ExitDiagBlock() {
    683   State->Stream.ExitBlock();
    684 }
    685 
    686 void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
    687                                      DiagnosticsEngine::Level Level) {
    688   if (Level == DiagnosticsEngine::Note)
    689     Writer.EnterDiagBlock();
    690 }
    691 
    692 void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
    693                                    DiagnosticsEngine::Level Level) {
    694   // Only end note diagnostics here, because we can't be sure when we've seen
    695   // the last note associated with a non-note diagnostic.
    696   if (Level == DiagnosticsEngine::Note)
    697     Writer.ExitDiagBlock();
    698 }
    699 
    700 void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
    701                                    ArrayRef<FixItHint> Hints,
    702                                    const SourceManager &SM) {
    703   llvm::BitstreamWriter &Stream = State->Stream;
    704   RecordData &Record = State->Record;
    705   AbbreviationMap &Abbrevs = State->Abbrevs;
    706 
    707   // Emit Source Ranges.
    708   for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
    709        I != E; ++I)
    710     if (I->isValid())
    711       EmitCharSourceRange(*I, SM);
    712 
    713   // Emit FixIts.
    714   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
    715        I != E; ++I) {
    716     const FixItHint &Fix = *I;
    717     if (Fix.isNull())
    718       continue;
    719     Record.clear();
    720     Record.push_back(RECORD_FIXIT);
    721     AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
    722     Record.push_back(Fix.CodeToInsert.size());
    723     Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
    724                               Fix.CodeToInsert);
    725   }
    726 }
    727 
    728 void SDiagsRenderer::emitCodeContext(FullSourceLoc Loc,
    729                                      DiagnosticsEngine::Level Level,
    730                                      SmallVectorImpl<CharSourceRange> &Ranges,
    731                                      ArrayRef<FixItHint> Hints) {
    732   Writer.EmitCodeContext(Ranges, Hints, Loc.getManager());
    733 }
    734 
    735 void SDiagsRenderer::emitNote(FullSourceLoc Loc, StringRef Message) {
    736   Writer.EnterDiagBlock();
    737   PresumedLoc PLoc = Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc();
    738   Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note, Message,
    739                                DiagOrStoredDiag());
    740   Writer.ExitDiagBlock();
    741 }
    742 
    743 DiagnosticsEngine *SDiagsWriter::getMetaDiags() {
    744   // FIXME: It's slightly absurd to create a new diagnostics engine here, but
    745   // the other options that are available today are worse:
    746   //
    747   // 1. Teach DiagnosticsConsumers to emit diagnostics to the engine they are a
    748   //    part of. The DiagnosticsEngine would need to know not to send
    749   //    diagnostics back to the consumer that failed. This would require us to
    750   //    rework ChainedDiagnosticsConsumer and teach the engine about multiple
    751   //    consumers, which is difficult today because most APIs interface with
    752   //    consumers rather than the engine itself.
    753   //
    754   // 2. Pass a DiagnosticsEngine to SDiagsWriter on creation - this would need
    755   //    to be distinct from the engine the writer was being added to and would
    756   //    normally not be used.
    757   if (!State->MetaDiagnostics) {
    758     IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs());
    759     auto Client =
    760         new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get());
    761     State->MetaDiagnostics = std::make_unique<DiagnosticsEngine>(
    762         IDs, State->DiagOpts.get(), Client);
    763   }
    764   return State->MetaDiagnostics.get();
    765 }
    766 
    767 void SDiagsWriter::RemoveOldDiagnostics() {
    768   if (!llvm::sys::fs::remove(State->OutputFile))
    769     return;
    770 
    771   getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
    772   // Disable merging child records, as whatever is in this file may be
    773   // misleading.
    774   MergeChildRecords = false;
    775 }
    776 
    777 void SDiagsWriter::finish() {
    778   assert(!IsFinishing);
    779   IsFinishing = true;
    780 
    781   // The original instance is responsible for writing the file.
    782   if (!OriginalInstance)
    783     return;
    784 
    785   // Finish off any diagnostic we were in the process of emitting.
    786   if (State->EmittedAnyDiagBlocks)
    787     ExitDiagBlock();
    788 
    789   if (MergeChildRecords) {
    790     if (!State->EmittedAnyDiagBlocks)
    791       // We have no diagnostics of our own, so we can just leave the child
    792       // process' output alone
    793       return;
    794 
    795     if (llvm::sys::fs::exists(State->OutputFile))
    796       if (SDiagsMerger(*this).mergeRecordsFromFile(State->OutputFile.c_str()))
    797         getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
    798   }
    799 
    800   std::error_code EC;
    801   auto OS = std::make_unique<llvm::raw_fd_ostream>(State->OutputFile.c_str(),
    802                                                     EC, llvm::sys::fs::OF_None);
    803   if (EC) {
    804     getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
    805         << State->OutputFile << EC.message();
    806     OS->clear_error();
    807     return;
    808   }
    809 
    810   // Write the generated bitstream to "Out".
    811   OS->write((char *)&State->Buffer.front(), State->Buffer.size());
    812   OS->flush();
    813 
    814   assert(!OS->has_error());
    815   if (OS->has_error()) {
    816     getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
    817         << State->OutputFile << OS->error().message();
    818     OS->clear_error();
    819   }
    820 }
    821 
    822 std::error_code SDiagsMerger::visitStartOfDiagnostic() {
    823   Writer.EnterDiagBlock();
    824   return std::error_code();
    825 }
    826 
    827 std::error_code SDiagsMerger::visitEndOfDiagnostic() {
    828   Writer.ExitDiagBlock();
    829   return std::error_code();
    830 }
    831 
    832 std::error_code
    833 SDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start,
    834                                      const serialized_diags::Location &End) {
    835   RecordData::value_type Record[] = {
    836       RECORD_SOURCE_RANGE, FileLookup[Start.FileID], Start.Line, Start.Col,
    837       Start.Offset, FileLookup[End.FileID], End.Line, End.Col, End.Offset};
    838   Writer.State->Stream.EmitRecordWithAbbrev(
    839       Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record);
    840   return std::error_code();
    841 }
    842 
    843 std::error_code SDiagsMerger::visitDiagnosticRecord(
    844     unsigned Severity, const serialized_diags::Location &Location,
    845     unsigned Category, unsigned Flag, StringRef Message) {
    846   RecordData::value_type Record[] = {
    847       RECORD_DIAG, Severity, FileLookup[Location.FileID], Location.Line,
    848       Location.Col, Location.Offset, CategoryLookup[Category],
    849       Flag ? DiagFlagLookup[Flag] : 0, Message.size()};
    850 
    851   Writer.State->Stream.EmitRecordWithBlob(
    852       Writer.State->Abbrevs.get(RECORD_DIAG), Record, Message);
    853   return std::error_code();
    854 }
    855 
    856 std::error_code
    857 SDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start,
    858                                const serialized_diags::Location &End,
    859                                StringRef Text) {
    860   RecordData::value_type Record[] = {RECORD_FIXIT, FileLookup[Start.FileID],
    861                                      Start.Line, Start.Col, Start.Offset,
    862                                      FileLookup[End.FileID], End.Line, End.Col,
    863                                      End.Offset, Text.size()};
    864 
    865   Writer.State->Stream.EmitRecordWithBlob(
    866       Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text);
    867   return std::error_code();
    868 }
    869 
    870 std::error_code SDiagsMerger::visitFilenameRecord(unsigned ID, unsigned Size,
    871                                                   unsigned Timestamp,
    872                                                   StringRef Name) {
    873   FileLookup[ID] = Writer.getEmitFile(Name.str().c_str());
    874   return std::error_code();
    875 }
    876 
    877 std::error_code SDiagsMerger::visitCategoryRecord(unsigned ID, StringRef Name) {
    878   CategoryLookup[ID] = Writer.getEmitCategory(ID);
    879   return std::error_code();
    880 }
    881 
    882 std::error_code SDiagsMerger::visitDiagFlagRecord(unsigned ID, StringRef Name) {
    883   DiagFlagLookup[ID] = Writer.getEmitDiagnosticFlag(Name);
    884   return std::error_code();
    885 }
    886