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