blob: 527f727b37d3d52f3b3ec2c62ae22f8f8a7ef24b [file] [log] [blame]
Ted Kremenek4610ea22011-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
Ted Kremenek4610ea22011-10-29 00:12:39 +000010#include "clang/Frontend/SerializedDiagnosticPrinter.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000011#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"
Ted Kremenek4548e042011-12-17 05:26:11 +000016#include "clang/Frontend/DiagnosticRenderer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "clang/Lex/Lexer.h"
18#include "llvm/ADT/DenseSet.h"
19#include "llvm/ADT/SmallString.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/raw_ostream.h"
22#include <vector>
Ted Kremenek4610ea22011-10-29 00:12:39 +000023
24using namespace clang;
Ted Kremenek337cd2a2011-11-05 00:09:57 +000025using namespace clang::serialized_diags;
Ted Kremenek4610ea22011-10-29 00:12:39 +000026
27namespace {
Ted Kremenek4610ea22011-10-29 00:12:39 +000028
29class AbbreviationMap {
30 llvm::DenseMap<unsigned, unsigned> Abbrevs;
31public:
32 AbbreviationMap() {}
33
34 void set(unsigned recordID, unsigned abbrevID) {
35 assert(Abbrevs.find(recordID) == Abbrevs.end()
36 && "Abbreviation already set.");
37 Abbrevs[recordID] = abbrevID;
38 }
39
40 unsigned get(unsigned recordID) {
41 assert(Abbrevs.find(recordID) != Abbrevs.end() &&
42 "Abbreviation not set.");
43 return Abbrevs[recordID];
44 }
45};
46
Dmitri Gribenkof8579502013-01-12 19:30:44 +000047typedef SmallVector<uint64_t, 64> RecordData;
48typedef SmallVectorImpl<uint64_t> RecordDataImpl;
Ted Kremenek4548e042011-12-17 05:26:11 +000049
50class SDiagsWriter;
51
Ted Kremenek0964cca2012-02-14 02:46:00 +000052class SDiagsRenderer : public DiagnosticNoteRenderer {
Ted Kremenek4548e042011-12-17 05:26:11 +000053 SDiagsWriter &Writer;
Ted Kremenek4548e042011-12-17 05:26:11 +000054public:
Richard Smitha9f521f2012-08-21 03:11:53 +000055 SDiagsRenderer(SDiagsWriter &Writer, const LangOptions &LangOpts,
Douglas Gregor811db4e2012-10-23 22:26:28 +000056 DiagnosticOptions *DiagOpts)
Richard Smitha9f521f2012-08-21 03:11:53 +000057 : DiagnosticNoteRenderer(LangOpts, DiagOpts), Writer(Writer) {}
Ted Kremenek4548e042011-12-17 05:26:11 +000058
59 virtual ~SDiagsRenderer() {}
60
61protected:
Craig Topperafa7cb32014-03-13 06:07:04 +000062 void emitDiagnosticMessage(SourceLocation Loc,
63 PresumedLoc PLoc,
64 DiagnosticsEngine::Level Level,
65 StringRef Message,
66 ArrayRef<CharSourceRange> Ranges,
67 const SourceManager *SM,
68 DiagOrStoredDiag D) override;
Richard Smitha9f521f2012-08-21 03:11:53 +000069
Craig Topperafa7cb32014-03-13 06:07:04 +000070 void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
71 DiagnosticsEngine::Level Level,
72 ArrayRef<CharSourceRange> Ranges,
73 const SourceManager &SM) override {}
Richard Smitha9f521f2012-08-21 03:11:53 +000074
Craig Topperafa7cb32014-03-13 06:07:04 +000075 void emitNote(SourceLocation Loc, StringRef Message,
76 const SourceManager *SM) override;
Richard Smitha9f521f2012-08-21 03:11:53 +000077
Craig Topperafa7cb32014-03-13 06:07:04 +000078 void emitCodeContext(SourceLocation Loc,
79 DiagnosticsEngine::Level Level,
80 SmallVectorImpl<CharSourceRange>& Ranges,
81 ArrayRef<FixItHint> Hints,
82 const SourceManager &SM) override;
83
84 void beginDiagnostic(DiagOrStoredDiag D,
85 DiagnosticsEngine::Level Level) override;
86 void endDiagnostic(DiagOrStoredDiag D,
87 DiagnosticsEngine::Level Level) override;
Ted Kremenek4548e042011-12-17 05:26:11 +000088};
Ted Kremenek4610ea22011-10-29 00:12:39 +000089
90class SDiagsWriter : public DiagnosticConsumer {
Ted Kremenek4548e042011-12-17 05:26:11 +000091 friend class SDiagsRenderer;
Douglas Gregorfa686fb2012-11-30 23:32:31 +000092
93 struct SharedState;
94
Dmitri Gribenkof8579502013-01-12 19:30:44 +000095 explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State)
Douglas Gregorfa686fb2012-11-30 23:32:31 +000096 : LangOpts(0), OriginalInstance(false), State(State) { }
97
98public:
Dmitri Gribenkof8579502013-01-12 19:30:44 +000099 SDiagsWriter(raw_ostream *os, DiagnosticOptions *diags)
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000100 : LangOpts(0), OriginalInstance(true), State(new SharedState(os, diags))
101 {
Ted Kremenek4610ea22011-10-29 00:12:39 +0000102 EmitPreamble();
Devang Patel9957e8b2011-11-15 01:30:40 +0000103 }
Richard Smitha9f521f2012-08-21 03:11:53 +0000104
Ted Kremenek4610ea22011-10-29 00:12:39 +0000105 ~SDiagsWriter() {}
Craig Topperafa7cb32014-03-13 06:07:04 +0000106
Ted Kremenek4610ea22011-10-29 00:12:39 +0000107 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
Craig Topperafa7cb32014-03-13 06:07:04 +0000108 const Diagnostic &Info) override;
109
110 void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override {
Ted Kremenekd010ba42011-11-10 08:43:12 +0000111 LangOpts = &LO;
112 }
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000113
Craig Topperafa7cb32014-03-13 06:07:04 +0000114 void finish() override;
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000115
Ted Kremenek4610ea22011-10-29 00:12:39 +0000116private:
117 /// \brief Emit the preamble for the serialized diagnostics.
118 void EmitPreamble();
119
120 /// \brief Emit the BLOCKINFO block.
121 void EmitBlockInfoBlock();
Ted Kremenekf264a202011-11-05 00:10:11 +0000122
Ted Kremenekcc88d262011-11-08 20:27:29 +0000123 /// \brief Emit the META data block.
124 void EmitMetaBlock();
Richard Smitha9f521f2012-08-21 03:11:53 +0000125
126 /// \brief Start a DIAG block.
127 void EnterDiagBlock();
128
129 /// \brief End a DIAG block.
130 void ExitDiagBlock();
131
132 /// \brief Emit a DIAG record.
133 void EmitDiagnosticMessage(SourceLocation Loc,
134 PresumedLoc PLoc,
135 DiagnosticsEngine::Level Level,
136 StringRef Message,
137 const SourceManager *SM,
138 DiagOrStoredDiag D);
139
140 /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic.
141 void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
142 ArrayRef<FixItHint> Hints,
143 const SourceManager &SM);
144
Ted Kremenek59f10252011-11-05 00:10:01 +0000145 /// \brief Emit a record for a CharSourceRange.
Ted Kremenek4548e042011-12-17 05:26:11 +0000146 void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM);
Ted Kremenek59f10252011-11-05 00:10:01 +0000147
Ted Kremenek4548e042011-12-17 05:26:11 +0000148 /// \brief Emit the string information for the category.
149 unsigned getEmitCategory(unsigned category = 0);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000150
151 /// \brief Emit the string information for diagnostic flags.
152 unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
Ted Kremenek4548e042011-12-17 05:26:11 +0000153 unsigned DiagID = 0);
Ted Kremenek319215062011-11-05 00:10:04 +0000154
Ted Kremenekf264a202011-11-05 00:10:11 +0000155 /// \brief Emit (lazily) the file string and retrieved the file identifier.
Ted Kremenek4548e042011-12-17 05:26:11 +0000156 unsigned getEmitFile(const char *Filename);
157
158 /// \brief Add SourceLocation information the specified record.
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000159 void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
Ted Kremenek4548e042011-12-17 05:26:11 +0000160 PresumedLoc PLoc, RecordDataImpl &Record,
161 unsigned TokSize = 0);
162
Ted Kremenekf264a202011-11-05 00:10:11 +0000163 /// \brief Add SourceLocation information the specified record.
Ted Kremenekd010ba42011-11-10 08:43:12 +0000164 void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000165 const SourceManager *SM,
Ted Kremenek4548e042011-12-17 05:26:11 +0000166 unsigned TokSize = 0) {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000167 AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
168 Record, TokSize);
Ted Kremenek4548e042011-12-17 05:26:11 +0000169 }
Ted Kremenekf264a202011-11-05 00:10:11 +0000170
Ted Kremenekd89a8272011-11-05 03:34:23 +0000171 /// \brief Add CharSourceRange information the specified record.
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000172 void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
Ted Kremenek4548e042011-12-17 05:26:11 +0000173 const SourceManager &SM);
Ted Kremenekd89a8272011-11-05 03:34:23 +0000174
Ted Kremenek4610ea22011-10-29 00:12:39 +0000175 /// \brief The version of the diagnostics file.
Jordan Rose7ef1c382014-03-03 18:29:52 +0000176 enum { Version = 2 };
Ted Kremenek4610ea22011-10-29 00:12:39 +0000177
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000178 /// \brief Language options, which can differ from one clone of this client
179 /// to another.
Ted Kremenekd010ba42011-11-10 08:43:12 +0000180 const LangOptions *LangOpts;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000181
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000182 /// \brief Whether this is the original instance (rather than one of its
183 /// clones), responsible for writing the file at the end.
184 bool OriginalInstance;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000185
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000186 /// \brief State that is shared among the various clones of this diagnostic
187 /// consumer.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000188 struct SharedState : RefCountedBase<SharedState> {
189 SharedState(raw_ostream *os, DiagnosticOptions *diags)
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000190 : DiagOpts(diags), Stream(Buffer), OS(os), EmittedAnyDiagBlocks(false) { }
Ted Kremenek4610ea22011-10-29 00:12:39 +0000191
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000192 /// \brief Diagnostic options.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000193 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000194
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000195 /// \brief The byte buffer for the serialized content.
196 SmallString<1024> Buffer;
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000197
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000198 /// \brief The BitStreamWriter for the serialized diagnostics.
199 llvm::BitstreamWriter Stream;
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000200
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000201 /// \brief The name of the diagnostics file.
Ahmed Charlesb8984322014-03-07 20:03:18 +0000202 std::unique_ptr<raw_ostream> OS;
Richard Smitha9f521f2012-08-21 03:11:53 +0000203
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000204 /// \brief The set of constructed record abbreviations.
205 AbbreviationMap Abbrevs;
206
207 /// \brief A utility buffer for constructing record content.
208 RecordData Record;
209
210 /// \brief A text buffer for rendering diagnostic text.
211 SmallString<256> diagBuf;
212
213 /// \brief The collection of diagnostic categories used.
214 llvm::DenseSet<unsigned> Categories;
215
216 /// \brief The collection of files used.
217 llvm::DenseMap<const char *, unsigned> Files;
218
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000219 typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000220 DiagFlagsTy;
221
222 /// \brief Map for uniquing strings.
223 DiagFlagsTy DiagFlags;
224
225 /// \brief Whether we have already started emission of any DIAG blocks. Once
226 /// this becomes \c true, we never close a DIAG block until we know that we're
227 /// starting another one or we're done.
228 bool EmittedAnyDiagBlocks;
229 };
230
231 /// \brief State shared among the various clones of this diagnostic consumer.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000232 IntrusiveRefCntPtr<SharedState> State;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000233};
234} // end anonymous namespace
235
236namespace clang {
237namespace serialized_diags {
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000238DiagnosticConsumer *create(raw_ostream *OS, DiagnosticOptions *diags) {
Ted Kremenek4548e042011-12-17 05:26:11 +0000239 return new SDiagsWriter(OS, diags);
Ted Kremenek4610ea22011-10-29 00:12:39 +0000240}
241} // end namespace serialized_diags
242} // end namespace clang
243
244//===----------------------------------------------------------------------===//
245// Serialization methods.
246//===----------------------------------------------------------------------===//
247
248/// \brief Emits a block ID in the BLOCKINFO block.
249static void EmitBlockID(unsigned ID, const char *Name,
250 llvm::BitstreamWriter &Stream,
251 RecordDataImpl &Record) {
252 Record.clear();
253 Record.push_back(ID);
254 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
255
256 // Emit the block name if present.
257 if (Name == 0 || Name[0] == 0)
258 return;
259
260 Record.clear();
261
262 while (*Name)
263 Record.push_back(*Name++);
264
265 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
266}
267
268/// \brief Emits a record ID in the BLOCKINFO block.
269static void EmitRecordID(unsigned ID, const char *Name,
270 llvm::BitstreamWriter &Stream,
271 RecordDataImpl &Record){
272 Record.clear();
273 Record.push_back(ID);
274
275 while (*Name)
276 Record.push_back(*Name++);
277
278 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
279}
280
Ted Kremenekf264a202011-11-05 00:10:11 +0000281void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000282 const SourceManager *SM,
Ted Kremenek4548e042011-12-17 05:26:11 +0000283 PresumedLoc PLoc,
Ted Kremenekd010ba42011-11-10 08:43:12 +0000284 RecordDataImpl &Record,
285 unsigned TokSize) {
Ted Kremenek4548e042011-12-17 05:26:11 +0000286 if (PLoc.isInvalid()) {
Ted Kremenek59f10252011-11-05 00:10:01 +0000287 // Emit a "sentinel" location.
Ted Kremenekd010ba42011-11-10 08:43:12 +0000288 Record.push_back((unsigned)0); // File.
289 Record.push_back((unsigned)0); // Line.
290 Record.push_back((unsigned)0); // Column.
291 Record.push_back((unsigned)0); // Offset.
Ted Kremenek59f10252011-11-05 00:10:01 +0000292 return;
293 }
294
Ted Kremenek4548e042011-12-17 05:26:11 +0000295 Record.push_back(getEmitFile(PLoc.getFilename()));
296 Record.push_back(PLoc.getLine());
297 Record.push_back(PLoc.getColumn()+TokSize);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000298 Record.push_back(SM->getFileOffset(Loc));
Ted Kremenek59f10252011-11-05 00:10:01 +0000299}
300
Ted Kremenekd89a8272011-11-05 03:34:23 +0000301void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000302 RecordDataImpl &Record,
Ted Kremenek4548e042011-12-17 05:26:11 +0000303 const SourceManager &SM) {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000304 AddLocToRecord(Range.getBegin(), Record, &SM);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000305 unsigned TokSize = 0;
306 if (Range.isTokenRange())
307 TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000308 SM, *LangOpts);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000309
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000310 AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
Ted Kremenekd89a8272011-11-05 03:34:23 +0000311}
312
Ted Kremenek4548e042011-12-17 05:26:11 +0000313unsigned SDiagsWriter::getEmitFile(const char *FileName){
314 if (!FileName)
Ted Kremenekf264a202011-11-05 00:10:11 +0000315 return 0;
316
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000317 unsigned &entry = State->Files[FileName];
Ted Kremenekf264a202011-11-05 00:10:11 +0000318 if (entry)
319 return entry;
320
321 // Lazily generate the record for the file.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000322 entry = State->Files.size();
Ted Kremenekf264a202011-11-05 00:10:11 +0000323 RecordData Record;
324 Record.push_back(RECORD_FILENAME);
325 Record.push_back(entry);
Ted Kremenek4548e042011-12-17 05:26:11 +0000326 Record.push_back(0); // For legacy.
327 Record.push_back(0); // For legacy.
328 StringRef Name(FileName);
Ted Kremenekf264a202011-11-05 00:10:11 +0000329 Record.push_back(Name.size());
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000330 State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
331 Name);
Ted Kremenekf264a202011-11-05 00:10:11 +0000332
333 return entry;
334}
335
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000336void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
Ted Kremenek4548e042011-12-17 05:26:11 +0000337 const SourceManager &SM) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000338 State->Record.clear();
339 State->Record.push_back(RECORD_SOURCE_RANGE);
340 AddCharSourceRangeToRecord(R, State->Record, SM);
341 State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE),
342 State->Record);
Ted Kremenek59f10252011-11-05 00:10:01 +0000343}
344
Ted Kremenek4610ea22011-10-29 00:12:39 +0000345/// \brief Emits the preamble of the diagnostics file.
346void SDiagsWriter::EmitPreamble() {
Ted Kremenek4610ea22011-10-29 00:12:39 +0000347 // Emit the file header.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000348 State->Stream.Emit((unsigned)'D', 8);
349 State->Stream.Emit((unsigned)'I', 8);
350 State->Stream.Emit((unsigned)'A', 8);
351 State->Stream.Emit((unsigned)'G', 8);
Ted Kremenek868504a2011-11-05 00:09:53 +0000352
Ted Kremenek4610ea22011-10-29 00:12:39 +0000353 EmitBlockInfoBlock();
Ted Kremenekcc88d262011-11-08 20:27:29 +0000354 EmitMetaBlock();
Ted Kremenek4610ea22011-10-29 00:12:39 +0000355}
356
Ted Kremenek59f10252011-11-05 00:10:01 +0000357static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
358 using namespace llvm;
Ted Kremenekf264a202011-11-05 00:10:11 +0000359 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
Ted Kremenek59f10252011-11-05 00:10:01 +0000360 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
361 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
362 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
363}
Ted Kremenekd89a8272011-11-05 03:34:23 +0000364
365static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
366 AddSourceLocationAbbrev(Abbrev);
367 AddSourceLocationAbbrev(Abbrev);
368}
369
Ted Kremenek4610ea22011-10-29 00:12:39 +0000370void SDiagsWriter::EmitBlockInfoBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000371 State->Stream.EnterBlockInfoBlock(3);
Ted Kremenekcc88d262011-11-08 20:27:29 +0000372
373 using namespace llvm;
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000374 llvm::BitstreamWriter &Stream = State->Stream;
375 RecordData &Record = State->Record;
376 AbbreviationMap &Abbrevs = State->Abbrevs;
Ted Kremenekcc88d262011-11-08 20:27:29 +0000377
378 // ==---------------------------------------------------------------------==//
379 // The subsequent records and Abbrevs are for the "Meta" block.
380 // ==---------------------------------------------------------------------==//
381
382 EmitBlockID(BLOCK_META, "Meta", Stream, Record);
383 EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
384 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
385 Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
386 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
387 Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
388
Ted Kremenek4610ea22011-10-29 00:12:39 +0000389 // ==---------------------------------------------------------------------==//
390 // The subsequent records and Abbrevs are for the "Diagnostic" block.
391 // ==---------------------------------------------------------------------==//
392
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000393 EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
394 EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
Ted Kremenek59f10252011-11-05 00:10:01 +0000395 EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
Ted Kremenek319215062011-11-05 00:10:04 +0000396 EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000397 EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
Ted Kremenekf264a202011-11-05 00:10:11 +0000398 EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
Ted Kremenekd89a8272011-11-05 03:34:23 +0000399 EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000400
Ted Kremenek4610ea22011-10-29 00:12:39 +0000401 // Emit abbreviation for RECORD_DIAG.
Ted Kremenekcc88d262011-11-08 20:27:29 +0000402 Abbrev = new BitCodeAbbrev();
Ted Kremenek4610ea22011-10-29 00:12:39 +0000403 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000404 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level.
Ted Kremenek59f10252011-11-05 00:10:01 +0000405 AddSourceLocationAbbrev(Abbrev);
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000406 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
407 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000408 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
409 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
410 Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek59f10252011-11-05 00:10:01 +0000411
Ted Kremenek319215062011-11-05 00:10:04 +0000412 // Emit abbrevation for RECORD_CATEGORY.
413 Abbrev = new BitCodeAbbrev();
414 Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
415 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
416 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size.
417 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text.
418 Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
419
Ted Kremenek59f10252011-11-05 00:10:01 +0000420 // Emit abbrevation for RECORD_SOURCE_RANGE.
421 Abbrev = new BitCodeAbbrev();
422 Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
Ted Kremenekd89a8272011-11-05 03:34:23 +0000423 AddRangeLocationAbbrev(Abbrev);
Ted Kremenek59f10252011-11-05 00:10:01 +0000424 Abbrevs.set(RECORD_SOURCE_RANGE,
425 Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000426
427 // Emit the abbreviation for RECORD_DIAG_FLAG.
428 Abbrev = new BitCodeAbbrev();
429 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
430 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
431 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
432 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
433 Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
434 Abbrev));
Ted Kremenekf264a202011-11-05 00:10:11 +0000435
436 // Emit the abbreviation for RECORD_FILENAME.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000437 Abbrev = new BitCodeAbbrev();
Ted Kremenekfce371a2011-11-05 00:09:43 +0000438 Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
Ted Kremenekf264a202011-11-05 00:10:11 +0000439 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
440 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
441 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000442 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
443 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
Ted Kremenekf264a202011-11-05 00:10:11 +0000444 Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Ted Kremenek4610ea22011-10-29 00:12:39 +0000445 Abbrev));
Ted Kremenekd89a8272011-11-05 03:34:23 +0000446
447 // Emit the abbreviation for RECORD_FIXIT.
448 Abbrev = new BitCodeAbbrev();
449 Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
450 AddRangeLocationAbbrev(Abbrev);
451 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
452 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text.
453 Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
454 Abbrev));
Ted Kremenek4610ea22011-10-29 00:12:39 +0000455
456 Stream.ExitBlock();
457}
458
Ted Kremenekcc88d262011-11-08 20:27:29 +0000459void SDiagsWriter::EmitMetaBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000460 llvm::BitstreamWriter &Stream = State->Stream;
461 RecordData &Record = State->Record;
462 AbbreviationMap &Abbrevs = State->Abbrevs;
463
Ted Kremenekcc88d262011-11-08 20:27:29 +0000464 Stream.EnterSubblock(BLOCK_META, 3);
465 Record.clear();
466 Record.push_back(RECORD_VERSION);
467 Record.push_back(Version);
468 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
469 Stream.ExitBlock();
470}
471
Ted Kremenek4548e042011-12-17 05:26:11 +0000472unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000473 if (State->Categories.count(category))
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000474 return category;
475
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000476 State->Categories.insert(category);
Ted Kremenek319215062011-11-05 00:10:04 +0000477
478 // We use a local version of 'Record' so that we can be generating
479 // another record when we lazily generate one for the category entry.
480 RecordData Record;
481 Record.push_back(RECORD_CATEGORY);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000482 Record.push_back(category);
483 StringRef catName = DiagnosticIDs::getCategoryNameFromID(category);
Ted Kremenek319215062011-11-05 00:10:04 +0000484 Record.push_back(catName.size());
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000485 State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_CATEGORY), Record,
486 catName);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000487
488 return category;
489}
490
491unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
Ted Kremenek4548e042011-12-17 05:26:11 +0000492 unsigned DiagID) {
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000493 if (DiagLevel == DiagnosticsEngine::Note)
494 return 0; // No flag for notes.
495
Ted Kremenek4548e042011-12-17 05:26:11 +0000496 StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000497 if (FlagName.empty())
498 return 0;
499
500 // Here we assume that FlagName points to static data whose pointer
501 // value is fixed. This allows us to unique by diagnostic groups.
502 const void *data = FlagName.data();
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000503 std::pair<unsigned, StringRef> &entry = State->DiagFlags[data];
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000504 if (entry.first == 0) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000505 entry.first = State->DiagFlags.size();
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000506 entry.second = FlagName;
507
508 // Lazily emit the string in a separate record.
509 RecordData Record;
510 Record.push_back(RECORD_DIAG_FLAG);
511 Record.push_back(entry.first);
512 Record.push_back(FlagName.size());
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000513 State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_DIAG_FLAG),
514 Record, FlagName);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000515 }
516
517 return entry.first;
Ted Kremenek319215062011-11-05 00:10:04 +0000518}
519
Ted Kremenek4610ea22011-10-29 00:12:39 +0000520void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
521 const Diagnostic &Info) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000522 // Enter the block for a non-note diagnostic immediately, rather than waiting
523 // for beginDiagnostic, in case associated notes are emitted before we get
524 // there.
Ted Kremenekf67bbca2011-11-05 00:09:47 +0000525 if (DiagLevel != DiagnosticsEngine::Note) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000526 if (State->EmittedAnyDiagBlocks)
Richard Smitha9f521f2012-08-21 03:11:53 +0000527 ExitDiagBlock();
528
529 EnterDiagBlock();
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000530 State->EmittedAnyDiagBlocks = true;
Ted Kremenekf67bbca2011-11-05 00:09:47 +0000531 }
Ted Kremenekd89a8272011-11-05 03:34:23 +0000532
Ted Kremenek4548e042011-12-17 05:26:11 +0000533 // Compute the diagnostic text.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000534 State->diagBuf.clear();
535 Info.FormatDiagnostic(State->diagBuf);
Ted Kremenek4548e042011-12-17 05:26:11 +0000536
Richard Smitha9f521f2012-08-21 03:11:53 +0000537 if (Info.getLocation().isInvalid()) {
538 // Special-case diagnostics with no location. We may not have entered a
539 // source file in this case, so we can't use the normal DiagnosticsRenderer
540 // machinery.
Ted Kremenekc6ebda12013-02-21 21:40:44 +0000541
542 // Make sure we bracket all notes as "sub-diagnostics". This matches
543 // the behavior in SDiagsRenderer::emitDiagnostic().
544 if (DiagLevel == DiagnosticsEngine::Note)
545 EnterDiagBlock();
546
Richard Smitha9f521f2012-08-21 03:11:53 +0000547 EmitDiagnosticMessage(SourceLocation(), PresumedLoc(), DiagLevel,
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000548 State->diagBuf, 0, &Info);
Ted Kremenekc6ebda12013-02-21 21:40:44 +0000549
550 if (DiagLevel == DiagnosticsEngine::Note)
551 ExitDiagBlock();
552
Richard Smitha9f521f2012-08-21 03:11:53 +0000553 return;
554 }
555
556 assert(Info.hasSourceManager() && LangOpts &&
557 "Unexpected diagnostic with valid location outside of a source file");
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000558 SDiagsRenderer Renderer(*this, *LangOpts, &*State->DiagOpts);
Ted Kremenek4548e042011-12-17 05:26:11 +0000559 Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000560 State->diagBuf.str(),
Ted Kremenek4548e042011-12-17 05:26:11 +0000561 Info.getRanges(),
562 llvm::makeArrayRef(Info.getFixItHints(),
563 Info.getNumFixItHints()),
Richard Smitha9f521f2012-08-21 03:11:53 +0000564 &Info.getSourceManager(),
Ted Kremenek4548e042011-12-17 05:26:11 +0000565 &Info);
566}
567
Jordan Rose7ef1c382014-03-03 18:29:52 +0000568static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
569 switch (Level) {
570#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X;
571 CASE(Ignored)
572 CASE(Note)
573 CASE(Remark)
574 CASE(Warning)
575 CASE(Error)
576 CASE(Fatal)
577#undef CASE
578 }
579
580 llvm_unreachable("invalid diagnostic level");
581}
582
Richard Smitha9f521f2012-08-21 03:11:53 +0000583void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
584 PresumedLoc PLoc,
585 DiagnosticsEngine::Level Level,
586 StringRef Message,
587 const SourceManager *SM,
588 DiagOrStoredDiag D) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000589 llvm::BitstreamWriter &Stream = State->Stream;
590 RecordData &Record = State->Record;
591 AbbreviationMap &Abbrevs = State->Abbrevs;
592
Richard Smitha9f521f2012-08-21 03:11:53 +0000593 // Emit the RECORD_DIAG record.
594 Record.clear();
595 Record.push_back(RECORD_DIAG);
Jordan Rose7ef1c382014-03-03 18:29:52 +0000596 Record.push_back(getStableLevel(Level));
Richard Smitha9f521f2012-08-21 03:11:53 +0000597 AddLocToRecord(Loc, SM, PLoc, Record);
598
599 if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
600 // Emit the category string lazily and get the category ID.
601 unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
602 Record.push_back(getEmitCategory(DiagID));
603 // Emit the diagnostic flag string lazily and get the mapped ID.
604 Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
605 } else {
606 Record.push_back(getEmitCategory());
607 Record.push_back(getEmitDiagnosticFlag(Level));
608 }
609
610 Record.push_back(Message.size());
611 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
612}
613
Ted Kremenek4548e042011-12-17 05:26:11 +0000614void
615SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
616 PresumedLoc PLoc,
617 DiagnosticsEngine::Level Level,
618 StringRef Message,
619 ArrayRef<clang::CharSourceRange> Ranges,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000620 const SourceManager *SM,
Ted Kremenek0964cca2012-02-14 02:46:00 +0000621 DiagOrStoredDiag D) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000622 Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
623}
Ted Kremenek4548e042011-12-17 05:26:11 +0000624
Richard Smitha9f521f2012-08-21 03:11:53 +0000625void SDiagsWriter::EnterDiagBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000626 State->Stream.EnterSubblock(BLOCK_DIAG, 4);
Richard Smitha9f521f2012-08-21 03:11:53 +0000627}
Ted Kremenek4548e042011-12-17 05:26:11 +0000628
Richard Smitha9f521f2012-08-21 03:11:53 +0000629void SDiagsWriter::ExitDiagBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000630 State->Stream.ExitBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000631}
632
Ted Kremenek0964cca2012-02-14 02:46:00 +0000633void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
Ted Kremenek4548e042011-12-17 05:26:11 +0000634 DiagnosticsEngine::Level Level) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000635 if (Level == DiagnosticsEngine::Note)
636 Writer.EnterDiagBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000637}
638
Ted Kremenek0964cca2012-02-14 02:46:00 +0000639void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
Ted Kremenek4548e042011-12-17 05:26:11 +0000640 DiagnosticsEngine::Level Level) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000641 // Only end note diagnostics here, because we can't be sure when we've seen
642 // the last note associated with a non-note diagnostic.
643 if (Level == DiagnosticsEngine::Note)
644 Writer.ExitDiagBlock();
645}
646
647void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
648 ArrayRef<FixItHint> Hints,
649 const SourceManager &SM) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000650 llvm::BitstreamWriter &Stream = State->Stream;
651 RecordData &Record = State->Record;
652 AbbreviationMap &Abbrevs = State->Abbrevs;
653
Richard Smitha9f521f2012-08-21 03:11:53 +0000654 // Emit Source Ranges.
655 for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
656 I != E; ++I)
657 if (I->isValid())
658 EmitCharSourceRange(*I, SM);
659
660 // Emit FixIts.
661 for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
662 I != E; ++I) {
663 const FixItHint &Fix = *I;
664 if (Fix.isNull())
665 continue;
666 Record.clear();
667 Record.push_back(RECORD_FIXIT);
668 AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
669 Record.push_back(Fix.CodeToInsert.size());
670 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
671 Fix.CodeToInsert);
672 }
Ted Kremenek4548e042011-12-17 05:26:11 +0000673}
674
675void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
676 DiagnosticsEngine::Level Level,
677 SmallVectorImpl<CharSourceRange> &Ranges,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000678 ArrayRef<FixItHint> Hints,
Richard Smitha9f521f2012-08-21 03:11:53 +0000679 const SourceManager &SM) {
680 Writer.EmitCodeContext(Ranges, Hints, SM);
Ted Kremenek4610ea22011-10-29 00:12:39 +0000681}
682
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000683void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
684 const SourceManager *SM) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000685 Writer.EnterDiagBlock();
686 PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
687 Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
688 Message, SM, DiagOrStoredDiag());
689 Writer.ExitDiagBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000690}
691
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000692void SDiagsWriter::finish() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000693 // The original instance is responsible for writing the file.
694 if (!OriginalInstance)
695 return;
696
Richard Smitha9f521f2012-08-21 03:11:53 +0000697 // Finish off any diagnostic we were in the process of emitting.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000698 if (State->EmittedAnyDiagBlocks)
Richard Smitha9f521f2012-08-21 03:11:53 +0000699 ExitDiagBlock();
Ted Kremenekf264a202011-11-05 00:10:11 +0000700
Ted Kremenek4610ea22011-10-29 00:12:39 +0000701 // Write the generated bitstream to "Out".
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000702 State->OS->write((char *)&State->Buffer.front(), State->Buffer.size());
703 State->OS->flush();
Richard Smitha9f521f2012-08-21 03:11:53 +0000704
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000705 State->OS.reset(0);
Ted Kremenek4610ea22011-10-29 00:12:39 +0000706}