blob: a20f30d6be837118a4b1402dd03415c2e4795793 [file] [log] [blame]
Ted Kremenek78002122011-10-29 00:12:39 +00001//===--- 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 <vector>
Ted Kremenek78002122011-10-29 00:12:39 +000011#include "llvm/Support/raw_ostream.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/DenseSet.h"
15#include "clang/Basic/SourceManager.h"
16#include "clang/Basic/FileManager.h"
17#include "clang/Basic/Diagnostic.h"
18#include "clang/Basic/Version.h"
Ted Kremenek15322172011-11-10 08:43:12 +000019#include "clang/Lex/Lexer.h"
Ted Kremenek78002122011-10-29 00:12:39 +000020#include "clang/Frontend/SerializedDiagnosticPrinter.h"
Ted Kremenek2a764102011-12-17 05:26:11 +000021#include "clang/Frontend/DiagnosticRenderer.h"
Ted Kremenek78002122011-10-29 00:12:39 +000022
23using namespace clang;
Ted Kremenekfdd0ced2011-11-05 00:09:57 +000024using namespace clang::serialized_diags;
Ted Kremenek78002122011-10-29 00:12:39 +000025
26namespace {
Ted Kremenek78002122011-10-29 00:12:39 +000027
28class AbbreviationMap {
29 llvm::DenseMap<unsigned, unsigned> Abbrevs;
30public:
31 AbbreviationMap() {}
32
33 void set(unsigned recordID, unsigned abbrevID) {
34 assert(Abbrevs.find(recordID) == Abbrevs.end()
35 && "Abbreviation already set.");
36 Abbrevs[recordID] = abbrevID;
37 }
38
39 unsigned get(unsigned recordID) {
40 assert(Abbrevs.find(recordID) != Abbrevs.end() &&
41 "Abbreviation not set.");
42 return Abbrevs[recordID];
43 }
44};
45
46typedef llvm::SmallVector<uint64_t, 64> RecordData;
47typedef llvm::SmallVectorImpl<uint64_t> RecordDataImpl;
Ted Kremenek2a764102011-12-17 05:26:11 +000048
49class SDiagsWriter;
50
Ted Kremenek8be51ea2012-02-14 02:46:00 +000051class SDiagsRenderer : public DiagnosticNoteRenderer {
Ted Kremenek2a764102011-12-17 05:26:11 +000052 SDiagsWriter &Writer;
53 RecordData &Record;
54public:
55 SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
Ted Kremenek2a764102011-12-17 05:26:11 +000056 const LangOptions &LangOpts,
57 const DiagnosticOptions &DiagOpts)
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000058 : DiagnosticNoteRenderer(LangOpts, DiagOpts),
Ted Kremenek2a764102011-12-17 05:26:11 +000059 Writer(Writer), Record(Record){}
60
61 virtual ~SDiagsRenderer() {}
62
63protected:
64 virtual void emitDiagnosticMessage(SourceLocation Loc,
65 PresumedLoc PLoc,
66 DiagnosticsEngine::Level Level,
67 StringRef Message,
68 ArrayRef<CharSourceRange> Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000069 const SourceManager *SM,
Ted Kremenek8be51ea2012-02-14 02:46:00 +000070 DiagOrStoredDiag D);
Ted Kremenek2a764102011-12-17 05:26:11 +000071
72 virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
73 DiagnosticsEngine::Level Level,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000074 ArrayRef<CharSourceRange> Ranges,
75 const SourceManager &SM) {}
Ted Kremenek2a764102011-12-17 05:26:11 +000076
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000077 void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM);
Ted Kremenek2a764102011-12-17 05:26:11 +000078
Ted Kremenek2a764102011-12-17 05:26:11 +000079 virtual void emitCodeContext(SourceLocation Loc,
80 DiagnosticsEngine::Level Level,
81 SmallVectorImpl<CharSourceRange>& Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +000082 ArrayRef<FixItHint> Hints,
83 const SourceManager &SM);
Ted Kremenek2a764102011-12-17 05:26:11 +000084
Ted Kremenek8be51ea2012-02-14 02:46:00 +000085 virtual void beginDiagnostic(DiagOrStoredDiag D,
Ted Kremenek2a764102011-12-17 05:26:11 +000086 DiagnosticsEngine::Level Level);
Ted Kremenek8be51ea2012-02-14 02:46:00 +000087 virtual void endDiagnostic(DiagOrStoredDiag D,
Ted Kremenek2a764102011-12-17 05:26:11 +000088 DiagnosticsEngine::Level Level);
89};
Ted Kremenek78002122011-10-29 00:12:39 +000090
91class SDiagsWriter : public DiagnosticConsumer {
Ted Kremenek2a764102011-12-17 05:26:11 +000092 friend class SDiagsRenderer;
Ted Kremenek78002122011-10-29 00:12:39 +000093public:
Ted Kremenek2a764102011-12-17 05:26:11 +000094 explicit SDiagsWriter(llvm::raw_ostream *os, const DiagnosticOptions &diags)
95 : LangOpts(0), DiagOpts(diags),
96 Stream(Buffer), OS(os), inNonNoteDiagnostic(false)
Ted Kremenek78002122011-10-29 00:12:39 +000097 {
98 EmitPreamble();
Devang Patel02ae32a2011-11-15 01:30:40 +000099 }
Ted Kremenek78002122011-10-29 00:12:39 +0000100
101 ~SDiagsWriter() {}
102
103 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
104 const Diagnostic &Info);
105
Ted Kremenek15322172011-11-10 08:43:12 +0000106 void BeginSourceFile(const LangOptions &LO,
107 const Preprocessor *PP) {
108 LangOpts = &LO;
109 }
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000110
111 virtual void finish();
112
Ted Kremenek78002122011-10-29 00:12:39 +0000113 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
114 // It makes no sense to clone this.
115 return 0;
116 }
117
118private:
119 /// \brief Emit the preamble for the serialized diagnostics.
120 void EmitPreamble();
121
122 /// \brief Emit the BLOCKINFO block.
123 void EmitBlockInfoBlock();
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000124
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000125 /// \brief Emit the META data block.
126 void EmitMetaBlock();
127
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000128 /// \brief Emit a record for a CharSourceRange.
Ted Kremenek2a764102011-12-17 05:26:11 +0000129 void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000130
Ted Kremenek2a764102011-12-17 05:26:11 +0000131 /// \brief Emit the string information for the category.
132 unsigned getEmitCategory(unsigned category = 0);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000133
134 /// \brief Emit the string information for diagnostic flags.
135 unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
Ted Kremenek2a764102011-12-17 05:26:11 +0000136 unsigned DiagID = 0);
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000137
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000138 /// \brief Emit (lazily) the file string and retrieved the file identifier.
Ted Kremenek2a764102011-12-17 05:26:11 +0000139 unsigned getEmitFile(const char *Filename);
140
141 /// \brief Add SourceLocation information the specified record.
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000142 void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
Ted Kremenek2a764102011-12-17 05:26:11 +0000143 PresumedLoc PLoc, RecordDataImpl &Record,
144 unsigned TokSize = 0);
145
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000146 /// \brief Add SourceLocation information the specified record.
Ted Kremenek15322172011-11-10 08:43:12 +0000147 void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000148 const SourceManager *SM,
Ted Kremenek2a764102011-12-17 05:26:11 +0000149 unsigned TokSize = 0) {
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000150 AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
151 Record, TokSize);
Ted Kremenek2a764102011-12-17 05:26:11 +0000152 }
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000153
Ted Kremenek96dcade2011-11-05 03:34:23 +0000154 /// \brief Add CharSourceRange information the specified record.
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000155 void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
Ted Kremenek2a764102011-12-17 05:26:11 +0000156 const SourceManager &SM);
Ted Kremenek96dcade2011-11-05 03:34:23 +0000157
Ted Kremenek78002122011-10-29 00:12:39 +0000158 /// \brief The version of the diagnostics file.
159 enum { Version = 1 };
160
Ted Kremenek15322172011-11-10 08:43:12 +0000161 const LangOptions *LangOpts;
Ted Kremenek2a764102011-12-17 05:26:11 +0000162 const DiagnosticOptions &DiagOpts;
Ted Kremenek15322172011-11-10 08:43:12 +0000163
Ted Kremenek78002122011-10-29 00:12:39 +0000164 /// \brief The byte buffer for the serialized content.
Daniel Dunbar8d6ff022012-02-29 20:31:23 +0000165 SmallString<1024> Buffer;
Ted Kremenek78002122011-10-29 00:12:39 +0000166
167 /// \brief The BitStreamWriter for the serialized diagnostics.
168 llvm::BitstreamWriter Stream;
169
170 /// \brief The name of the diagnostics file.
Dylan Noblesmith6f42b622012-02-05 02:12:40 +0000171 OwningPtr<llvm::raw_ostream> OS;
Ted Kremenek78002122011-10-29 00:12:39 +0000172
Ted Kremenek78002122011-10-29 00:12:39 +0000173 /// \brief The set of constructed record abbreviations.
174 AbbreviationMap Abbrevs;
175
176 /// \brief A utility buffer for constructing record content.
177 RecordData Record;
178
179 /// \brief A text buffer for rendering diagnostic text.
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000180 SmallString<256> diagBuf;
Ted Kremenek78002122011-10-29 00:12:39 +0000181
182 /// \brief The collection of diagnostic categories used.
183 llvm::DenseSet<unsigned> Categories;
184
185 /// \brief The collection of files used.
Ted Kremenek2a764102011-12-17 05:26:11 +0000186 llvm::DenseMap<const char *, unsigned> Files;
Ted Kremenek45d92752011-11-05 00:09:50 +0000187
188 typedef llvm::DenseMap<const void *, std::pair<unsigned, llvm::StringRef> >
189 DiagFlagsTy;
190
191 /// \brief Map for uniquing strings.
192 DiagFlagsTy DiagFlags;
Ted Kremenek78002122011-10-29 00:12:39 +0000193
Ted Kremenek59b61612011-11-05 00:09:47 +0000194 /// \brief Flag indicating whether or not we are in the process of
195 /// emitting a non-note diagnostic.
196 bool inNonNoteDiagnostic;
Ted Kremenek78002122011-10-29 00:12:39 +0000197};
198} // end anonymous namespace
199
200namespace clang {
201namespace serialized_diags {
Ted Kremenek2a764102011-12-17 05:26:11 +0000202DiagnosticConsumer *create(llvm::raw_ostream *OS,
203 const DiagnosticOptions &diags) {
204 return new SDiagsWriter(OS, diags);
Ted Kremenek78002122011-10-29 00:12:39 +0000205}
206} // end namespace serialized_diags
207} // end namespace clang
208
209//===----------------------------------------------------------------------===//
210// Serialization methods.
211//===----------------------------------------------------------------------===//
212
213/// \brief Emits a block ID in the BLOCKINFO block.
214static void EmitBlockID(unsigned ID, const char *Name,
215 llvm::BitstreamWriter &Stream,
216 RecordDataImpl &Record) {
217 Record.clear();
218 Record.push_back(ID);
219 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
220
221 // Emit the block name if present.
222 if (Name == 0 || Name[0] == 0)
223 return;
224
225 Record.clear();
226
227 while (*Name)
228 Record.push_back(*Name++);
229
230 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
231}
232
233/// \brief Emits a record ID in the BLOCKINFO block.
234static void EmitRecordID(unsigned ID, const char *Name,
235 llvm::BitstreamWriter &Stream,
236 RecordDataImpl &Record){
237 Record.clear();
238 Record.push_back(ID);
239
240 while (*Name)
241 Record.push_back(*Name++);
242
243 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
244}
245
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000246void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000247 const SourceManager *SM,
Ted Kremenek2a764102011-12-17 05:26:11 +0000248 PresumedLoc PLoc,
Ted Kremenek15322172011-11-10 08:43:12 +0000249 RecordDataImpl &Record,
250 unsigned TokSize) {
Ted Kremenek2a764102011-12-17 05:26:11 +0000251 if (PLoc.isInvalid()) {
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000252 // Emit a "sentinel" location.
Ted Kremenek15322172011-11-10 08:43:12 +0000253 Record.push_back((unsigned)0); // File.
254 Record.push_back((unsigned)0); // Line.
255 Record.push_back((unsigned)0); // Column.
256 Record.push_back((unsigned)0); // Offset.
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000257 return;
258 }
259
Ted Kremenek2a764102011-12-17 05:26:11 +0000260 Record.push_back(getEmitFile(PLoc.getFilename()));
261 Record.push_back(PLoc.getLine());
262 Record.push_back(PLoc.getColumn()+TokSize);
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000263 Record.push_back(SM->getFileOffset(Loc));
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000264}
265
Ted Kremenek96dcade2011-11-05 03:34:23 +0000266void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000267 RecordDataImpl &Record,
Ted Kremenek2a764102011-12-17 05:26:11 +0000268 const SourceManager &SM) {
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000269 AddLocToRecord(Range.getBegin(), Record, &SM);
Ted Kremenek15322172011-11-10 08:43:12 +0000270 unsigned TokSize = 0;
271 if (Range.isTokenRange())
272 TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000273 SM, *LangOpts);
Ted Kremenek15322172011-11-10 08:43:12 +0000274
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000275 AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
Ted Kremenek96dcade2011-11-05 03:34:23 +0000276}
277
Ted Kremenek2a764102011-12-17 05:26:11 +0000278unsigned SDiagsWriter::getEmitFile(const char *FileName){
279 if (!FileName)
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000280 return 0;
281
Ted Kremenek2a764102011-12-17 05:26:11 +0000282 unsigned &entry = Files[FileName];
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000283 if (entry)
284 return entry;
285
286 // Lazily generate the record for the file.
287 entry = Files.size();
288 RecordData Record;
289 Record.push_back(RECORD_FILENAME);
290 Record.push_back(entry);
Ted Kremenek2a764102011-12-17 05:26:11 +0000291 Record.push_back(0); // For legacy.
292 Record.push_back(0); // For legacy.
293 StringRef Name(FileName);
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000294 Record.push_back(Name.size());
295 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FILENAME), Record, Name);
296
297 return entry;
298}
299
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000300void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
Ted Kremenek2a764102011-12-17 05:26:11 +0000301 const SourceManager &SM) {
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000302 Record.clear();
303 Record.push_back(RECORD_SOURCE_RANGE);
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000304 AddCharSourceRangeToRecord(R, Record, SM);
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000305 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_SOURCE_RANGE), Record);
306}
307
Ted Kremenek78002122011-10-29 00:12:39 +0000308/// \brief Emits the preamble of the diagnostics file.
309void SDiagsWriter::EmitPreamble() {
Ted Kremenek78002122011-10-29 00:12:39 +0000310 // Emit the file header.
311 Stream.Emit((unsigned)'D', 8);
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000312 Stream.Emit((unsigned)'I', 8);
313 Stream.Emit((unsigned)'A', 8);
314 Stream.Emit((unsigned)'G', 8);
Ted Kremenek069f9c22011-11-05 00:09:53 +0000315
Ted Kremenek78002122011-10-29 00:12:39 +0000316 EmitBlockInfoBlock();
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000317 EmitMetaBlock();
Ted Kremenek78002122011-10-29 00:12:39 +0000318}
319
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000320static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
321 using namespace llvm;
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000322 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000323 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
324 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
325 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
326}
Ted Kremenek96dcade2011-11-05 03:34:23 +0000327
328static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
329 AddSourceLocationAbbrev(Abbrev);
330 AddSourceLocationAbbrev(Abbrev);
331}
332
Ted Kremenek78002122011-10-29 00:12:39 +0000333void SDiagsWriter::EmitBlockInfoBlock() {
334 Stream.EnterBlockInfoBlock(3);
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000335
336 using namespace llvm;
337
338 // ==---------------------------------------------------------------------==//
339 // The subsequent records and Abbrevs are for the "Meta" block.
340 // ==---------------------------------------------------------------------==//
341
342 EmitBlockID(BLOCK_META, "Meta", Stream, Record);
343 EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
344 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
345 Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
346 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
347 Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
348
Ted Kremenek78002122011-10-29 00:12:39 +0000349 // ==---------------------------------------------------------------------==//
350 // The subsequent records and Abbrevs are for the "Diagnostic" block.
351 // ==---------------------------------------------------------------------==//
352
Ted Kremenek45d92752011-11-05 00:09:50 +0000353 EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
354 EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000355 EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000356 EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000357 EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000358 EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
Ted Kremenek96dcade2011-11-05 03:34:23 +0000359 EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000360
Ted Kremenek78002122011-10-29 00:12:39 +0000361 // Emit abbreviation for RECORD_DIAG.
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000362 Abbrev = new BitCodeAbbrev();
Ted Kremenek78002122011-10-29 00:12:39 +0000363 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
Ted Kremenek45d92752011-11-05 00:09:50 +0000364 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level.
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000365 AddSourceLocationAbbrev(Abbrev);
Ted Kremenek45d92752011-11-05 00:09:50 +0000366 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
367 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
Ted Kremenek78002122011-10-29 00:12:39 +0000368 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
369 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
370 Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000371
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000372 // Emit abbrevation for RECORD_CATEGORY.
373 Abbrev = new BitCodeAbbrev();
374 Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
375 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
376 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size.
377 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text.
378 Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
379
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000380 // Emit abbrevation for RECORD_SOURCE_RANGE.
381 Abbrev = new BitCodeAbbrev();
382 Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
Ted Kremenek96dcade2011-11-05 03:34:23 +0000383 AddRangeLocationAbbrev(Abbrev);
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000384 Abbrevs.set(RECORD_SOURCE_RANGE,
385 Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000386
387 // Emit the abbreviation for RECORD_DIAG_FLAG.
388 Abbrev = new BitCodeAbbrev();
389 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
390 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
391 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
392 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
393 Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
394 Abbrev));
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000395
396 // Emit the abbreviation for RECORD_FILENAME.
Ted Kremenek78002122011-10-29 00:12:39 +0000397 Abbrev = new BitCodeAbbrev();
Ted Kremenek28eac522011-11-05 00:09:43 +0000398 Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000399 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
400 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
401 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time.
Ted Kremenek78002122011-10-29 00:12:39 +0000402 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
403 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000404 Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Ted Kremenek78002122011-10-29 00:12:39 +0000405 Abbrev));
Ted Kremenek96dcade2011-11-05 03:34:23 +0000406
407 // Emit the abbreviation for RECORD_FIXIT.
408 Abbrev = new BitCodeAbbrev();
409 Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
410 AddRangeLocationAbbrev(Abbrev);
411 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
412 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text.
413 Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
414 Abbrev));
Ted Kremenek78002122011-10-29 00:12:39 +0000415
416 Stream.ExitBlock();
417}
418
Ted Kremenek0b69aa82011-11-08 20:27:29 +0000419void SDiagsWriter::EmitMetaBlock() {
420 Stream.EnterSubblock(BLOCK_META, 3);
421 Record.clear();
422 Record.push_back(RECORD_VERSION);
423 Record.push_back(Version);
424 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
425 Stream.ExitBlock();
426}
427
Ted Kremenek2a764102011-12-17 05:26:11 +0000428unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000429 if (Categories.count(category))
430 return category;
431
432 Categories.insert(category);
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000433
434 // We use a local version of 'Record' so that we can be generating
435 // another record when we lazily generate one for the category entry.
436 RecordData Record;
437 Record.push_back(RECORD_CATEGORY);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000438 Record.push_back(category);
439 StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000440 Record.push_back(catName.size());
441 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_CATEGORY), Record, catName);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000442
443 return category;
444}
445
446unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
Ted Kremenek2a764102011-12-17 05:26:11 +0000447 unsigned DiagID) {
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000448 if (DiagLevel == DiagnosticsEngine::Note)
449 return 0; // No flag for notes.
450
Ted Kremenek2a764102011-12-17 05:26:11 +0000451 StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
Ted Kremenek3baf63d2011-11-05 00:10:07 +0000452 if (FlagName.empty())
453 return 0;
454
455 // Here we assume that FlagName points to static data whose pointer
456 // value is fixed. This allows us to unique by diagnostic groups.
457 const void *data = FlagName.data();
458 std::pair<unsigned, StringRef> &entry = DiagFlags[data];
459 if (entry.first == 0) {
460 entry.first = DiagFlags.size();
461 entry.second = FlagName;
462
463 // Lazily emit the string in a separate record.
464 RecordData Record;
465 Record.push_back(RECORD_DIAG_FLAG);
466 Record.push_back(entry.first);
467 Record.push_back(FlagName.size());
468 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG_FLAG),
469 Record, FlagName);
470 }
471
472 return entry.first;
Ted Kremenek0dbadc42011-11-05 00:10:04 +0000473}
474
Ted Kremenek78002122011-10-29 00:12:39 +0000475void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
476 const Diagnostic &Info) {
Ted Kremenek59b61612011-11-05 00:09:47 +0000477 if (DiagLevel != DiagnosticsEngine::Note) {
478 if (inNonNoteDiagnostic) {
479 // We have encountered a non-note diagnostic. Finish up the previous
480 // diagnostic block before starting a new one.
481 Stream.ExitBlock();
482 }
483 inNonNoteDiagnostic = true;
484 }
Ted Kremenek96dcade2011-11-05 03:34:23 +0000485
Ted Kremenek2a764102011-12-17 05:26:11 +0000486 // Compute the diagnostic text.
487 diagBuf.clear();
488 Info.FormatDiagnostic(diagBuf);
489
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000490 const SourceManager *
491 SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
492 SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
Ted Kremenek2a764102011-12-17 05:26:11 +0000493 Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
494 diagBuf.str(),
495 Info.getRanges(),
496 llvm::makeArrayRef(Info.getFixItHints(),
497 Info.getNumFixItHints()),
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000498 SM,
Ted Kremenek2a764102011-12-17 05:26:11 +0000499 &Info);
500}
501
502void
503SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
504 PresumedLoc PLoc,
505 DiagnosticsEngine::Level Level,
506 StringRef Message,
507 ArrayRef<clang::CharSourceRange> Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000508 const SourceManager *SM,
Ted Kremenek8be51ea2012-02-14 02:46:00 +0000509 DiagOrStoredDiag D) {
Ted Kremenek2a764102011-12-17 05:26:11 +0000510 // Emit the RECORD_DIAG record.
511 Writer.Record.clear();
512 Writer.Record.push_back(RECORD_DIAG);
513 Writer.Record.push_back(Level);
514 Writer.AddLocToRecord(Loc, SM, PLoc, Record);
515
Ted Kremenek8be51ea2012-02-14 02:46:00 +0000516 if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
Ted Kremenek2a764102011-12-17 05:26:11 +0000517 // Emit the category string lazily and get the category ID.
518 unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
519 Writer.Record.push_back(Writer.getEmitCategory(DiagID));
520 // Emit the diagnostic flag string lazily and get the mapped ID.
521 Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level, Info->getID()));
522 }
523 else {
524 Writer.Record.push_back(Writer.getEmitCategory());
525 Writer.Record.push_back(Writer.getEmitDiagnosticFlag(Level));
526 }
527
528 Writer.Record.push_back(Message.size());
529 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG),
530 Writer.Record, Message);
531}
532
Ted Kremenek8be51ea2012-02-14 02:46:00 +0000533void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
Ted Kremenek2a764102011-12-17 05:26:11 +0000534 DiagnosticsEngine::Level Level) {
535 Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
536}
537
Ted Kremenek8be51ea2012-02-14 02:46:00 +0000538void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
Ted Kremenek2a764102011-12-17 05:26:11 +0000539 DiagnosticsEngine::Level Level) {
Ted Kremenek8be51ea2012-02-14 02:46:00 +0000540 if (D && Level != DiagnosticsEngine::Note)
Ted Kremenek2a764102011-12-17 05:26:11 +0000541 return;
542 Writer.Stream.ExitBlock();
543}
544
545void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
546 DiagnosticsEngine::Level Level,
547 SmallVectorImpl<CharSourceRange> &Ranges,
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000548 ArrayRef<FixItHint> Hints,
549 const SourceManager &SM) {
Ted Kremenek96dcade2011-11-05 03:34:23 +0000550 // Emit Source Ranges.
Ted Kremenek2a20b4f2011-11-05 00:10:01 +0000551 for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
552 it != ei; ++it) {
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000553 if (it->isValid())
Ted Kremenek2a764102011-12-17 05:26:11 +0000554 Writer.EmitCharSourceRange(*it, SM);
Ted Kremenek96dcade2011-11-05 03:34:23 +0000555 }
Ted Kremenek59b61612011-11-05 00:09:47 +0000556
Ted Kremenek2a764102011-12-17 05:26:11 +0000557 // Emit FixIts.
558 for (ArrayRef<FixItHint>::iterator it = Hints.begin(), et = Hints.end();
559 it != et; ++it) {
560 const FixItHint &fix = *it;
561 if (fix.isNull())
562 continue;
563 Writer.Record.clear();
564 Writer.Record.push_back(RECORD_FIXIT);
565 Writer.AddCharSourceRangeToRecord(fix.RemoveRange, Record, SM);
566 Writer.Record.push_back(fix.CodeToInsert.size());
567 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_FIXIT), Record,
568 fix.CodeToInsert);
Ted Kremenek59b61612011-11-05 00:09:47 +0000569 }
Ted Kremenek78002122011-10-29 00:12:39 +0000570}
571
Argyrios Kyrtzidis16afdf72012-05-10 05:03:45 +0000572void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
573 const SourceManager *SM) {
Ted Kremenek2a764102011-12-17 05:26:11 +0000574 Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
575 RecordData Record;
576 Record.push_back(RECORD_DIAG);
577 Record.push_back(DiagnosticsEngine::Note);
578 Writer.AddLocToRecord(Loc, Record, SM);
579 Record.push_back(Writer.getEmitCategory());
580 Record.push_back(Writer.getEmitDiagnosticFlag(DiagnosticsEngine::Note));
581 Record.push_back(Message.size());
582 Writer.Stream.EmitRecordWithBlob(Writer.Abbrevs.get(RECORD_DIAG),
583 Record, Message);
584 Writer.Stream.ExitBlock();
585}
586
Argyrios Kyrtzidis29f27872011-12-07 05:52:12 +0000587void SDiagsWriter::finish() {
Ted Kremenek59b61612011-11-05 00:09:47 +0000588 if (inNonNoteDiagnostic) {
589 // Finish off any diagnostics we were in the process of emitting.
590 Stream.ExitBlock();
591 inNonNoteDiagnostic = false;
592 }
Ted Kremenek0d34e6e2011-11-05 00:10:11 +0000593
Ted Kremenek78002122011-10-29 00:12:39 +0000594 // Write the generated bitstream to "Out".
595 OS->write((char *)&Buffer.front(), Buffer.size());
596 OS->flush();
597
598 OS.reset(0);
599}
600