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