clang API Documentation

SerializedDiagnosticPrinter.cpp
Go to the documentation of this file.
00001 //===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/Frontend/SerializedDiagnosticPrinter.h"
00011 #include "clang/Frontend/SerializedDiagnosticReader.h"
00012 #include "clang/Frontend/SerializedDiagnostics.h"
00013 #include "clang/Basic/Diagnostic.h"
00014 #include "clang/Basic/DiagnosticOptions.h"
00015 #include "clang/Basic/FileManager.h"
00016 #include "clang/Basic/SourceManager.h"
00017 #include "clang/Basic/Version.h"
00018 #include "clang/Frontend/DiagnosticRenderer.h"
00019 #include "clang/Frontend/FrontendDiagnostic.h"
00020 #include "clang/Frontend/TextDiagnosticPrinter.h"
00021 #include "clang/Lex/Lexer.h"
00022 #include "llvm/ADT/DenseSet.h"
00023 #include "llvm/ADT/SmallString.h"
00024 #include "llvm/ADT/StringRef.h"
00025 #include "llvm/Support/raw_ostream.h"
00026 #include <vector>
00027 
00028 using namespace clang;
00029 using namespace clang::serialized_diags;
00030 
00031 namespace {
00032   
00033 class AbbreviationMap {
00034   llvm::DenseMap<unsigned, unsigned> Abbrevs;
00035 public:
00036   AbbreviationMap() {}
00037   
00038   void set(unsigned recordID, unsigned abbrevID) {
00039     assert(Abbrevs.find(recordID) == Abbrevs.end() 
00040            && "Abbreviation already set.");
00041     Abbrevs[recordID] = abbrevID;
00042   }
00043   
00044   unsigned get(unsigned recordID) {
00045     assert(Abbrevs.find(recordID) != Abbrevs.end() &&
00046            "Abbreviation not set.");
00047     return Abbrevs[recordID];
00048   }
00049 };
00050  
00051 typedef SmallVector<uint64_t, 64> RecordData;
00052 typedef SmallVectorImpl<uint64_t> RecordDataImpl;
00053 
00054 class SDiagsWriter;
00055   
00056 class SDiagsRenderer : public DiagnosticNoteRenderer {
00057   SDiagsWriter &Writer;
00058 public:
00059   SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts,
00060                  DiagnosticOptions *DiagOpts)
00061     : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
00062 
00063   virtual ~SDiagsRenderer() {}
00064   
00065 protected:
00066   void emitDiagnosticMessage(SourceLocation Loc,
00067                              PresumedLoc PLoc,
00068                              DiagnosticsEngine::Level Level,
00069                              StringRef Message,
00070                              ArrayRef<CharSourceRange> Ranges,
00071                              const SourceManager *SM,
00072                              DiagOrStoredDiag D) override;
00073 
00074   void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
00075                          DiagnosticsEngine::Level Level,
00076                          ArrayRef<CharSourceRange> Ranges,
00077                          const SourceManager &SM) override {}
00078 
00079   void emitNote(SourceLocation Loc, StringRef Message,
00080                 const SourceManager *SM) override;
00081 
00082   void emitCodeContext(SourceLocation Loc,
00083                        DiagnosticsEngine::Level Level,
00084                        SmallVectorImpl<CharSourceRange>& Ranges,
00085                        ArrayRef<FixItHint> Hints,
00086                        const SourceManager &SM) override;
00087 
00088   void beginDiagnostic(DiagOrStoredDiag D,
00089                        DiagnosticsEngine::Level Level) override;
00090   void endDiagnostic(DiagOrStoredDiag D,
00091                      DiagnosticsEngine::Level Level) override;
00092 };
00093 
00094 typedef llvm::DenseMap<unsigned, unsigned> AbbrevLookup;
00095 
00096 class SDiagsMerger : SerializedDiagnosticReader {
00097   SDiagsWriter &Writer;
00098   AbbrevLookup FileLookup;
00099   AbbrevLookup CategoryLookup;
00100   AbbrevLookup DiagFlagLookup;
00101 
00102 public:
00103   SDiagsMerger(SDiagsWriter &Writer)
00104       : SerializedDiagnosticReader(), Writer(Writer) {}
00105 
00106   std::error_code mergeRecordsFromFile(const char *File) {
00107     return readDiagnostics(File);
00108   }
00109 
00110 protected:
00111   std::error_code visitStartOfDiagnostic() override;
00112   std::error_code visitEndOfDiagnostic() override;
00113   std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
00114   std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
00115   std::error_code visitDiagnosticRecord(
00116       unsigned Severity, const serialized_diags::Location &Location,
00117       unsigned Category, unsigned Flag, StringRef Message) override;
00118   std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
00119                                       unsigned Timestamp,
00120                                       StringRef Name) override;
00121   std::error_code visitFixitRecord(const serialized_diags::Location &Start,
00122                                    const serialized_diags::Location &End,
00123                                    StringRef CodeToInsert) override;
00124   std::error_code
00125   visitSourceRangeRecord(const serialized_diags::Location &Start,
00126                          const serialized_diags::Location &End) override;
00127 
00128 private:
00129   std::error_code adjustSourceLocFilename(RecordData &Record,
00130                                           unsigned int offset);
00131 
00132   void adjustAbbrevID(RecordData &Record, AbbrevLookup &Lookup,
00133                       unsigned NewAbbrev);
00134 
00135   void writeRecordWithAbbrev(unsigned ID, RecordData &Record);
00136 
00137   void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob);
00138 };
00139 
00140 class SDiagsWriter : public DiagnosticConsumer {
00141   friend class SDiagsRenderer;
00142   friend class SDiagsMerger;
00143 
00144   struct SharedState;
00145 
00146   explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State)
00147       : LangOpts(nullptr), OriginalInstance(false), MergeChildRecords(false),
00148         State(State) {}
00149 
00150 public:
00151   SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords)
00152       : LangOpts(nullptr), OriginalInstance(true),
00153         MergeChildRecords(MergeChildRecords),
00154         State(new SharedState(File, Diags)) {
00155     if (MergeChildRecords)
00156       RemoveOldDiagnostics();
00157     EmitPreamble();
00158   }
00159 
00160   ~SDiagsWriter() {}
00161 
00162   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
00163                         const Diagnostic &Info) override;
00164 
00165   void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
00166     LangOpts = &LO;
00167   }
00168 
00169   void finish() override;
00170 
00171 private:
00172   /// \brief Build a DiagnosticsEngine to emit diagnostics about the diagnostics
00173   DiagnosticsEngine *getMetaDiags();
00174 
00175   /// \brief Remove old copies of the serialized diagnostics. This is necessary
00176   /// so that we can detect when subprocesses write diagnostics that we should
00177   /// merge into our own.
00178   void RemoveOldDiagnostics();
00179 
00180   /// \brief Emit the preamble for the serialized diagnostics.
00181   void EmitPreamble();
00182   
00183   /// \brief Emit the BLOCKINFO block.
00184   void EmitBlockInfoBlock();
00185 
00186   /// \brief Emit the META data block.
00187   void EmitMetaBlock();
00188 
00189   /// \brief Start a DIAG block.
00190   void EnterDiagBlock();
00191 
00192   /// \brief End a DIAG block.
00193   void ExitDiagBlock();
00194 
00195   /// \brief Emit a DIAG record.
00196   void EmitDiagnosticMessage(SourceLocation Loc,
00197                              PresumedLoc PLoc,
00198                              DiagnosticsEngine::Level Level,
00199                              StringRef Message,
00200                              const SourceManager *SM,
00201                              DiagOrStoredDiag D);
00202 
00203   /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
00204   void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
00205                        ArrayRef<FixItHint> Hints,
00206                        const SourceManager &SM);
00207 
00208   /// \brief Emit a record for a CharSourceRange.
00209   void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
00210   
00211   /// \brief Emit the string information for the category.
00212   unsigned getEmitCategory(unsigned category = 0);
00213   
00214   /// \brief Emit the string information for diagnostic flags.
00215   unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
00216                                  unsigned DiagID = 0);
00217 
00218   unsigned getEmitDiagnosticFlag(StringRef DiagName);
00219 
00220   /// \brief Emit (lazily) the file string and retrieved the file identifier.
00221   unsigned getEmitFile(const char *Filename);
00222 
00223   /// \brief Add SourceLocation information the specified record.  
00224   void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
00225                       PresumedLoc PLoc, RecordDataImpl &Record,
00226                       unsigned TokSize = 0);
00227 
00228   /// \brief Add SourceLocation information the specified record.
00229   void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
00230                       const SourceManager *SM,
00231                       unsigned TokSize = 0) {
00232     AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
00233                    Record, TokSize);
00234   }
00235 
00236   /// \brief Add CharSourceRange information the specified record.
00237   void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
00238                                   const SourceManager &SM);
00239 
00240   /// \brief Language options, which can differ from one clone of this client
00241   /// to another.
00242   const LangOptions *LangOpts;
00243 
00244   /// \brief Whether this is the original instance (rather than one of its
00245   /// clones), responsible for writing the file at the end.
00246   bool OriginalInstance;
00247 
00248   /// \brief Whether this instance should aggregate diagnostics that are
00249   /// generated from child processes.
00250   bool MergeChildRecords;
00251 
00252   /// \brief State that is shared among the various clones of this diagnostic
00253   /// consumer.
00254   struct SharedState : RefCountedBase<SharedState> {
00255     SharedState(StringRef File, DiagnosticOptions *Diags)
00256         : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()),
00257           EmittedAnyDiagBlocks(false) {}
00258 
00259     /// \brief Diagnostic options.
00260     IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
00261 
00262     /// \brief The byte buffer for the serialized content.
00263     SmallString<1024> Buffer;
00264 
00265     /// \brief The BitStreamWriter for the serialized diagnostics.
00266     llvm::BitstreamWriter Stream;
00267 
00268     /// \brief The name of the diagnostics file.
00269     std::string OutputFile;
00270 
00271     /// \brief The set of constructed record abbreviations.
00272     AbbreviationMap Abbrevs;
00273 
00274     /// \brief A utility buffer for constructing record content.
00275     RecordData Record;
00276 
00277     /// \brief A text buffer for rendering diagnostic text.
00278     SmallString<256> diagBuf;
00279 
00280     /// \brief The collection of diagnostic categories used.
00281     llvm::DenseSet<unsigned> Categories;
00282 
00283     /// \brief The collection of files used.
00284     llvm::DenseMap<const char *, unsigned> Files;
00285 
00286     typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
00287     DiagFlagsTy;
00288 
00289     /// \brief Map for uniquing strings.
00290     DiagFlagsTy DiagFlags;
00291 
00292     /// \brief Whether we have already started emission of any DIAG blocks. Once
00293     /// this becomes \c true, we never close a DIAG block until we know that we're
00294     /// starting another one or we're done.
00295     bool EmittedAnyDiagBlocks;
00296 
00297     /// \brief Engine for emitting diagnostics about the diagnostics.
00298     std::unique_ptr<DiagnosticsEngine> MetaDiagnostics;
00299   };
00300 
00301   /// \brief State shared among the various clones of this diagnostic consumer.
00302   IntrusiveRefCntPtr<SharedState> State;
00303 };
00304 } // end anonymous namespace
00305 
00306 namespace clang {
00307 namespace serialized_diags {
00308 std::unique_ptr<DiagnosticConsumer>
00309 create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) {
00310   return llvm::make_unique<SDiagsWriter>(OutputFile, Diags, MergeChildRecords);
00311 }
00312 
00313 } // end namespace serialized_diags
00314 } // end namespace clang
00315 
00316 //===----------------------------------------------------------------------===//
00317 // Serialization methods.
00318 //===----------------------------------------------------------------------===//
00319 
00320 /// \brief Emits a block ID in the BLOCKINFO block.
00321 static void EmitBlockID(unsigned ID, const char *Name,
00322                         llvm::BitstreamWriter &Stream,
00323                         RecordDataImpl &Record) {
00324   Record.clear();
00325   Record.push_back(ID);
00326   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
00327   
00328   // Emit the block name if present.
00329   if (!Name || Name[0] == 0)
00330     return;
00331 
00332   Record.clear();
00333 
00334   while (*Name)
00335     Record.push_back(*Name++);
00336 
00337   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
00338 }
00339 
00340 /// \brief Emits a record ID in the BLOCKINFO block.
00341 static void EmitRecordID(unsigned ID, const char *Name,
00342                          llvm::BitstreamWriter &Stream,
00343                          RecordDataImpl &Record){
00344   Record.clear();
00345   Record.push_back(ID);
00346 
00347   while (*Name)
00348     Record.push_back(*Name++);
00349 
00350   Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
00351 }
00352 
00353 void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
00354                                   const SourceManager *SM,
00355                                   PresumedLoc PLoc,
00356                                   RecordDataImpl &Record,
00357                                   unsigned TokSize) {
00358   if (PLoc.isInvalid()) {
00359     // Emit a "sentinel" location.
00360     Record.push_back((unsigned)0); // File.
00361     Record.push_back((unsigned)0); // Line.
00362     Record.push_back((unsigned)0); // Column.
00363     Record.push_back((unsigned)0); // Offset.
00364     return;
00365   }
00366 
00367   Record.push_back(getEmitFile(PLoc.getFilename()));
00368   Record.push_back(PLoc.getLine());
00369   Record.push_back(PLoc.getColumn()+TokSize);
00370   Record.push_back(SM->getFileOffset(Loc));
00371 }
00372 
00373 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
00374                                               RecordDataImpl &Record,
00375                                               const SourceManager &SM) {
00376   AddLocToRecord(Range.getBegin(), Record, &SM);
00377   unsigned TokSize = 0;
00378   if (Range.isTokenRange())
00379     TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
00380                                         SM, *LangOpts);
00381   
00382   AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
00383 }
00384 
00385 unsigned SDiagsWriter::getEmitFile(const char *FileName){
00386   if (!FileName)
00387     return 0;
00388   
00389   unsigned &entry = State->Files[FileName];
00390   if (entry)
00391     return entry;
00392   
00393   // Lazily generate the record for the file.
00394   entry = State->Files.size();
00395   RecordData Record;
00396   Record.push_back(RECORD_FILENAME);
00397   Record.push_back(entry);
00398   Record.push_back(0); // For legacy.
00399   Record.push_back(0); // For legacy.
00400   StringRef Name(FileName);
00401   Record.push_back(Name.size());
00402   State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
00403                                    Name);
00404 
00405   return entry;
00406 }
00407 
00408 void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
00409                                        const SourceManager &SM) {
00410   State->Record.clear();
00411   State->Record.push_back(RECORD_SOURCE_RANGE);
00412   AddCharSourceRangeToRecord(R, State->Record, SM);
00413   State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE),
00414                                      State->Record);
00415 }
00416 
00417 /// \brief Emits the preamble of the diagnostics file.
00418 void SDiagsWriter::EmitPreamble() {
00419   // Emit the file header.
00420   State->Stream.Emit((unsigned)'D', 8);
00421   State->Stream.Emit((unsigned)'I', 8);
00422   State->Stream.Emit((unsigned)'A', 8);
00423   State->Stream.Emit((unsigned)'G', 8);
00424 
00425   EmitBlockInfoBlock();
00426   EmitMetaBlock();
00427 }
00428 
00429 static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
00430   using namespace llvm;
00431   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
00432   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
00433   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
00434   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
00435 }
00436 
00437 static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
00438   AddSourceLocationAbbrev(Abbrev);
00439   AddSourceLocationAbbrev(Abbrev);  
00440 }
00441 
00442 void SDiagsWriter::EmitBlockInfoBlock() {
00443   State->Stream.EnterBlockInfoBlock(3);
00444 
00445   using namespace llvm;
00446   llvm::BitstreamWriter &Stream = State->Stream;
00447   RecordData &Record = State->Record;
00448   AbbreviationMap &Abbrevs = State->Abbrevs;
00449 
00450   // ==---------------------------------------------------------------------==//
00451   // The subsequent records and Abbrevs are for the "Meta" block.
00452   // ==---------------------------------------------------------------------==//
00453 
00454   EmitBlockID(BLOCK_META, "Meta", Stream, Record);
00455   EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
00456   BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
00457   Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
00458   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
00459   Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
00460 
00461   // ==---------------------------------------------------------------------==//
00462   // The subsequent records and Abbrevs are for the "Diagnostic" block.
00463   // ==---------------------------------------------------------------------==//
00464 
00465   EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
00466   EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
00467   EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
00468   EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
00469   EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
00470   EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
00471   EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
00472 
00473   // Emit abbreviation for RECORD_DIAG.
00474   Abbrev = new BitCodeAbbrev();
00475   Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
00476   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));  // Diag level.
00477   AddSourceLocationAbbrev(Abbrev);
00478   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.  
00479   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
00480   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
00481   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
00482   Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
00483   
00484   // Emit abbrevation for RECORD_CATEGORY.
00485   Abbrev = new BitCodeAbbrev();
00486   Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
00487   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
00488   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));  // Text size.
00489   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // Category text.
00490   Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
00491 
00492   // Emit abbrevation for RECORD_SOURCE_RANGE.
00493   Abbrev = new BitCodeAbbrev();
00494   Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
00495   AddRangeLocationAbbrev(Abbrev);
00496   Abbrevs.set(RECORD_SOURCE_RANGE,
00497               Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
00498   
00499   // Emit the abbreviation for RECORD_DIAG_FLAG.
00500   Abbrev = new BitCodeAbbrev();
00501   Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
00502   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
00503   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
00504   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
00505   Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
00506                                                            Abbrev));
00507   
00508   // Emit the abbreviation for RECORD_FILENAME.
00509   Abbrev = new BitCodeAbbrev();
00510   Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
00511   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
00512   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
00513   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time.  
00514   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
00515   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
00516   Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
00517                                                           Abbrev));
00518   
00519   // Emit the abbreviation for RECORD_FIXIT.
00520   Abbrev = new BitCodeAbbrev();
00521   Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
00522   AddRangeLocationAbbrev(Abbrev);
00523   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
00524   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // FixIt text.
00525   Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
00526                                                        Abbrev));
00527 
00528   Stream.ExitBlock();
00529 }
00530 
00531 void SDiagsWriter::EmitMetaBlock() {
00532   llvm::BitstreamWriter &Stream = State->Stream;
00533   RecordData &Record = State->Record;
00534   AbbreviationMap &Abbrevs = State->Abbrevs;
00535 
00536   Stream.EnterSubblock(BLOCK_META, 3);
00537   Record.clear();
00538   Record.push_back(RECORD_VERSION);
00539   Record.push_back(VersionNumber);
00540   Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);  
00541   Stream.ExitBlock();
00542 }
00543 
00544 unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
00545   if (!State->Categories.insert(category).second)
00546     return category;
00547 
00548   // We use a local version of 'Record' so that we can be generating
00549   // another record when we lazily generate one for the category entry.
00550   RecordData Record;
00551   Record.push_back(RECORD_CATEGORY);
00552   Record.push_back(category);
00553   StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
00554   Record.push_back(catName.size());
00555   State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
00556                                    catName);
00557   
00558   return category;
00559 }
00560 
00561 unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
00562                                              unsigned DiagID) {
00563   if (DiagLevel == DiagnosticsEngine::Note)
00564     return 0; // No flag for notes.
00565   
00566   StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
00567   return getEmitDiagnosticFlag(FlagName);
00568 }
00569 
00570 unsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) {
00571   if (FlagName.empty())
00572     return 0;
00573 
00574   // Here we assume that FlagName points to static data whose pointer
00575   // value is fixed.  This allows us to unique by diagnostic groups.
00576   const void *data = FlagName.data();
00577   std::pair<unsigned, StringRef> &entry = State->DiagFlags[data];
00578   if (entry.first == 0) {
00579     entry.first = State->DiagFlags.size();
00580     entry.second = FlagName;
00581     
00582     // Lazily emit the string in a separate record.
00583     RecordData Record;
00584     Record.push_back(RECORD_DIAG_FLAG);
00585     Record.push_back(entry.first);
00586     Record.push_back(FlagName.size());
00587     State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG),
00588                                      Record, FlagName);
00589   }
00590 
00591   return entry.first;
00592 }
00593 
00594 void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
00595                                     const Diagnostic &Info) {
00596   // Enter the block for a non-note diagnostic immediately, rather than waiting
00597   // for beginDiagnostic, in case associated notes are emitted before we get
00598   // there.
00599   if (DiagLevel != DiagnosticsEngine::Note) {
00600     if (State->EmittedAnyDiagBlocks)
00601       ExitDiagBlock();
00602 
00603     EnterDiagBlock();
00604     State->EmittedAnyDiagBlocks = true;
00605   }
00606 
00607   // Compute the diagnostic text.
00608   State->diagBuf.clear();
00609   Info.FormatDiagnostic(State->diagBuf);
00610 
00611   if (Info.getLocation().isInvalid()) {
00612     // Special-case diagnostics with no location. We may not have entered a
00613     // source file in this case, so we can't use the normal DiagnosticsRenderer
00614     // machinery.
00615 
00616     // Make sure we bracket all notes as "sub-diagnostics".  This matches
00617     // the behavior in SDiagsRenderer::emitDiagnostic().
00618     if (DiagLevel == DiagnosticsEngine::Note)
00619       EnterDiagBlock();
00620 
00621     EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
00622                           State->diagBuf, nullptr, &Info);
00623 
00624     if (DiagLevel == DiagnosticsEngine::Note)
00625       ExitDiagBlock();
00626 
00627     return;
00628   }
00629 
00630   assert(Info.hasSourceManager() && LangOpts &&
00631          "Unexpected diagnostic with valid location outside of a source file");
00632   SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
00633   Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
00634                           State->diagBuf.str(),
00635                           Info.getRanges(),
00636                           Info.getFixItHints(),
00637                           &Info.getSourceManager(),
00638                           &Info);
00639 }
00640 
00641 static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
00642   switch (Level) {
00643 #define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X;
00644   CASE(Ignored)
00645   CASE(Note)
00646   CASE(Remark)
00647   CASE(Warning)
00648   CASE(Error)
00649   CASE(Fatal)
00650 #undef CASE
00651   }
00652 
00653   llvm_unreachable("invalid diagnostic level");
00654 }
00655 
00656 void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
00657                                          PresumedLoc PLoc,
00658                                          DiagnosticsEngine::Level Level,
00659                                          StringRef Message,
00660                                          const SourceManager *SM,
00661                                          DiagOrStoredDiag D) {
00662   llvm::BitstreamWriter &Stream = State->Stream;
00663   RecordData &Record = State->Record;
00664   AbbreviationMap &Abbrevs = State->Abbrevs;
00665   
00666   // Emit the RECORD_DIAG record.
00667   Record.clear();
00668   Record.push_back(RECORD_DIAG);
00669   Record.push_back(getStableLevel(Level));
00670   AddLocToRecord(Loc, SM, PLoc, Record);
00671 
00672   if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
00673     // Emit the category string lazily and get the category ID.
00674     unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
00675     Record.push_back(getEmitCategory(DiagID));
00676     // Emit the diagnostic flag string lazily and get the mapped ID.
00677     Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
00678   } else {
00679     Record.push_back(getEmitCategory());
00680     Record.push_back(getEmitDiagnosticFlag(Level));
00681   }
00682 
00683   Record.push_back(Message.size());
00684   Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
00685 }
00686 
00687 void
00688 SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
00689                                       PresumedLoc PLoc,
00690                                       DiagnosticsEngine::Level Level,
00691                                       StringRef Message,
00692                                       ArrayRef<clang::CharSourceRange> Ranges,
00693                                       const SourceManager *SM,
00694                                       DiagOrStoredDiag D) {
00695   Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
00696 }
00697 
00698 void SDiagsWriter::EnterDiagBlock() {
00699   State->Stream.EnterSubblock(BLOCK_DIAG, 4);
00700 }
00701 
00702 void SDiagsWriter::ExitDiagBlock() {
00703   State->Stream.ExitBlock();
00704 }
00705 
00706 void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
00707                                      DiagnosticsEngine::Level Level) {
00708   if (Level == DiagnosticsEngine::Note)
00709     Writer.EnterDiagBlock();
00710 }
00711 
00712 void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
00713                                    DiagnosticsEngine::Level Level) {
00714   // Only end note diagnostics here, because we can't be sure when we've seen
00715   // the last note associated with a non-note diagnostic.
00716   if (Level == DiagnosticsEngine::Note)
00717     Writer.ExitDiagBlock();
00718 }
00719 
00720 void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
00721                                    ArrayRef<FixItHint> Hints,
00722                                    const SourceManager &SM) {
00723   llvm::BitstreamWriter &Stream = State->Stream;
00724   RecordData &Record = State->Record;
00725   AbbreviationMap &Abbrevs = State->Abbrevs;
00726 
00727   // Emit Source Ranges.
00728   for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
00729        I != E; ++I)
00730     if (I->isValid())
00731       EmitCharSourceRange(*I, SM);
00732 
00733   // Emit FixIts.
00734   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
00735        I != E; ++I) {
00736     const FixItHint &Fix = *I;
00737     if (Fix.isNull())
00738       continue;
00739     Record.clear();
00740     Record.push_back(RECORD_FIXIT);
00741     AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
00742     Record.push_back(Fix.CodeToInsert.size());
00743     Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
00744                               Fix.CodeToInsert);
00745   }
00746 }
00747 
00748 void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
00749                                      DiagnosticsEngine::Level Level,
00750                                      SmallVectorImpl<CharSourceRange> &Ranges,
00751                                      ArrayRef<FixItHint> Hints,
00752                                      const SourceManager &SM) {
00753   Writer.EmitCodeContext(Ranges, Hints, SM);
00754 }
00755 
00756 void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
00757                               const SourceManager *SM) {
00758   Writer.EnterDiagBlock();
00759   PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
00760   Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
00761                                Message, SM, DiagOrStoredDiag());
00762   Writer.ExitDiagBlock();
00763 }
00764 
00765 DiagnosticsEngine *SDiagsWriter::getMetaDiags() {
00766   // FIXME: It's slightly absurd to create a new diagnostics engine here, but
00767   // the other options that are available today are worse:
00768   //
00769   // 1. Teach DiagnosticsConsumers to emit diagnostics to the engine they are a
00770   //    part of. The DiagnosticsEngine would need to know not to send
00771   //    diagnostics back to the consumer that failed. This would require us to
00772   //    rework ChainedDiagnosticsConsumer and teach the engine about multiple
00773   //    consumers, which is difficult today because most APIs interface with
00774   //    consumers rather than the engine itself.
00775   //
00776   // 2. Pass a DiagnosticsEngine to SDiagsWriter on creation - this would need
00777   //    to be distinct from the engine the writer was being added to and would
00778   //    normally not be used.
00779   if (!State->MetaDiagnostics) {
00780     IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs());
00781     auto Client =
00782         new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get());
00783     State->MetaDiagnostics = llvm::make_unique<DiagnosticsEngine>(
00784         IDs, State->DiagOpts.get(), Client);
00785   }
00786   return State->MetaDiagnostics.get();
00787 }
00788 
00789 void SDiagsWriter::RemoveOldDiagnostics() {
00790   if (!llvm::sys::fs::remove(State->OutputFile))
00791     return;
00792 
00793   getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
00794   // Disable merging child records, as whatever is in this file may be
00795   // misleading.
00796   MergeChildRecords = false;
00797 }
00798 
00799 void SDiagsWriter::finish() {
00800   // The original instance is responsible for writing the file.
00801   if (!OriginalInstance)
00802     return;
00803 
00804   // Finish off any diagnostic we were in the process of emitting.
00805   if (State->EmittedAnyDiagBlocks)
00806     ExitDiagBlock();
00807 
00808   if (MergeChildRecords) {
00809     if (!State->EmittedAnyDiagBlocks)
00810       // We have no diagnostics of our own, so we can just leave the child
00811       // process' output alone
00812       return;
00813 
00814     if (llvm::sys::fs::exists(State->OutputFile))
00815       if (SDiagsMerger(*this).mergeRecordsFromFile(State->OutputFile.c_str()))
00816         getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
00817   }
00818 
00819   std::error_code EC;
00820   auto OS = llvm::make_unique<llvm::raw_fd_ostream>(State->OutputFile.c_str(),
00821                                                     EC, llvm::sys::fs::F_None);
00822   if (EC) {
00823     getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
00824         << State->OutputFile << EC.message();
00825     return;
00826   }
00827 
00828   // Write the generated bitstream to "Out".
00829   OS->write((char *)&State->Buffer.front(), State->Buffer.size());
00830   OS->flush();
00831 }
00832 
00833 std::error_code SDiagsMerger::visitStartOfDiagnostic() {
00834   Writer.EnterDiagBlock();
00835   return std::error_code();
00836 }
00837 
00838 std::error_code SDiagsMerger::visitEndOfDiagnostic() {
00839   Writer.ExitDiagBlock();
00840   return std::error_code();
00841 }
00842 
00843 std::error_code
00844 SDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start,
00845                                      const serialized_diags::Location &End) {
00846   RecordData Record;
00847   Record.push_back(RECORD_SOURCE_RANGE);
00848   Record.push_back(FileLookup[Start.FileID]);
00849   Record.push_back(Start.Line);
00850   Record.push_back(Start.Col);
00851   Record.push_back(Start.Offset);
00852   Record.push_back(FileLookup[End.FileID]);
00853   Record.push_back(End.Line);
00854   Record.push_back(End.Col);
00855   Record.push_back(End.Offset);
00856 
00857   Writer.State->Stream.EmitRecordWithAbbrev(
00858       Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record);
00859   return std::error_code();
00860 }
00861 
00862 std::error_code SDiagsMerger::visitDiagnosticRecord(
00863     unsigned Severity, const serialized_diags::Location &Location,
00864     unsigned Category, unsigned Flag, StringRef Message) {
00865   RecordData MergedRecord;
00866   MergedRecord.push_back(RECORD_DIAG);
00867   MergedRecord.push_back(Severity);
00868   MergedRecord.push_back(FileLookup[Location.FileID]);
00869   MergedRecord.push_back(Location.Line);
00870   MergedRecord.push_back(Location.Col);
00871   MergedRecord.push_back(Location.Offset);
00872   MergedRecord.push_back(CategoryLookup[Category]);
00873   MergedRecord.push_back(Flag ? DiagFlagLookup[Flag] : 0);
00874   MergedRecord.push_back(Message.size());
00875 
00876   Writer.State->Stream.EmitRecordWithBlob(
00877       Writer.State->Abbrevs.get(RECORD_DIAG), MergedRecord, Message);
00878   return std::error_code();
00879 }
00880 
00881 std::error_code
00882 SDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start,
00883                                const serialized_diags::Location &End,
00884                                StringRef Text) {
00885   RecordData Record;
00886   Record.push_back(RECORD_FIXIT);
00887   Record.push_back(FileLookup[Start.FileID]);
00888   Record.push_back(Start.Line);
00889   Record.push_back(Start.Col);
00890   Record.push_back(Start.Offset);
00891   Record.push_back(FileLookup[End.FileID]);
00892   Record.push_back(End.Line);
00893   Record.push_back(End.Col);
00894   Record.push_back(End.Offset);
00895   Record.push_back(Text.size());
00896 
00897   Writer.State->Stream.EmitRecordWithBlob(
00898       Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text);
00899   return std::error_code();
00900 }
00901 
00902 std::error_code SDiagsMerger::visitFilenameRecord(unsigned ID, unsigned Size,
00903                                                   unsigned Timestamp,
00904                                                   StringRef Name) {
00905   FileLookup[ID] = Writer.getEmitFile(Name.str().c_str());
00906   return std::error_code();
00907 }
00908 
00909 std::error_code SDiagsMerger::visitCategoryRecord(unsigned ID, StringRef Name) {
00910   CategoryLookup[ID] = Writer.getEmitCategory(ID);
00911   return std::error_code();
00912 }
00913 
00914 std::error_code SDiagsMerger::visitDiagFlagRecord(unsigned ID, StringRef Name) {
00915   DiagFlagLookup[ID] = Writer.getEmitDiagnosticFlag(Name);
00916   return std::error_code();
00917 }