blob: 3d6e7578c78d805c3f1dba1ed088c4874b27b48f [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)
Craig Topper49a27902014-05-22 04:46:25 +000096 : LangOpts(nullptr), OriginalInstance(false), State(State) {}
Douglas Gregorfa686fb2012-11-30 23:32:31 +000097
98public:
David Blaikieeb62b822014-08-29 20:17:13 +000099 SDiagsWriter(std::unique_ptr<raw_ostream> os, DiagnosticOptions *diags)
100 : LangOpts(nullptr), OriginalInstance(true),
101 State(new SharedState(std::move(os), diags)) {
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
Justin Bognerd776d672014-10-14 00:57:34 +0000175 /// \brief The version of the diagnostics file.
176 enum { Version = 2 };
177
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> {
David Blaikieeb62b822014-08-29 20:17:13 +0000189 SharedState(std::unique_ptr<raw_ostream> os, DiagnosticOptions *diags)
190 : DiagOpts(diags), Stream(Buffer), OS(std::move(os)),
191 EmittedAnyDiagBlocks(false) {}
Ted Kremenek4610ea22011-10-29 00:12:39 +0000192
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000193 /// \brief Diagnostic options.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000194 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000195
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000196 /// \brief The byte buffer for the serialized content.
197 SmallString<1024> Buffer;
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000198
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000199 /// \brief The BitStreamWriter for the serialized diagnostics.
200 llvm::BitstreamWriter Stream;
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000201
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000202 /// \brief The name of the diagnostics file.
Ahmed Charlesb8984322014-03-07 20:03:18 +0000203 std::unique_ptr<raw_ostream> OS;
Richard Smitha9f521f2012-08-21 03:11:53 +0000204
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000205 /// \brief The set of constructed record abbreviations.
206 AbbreviationMap Abbrevs;
207
208 /// \brief A utility buffer for constructing record content.
209 RecordData Record;
210
211 /// \brief A text buffer for rendering diagnostic text.
212 SmallString<256> diagBuf;
213
214 /// \brief The collection of diagnostic categories used.
215 llvm::DenseSet<unsigned> Categories;
216
217 /// \brief The collection of files used.
218 llvm::DenseMap<const char *, unsigned> Files;
219
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000220 typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> >
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000221 DiagFlagsTy;
222
223 /// \brief Map for uniquing strings.
224 DiagFlagsTy DiagFlags;
225
226 /// \brief Whether we have already started emission of any DIAG blocks. Once
227 /// this becomes \c true, we never close a DIAG block until we know that we're
228 /// starting another one or we're done.
229 bool EmittedAnyDiagBlocks;
230 };
231
232 /// \brief State shared among the various clones of this diagnostic consumer.
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000233 IntrusiveRefCntPtr<SharedState> State;
Ted Kremenek4610ea22011-10-29 00:12:39 +0000234};
235} // end anonymous namespace
236
237namespace clang {
238namespace serialized_diags {
David Blaikie7ee25502014-09-15 17:50:10 +0000239std::unique_ptr<DiagnosticConsumer> create(std::unique_ptr<raw_ostream> OS,
240 DiagnosticOptions *diags) {
241 return llvm::make_unique<SDiagsWriter>(std::move(OS), diags);
Ted Kremenek4610ea22011-10-29 00:12:39 +0000242}
243} // end namespace serialized_diags
244} // end namespace clang
245
246//===----------------------------------------------------------------------===//
247// Serialization methods.
248//===----------------------------------------------------------------------===//
249
250/// \brief Emits a block ID in the BLOCKINFO block.
251static void EmitBlockID(unsigned ID, const char *Name,
252 llvm::BitstreamWriter &Stream,
253 RecordDataImpl &Record) {
254 Record.clear();
255 Record.push_back(ID);
256 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
257
258 // Emit the block name if present.
Craig Topper49a27902014-05-22 04:46:25 +0000259 if (!Name || Name[0] == 0)
Ted Kremenek4610ea22011-10-29 00:12:39 +0000260 return;
261
262 Record.clear();
263
264 while (*Name)
265 Record.push_back(*Name++);
266
267 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
268}
269
270/// \brief Emits a record ID in the BLOCKINFO block.
271static void EmitRecordID(unsigned ID, const char *Name,
272 llvm::BitstreamWriter &Stream,
273 RecordDataImpl &Record){
274 Record.clear();
275 Record.push_back(ID);
276
277 while (*Name)
278 Record.push_back(*Name++);
279
280 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
281}
282
Ted Kremenekf264a202011-11-05 00:10:11 +0000283void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000284 const SourceManager *SM,
Ted Kremenek4548e042011-12-17 05:26:11 +0000285 PresumedLoc PLoc,
Ted Kremenekd010ba42011-11-10 08:43:12 +0000286 RecordDataImpl &Record,
287 unsigned TokSize) {
Ted Kremenek4548e042011-12-17 05:26:11 +0000288 if (PLoc.isInvalid()) {
Ted Kremenek59f10252011-11-05 00:10:01 +0000289 // Emit a "sentinel" location.
Ted Kremenekd010ba42011-11-10 08:43:12 +0000290 Record.push_back((unsigned)0); // File.
291 Record.push_back((unsigned)0); // Line.
292 Record.push_back((unsigned)0); // Column.
293 Record.push_back((unsigned)0); // Offset.
Ted Kremenek59f10252011-11-05 00:10:01 +0000294 return;
295 }
296
Ted Kremenek4548e042011-12-17 05:26:11 +0000297 Record.push_back(getEmitFile(PLoc.getFilename()));
298 Record.push_back(PLoc.getLine());
299 Record.push_back(PLoc.getColumn()+TokSize);
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000300 Record.push_back(SM->getFileOffset(Loc));
Ted Kremenek59f10252011-11-05 00:10:01 +0000301}
302
Ted Kremenekd89a8272011-11-05 03:34:23 +0000303void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000304 RecordDataImpl &Record,
Ted Kremenek4548e042011-12-17 05:26:11 +0000305 const SourceManager &SM) {
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000306 AddLocToRecord(Range.getBegin(), Record, &SM);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000307 unsigned TokSize = 0;
308 if (Range.isTokenRange())
309 TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000310 SM, *LangOpts);
Ted Kremenekd010ba42011-11-10 08:43:12 +0000311
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000312 AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
Ted Kremenekd89a8272011-11-05 03:34:23 +0000313}
314
Ted Kremenek4548e042011-12-17 05:26:11 +0000315unsigned SDiagsWriter::getEmitFile(const char *FileName){
316 if (!FileName)
Ted Kremenekf264a202011-11-05 00:10:11 +0000317 return 0;
318
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000319 unsigned &entry = State->Files[FileName];
Ted Kremenekf264a202011-11-05 00:10:11 +0000320 if (entry)
321 return entry;
322
323 // Lazily generate the record for the file.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000324 entry = State->Files.size();
Ted Kremenekf264a202011-11-05 00:10:11 +0000325 RecordData Record;
326 Record.push_back(RECORD_FILENAME);
327 Record.push_back(entry);
Ted Kremenek4548e042011-12-17 05:26:11 +0000328 Record.push_back(0); // For legacy.
329 Record.push_back(0); // For legacy.
330 StringRef Name(FileName);
Ted Kremenekf264a202011-11-05 00:10:11 +0000331 Record.push_back(Name.size());
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000332 State->Stream.EmitRecordWithBlob(State->Abbrevs.get(RECORD_FILENAME), Record,
333 Name);
Ted Kremenekf264a202011-11-05 00:10:11 +0000334
335 return entry;
336}
337
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000338void SDiagsWriter::EmitCharSourceRange(CharSourceRange R,
Ted Kremenek4548e042011-12-17 05:26:11 +0000339 const SourceManager &SM) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000340 State->Record.clear();
341 State->Record.push_back(RECORD_SOURCE_RANGE);
342 AddCharSourceRangeToRecord(R, State->Record, SM);
343 State->Stream.EmitRecordWithAbbrev(State->Abbrevs.get(RECORD_SOURCE_RANGE),
344 State->Record);
Ted Kremenek59f10252011-11-05 00:10:01 +0000345}
346
Ted Kremenek4610ea22011-10-29 00:12:39 +0000347/// \brief Emits the preamble of the diagnostics file.
348void SDiagsWriter::EmitPreamble() {
Ted Kremenek4610ea22011-10-29 00:12:39 +0000349 // Emit the file header.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000350 State->Stream.Emit((unsigned)'D', 8);
351 State->Stream.Emit((unsigned)'I', 8);
352 State->Stream.Emit((unsigned)'A', 8);
353 State->Stream.Emit((unsigned)'G', 8);
Ted Kremenek868504a2011-11-05 00:09:53 +0000354
Ted Kremenek4610ea22011-10-29 00:12:39 +0000355 EmitBlockInfoBlock();
Ted Kremenekcc88d262011-11-08 20:27:29 +0000356 EmitMetaBlock();
Ted Kremenek4610ea22011-10-29 00:12:39 +0000357}
358
Ted Kremenek59f10252011-11-05 00:10:01 +0000359static void AddSourceLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
360 using namespace llvm;
Ted Kremenekf264a202011-11-05 00:10:11 +0000361 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // File ID.
Ted Kremenek59f10252011-11-05 00:10:01 +0000362 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Line.
363 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Column.
364 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Offset;
365}
Ted Kremenekd89a8272011-11-05 03:34:23 +0000366
367static void AddRangeLocationAbbrev(llvm::BitCodeAbbrev *Abbrev) {
368 AddSourceLocationAbbrev(Abbrev);
369 AddSourceLocationAbbrev(Abbrev);
370}
371
Ted Kremenek4610ea22011-10-29 00:12:39 +0000372void SDiagsWriter::EmitBlockInfoBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000373 State->Stream.EnterBlockInfoBlock(3);
Ted Kremenekcc88d262011-11-08 20:27:29 +0000374
375 using namespace llvm;
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000376 llvm::BitstreamWriter &Stream = State->Stream;
377 RecordData &Record = State->Record;
378 AbbreviationMap &Abbrevs = State->Abbrevs;
Ted Kremenekcc88d262011-11-08 20:27:29 +0000379
380 // ==---------------------------------------------------------------------==//
381 // The subsequent records and Abbrevs are for the "Meta" block.
382 // ==---------------------------------------------------------------------==//
383
384 EmitBlockID(BLOCK_META, "Meta", Stream, Record);
385 EmitRecordID(RECORD_VERSION, "Version", Stream, Record);
386 BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
387 Abbrev->Add(BitCodeAbbrevOp(RECORD_VERSION));
388 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
389 Abbrevs.set(RECORD_VERSION, Stream.EmitBlockInfoAbbrev(BLOCK_META, Abbrev));
390
Ted Kremenek4610ea22011-10-29 00:12:39 +0000391 // ==---------------------------------------------------------------------==//
392 // The subsequent records and Abbrevs are for the "Diagnostic" block.
393 // ==---------------------------------------------------------------------==//
394
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000395 EmitBlockID(BLOCK_DIAG, "Diag", Stream, Record);
396 EmitRecordID(RECORD_DIAG, "DiagInfo", Stream, Record);
Ted Kremenek59f10252011-11-05 00:10:01 +0000397 EmitRecordID(RECORD_SOURCE_RANGE, "SrcRange", Stream, Record);
Ted Kremenek319215062011-11-05 00:10:04 +0000398 EmitRecordID(RECORD_CATEGORY, "CatName", Stream, Record);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000399 EmitRecordID(RECORD_DIAG_FLAG, "DiagFlag", Stream, Record);
Ted Kremenekf264a202011-11-05 00:10:11 +0000400 EmitRecordID(RECORD_FILENAME, "FileName", Stream, Record);
Ted Kremenekd89a8272011-11-05 03:34:23 +0000401 EmitRecordID(RECORD_FIXIT, "FixIt", Stream, Record);
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000402
Ted Kremenek4610ea22011-10-29 00:12:39 +0000403 // Emit abbreviation for RECORD_DIAG.
Ted Kremenekcc88d262011-11-08 20:27:29 +0000404 Abbrev = new BitCodeAbbrev();
Ted Kremenek4610ea22011-10-29 00:12:39 +0000405 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG));
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000406 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Diag level.
Ted Kremenek59f10252011-11-05 00:10:01 +0000407 AddSourceLocationAbbrev(Abbrev);
Ted Kremenek2724b1f2011-11-05 00:09:50 +0000408 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Category.
409 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000410 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
411 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text.
412 Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek59f10252011-11-05 00:10:01 +0000413
Ted Kremenek319215062011-11-05 00:10:04 +0000414 // Emit abbrevation for RECORD_CATEGORY.
415 Abbrev = new BitCodeAbbrev();
416 Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY));
417 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID.
418 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // Text size.
419 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text.
420 Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
421
Ted Kremenek59f10252011-11-05 00:10:01 +0000422 // Emit abbrevation for RECORD_SOURCE_RANGE.
423 Abbrev = new BitCodeAbbrev();
424 Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE));
Ted Kremenekd89a8272011-11-05 03:34:23 +0000425 AddRangeLocationAbbrev(Abbrev);
Ted Kremenek59f10252011-11-05 00:10:01 +0000426 Abbrevs.set(RECORD_SOURCE_RANGE,
427 Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev));
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000428
429 // Emit the abbreviation for RECORD_DIAG_FLAG.
430 Abbrev = new BitCodeAbbrev();
431 Abbrev->Add(BitCodeAbbrevOp(RECORD_DIAG_FLAG));
432 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped Diag ID.
433 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
434 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Flag name text.
435 Abbrevs.set(RECORD_DIAG_FLAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
436 Abbrev));
Ted Kremenekf264a202011-11-05 00:10:11 +0000437
438 // Emit the abbreviation for RECORD_FILENAME.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000439 Abbrev = new BitCodeAbbrev();
Ted Kremenekfce371a2011-11-05 00:09:43 +0000440 Abbrev->Add(BitCodeAbbrevOp(RECORD_FILENAME));
Ted Kremenekf264a202011-11-05 00:10:11 +0000441 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); // Mapped file ID.
442 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Size.
443 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Modifcation time.
Ted Kremenek4610ea22011-10-29 00:12:39 +0000444 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
445 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name text.
Ted Kremenekf264a202011-11-05 00:10:11 +0000446 Abbrevs.set(RECORD_FILENAME, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
Ted Kremenek4610ea22011-10-29 00:12:39 +0000447 Abbrev));
Ted Kremenekd89a8272011-11-05 03:34:23 +0000448
449 // Emit the abbreviation for RECORD_FIXIT.
450 Abbrev = new BitCodeAbbrev();
451 Abbrev->Add(BitCodeAbbrevOp(RECORD_FIXIT));
452 AddRangeLocationAbbrev(Abbrev);
453 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Text size.
454 Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // FixIt text.
455 Abbrevs.set(RECORD_FIXIT, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG,
456 Abbrev));
Ted Kremenek4610ea22011-10-29 00:12:39 +0000457
458 Stream.ExitBlock();
459}
460
Ted Kremenekcc88d262011-11-08 20:27:29 +0000461void SDiagsWriter::EmitMetaBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000462 llvm::BitstreamWriter &Stream = State->Stream;
463 RecordData &Record = State->Record;
464 AbbreviationMap &Abbrevs = State->Abbrevs;
465
Ted Kremenekcc88d262011-11-08 20:27:29 +0000466 Stream.EnterSubblock(BLOCK_META, 3);
467 Record.clear();
468 Record.push_back(RECORD_VERSION);
Justin Bognerd776d672014-10-14 00:57:34 +0000469 Record.push_back(Version);
Ted Kremenekcc88d262011-11-08 20:27:29 +0000470 Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
471 Stream.ExitBlock();
472}
473
Ted Kremenek4548e042011-12-17 05:26:11 +0000474unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
Benjamin Kramerad8e0792014-10-10 15:32:48 +0000475 if (!State->Categories.insert(category).second)
Ted Kremenek0a49dae2011-11-05 00:10:07 +0000476 return category;
Benjamin Kramerad8e0792014-10-10 15:32:48 +0000477
Ted Kremenek319215062011-11-05 00:10:04 +0000478 // 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,
Craig Topper49a27902014-05-22 04:46:25 +0000548 State->diagBuf, nullptr, &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(),
Alexander Kornienkod3b4e082014-05-22 19:56:11 +0000562 Info.getFixItHints(),
Richard Smitha9f521f2012-08-21 03:11:53 +0000563 &Info.getSourceManager(),
Ted Kremenek4548e042011-12-17 05:26:11 +0000564 &Info);
565}
566
Jordan Rose7ef1c382014-03-03 18:29:52 +0000567static serialized_diags::Level getStableLevel(DiagnosticsEngine::Level Level) {
568 switch (Level) {
569#define CASE(X) case DiagnosticsEngine::X: return serialized_diags::X;
570 CASE(Ignored)
571 CASE(Note)
572 CASE(Remark)
573 CASE(Warning)
574 CASE(Error)
575 CASE(Fatal)
576#undef CASE
577 }
578
579 llvm_unreachable("invalid diagnostic level");
580}
581
Richard Smitha9f521f2012-08-21 03:11:53 +0000582void SDiagsWriter::EmitDiagnosticMessage(SourceLocation Loc,
583 PresumedLoc PLoc,
584 DiagnosticsEngine::Level Level,
585 StringRef Message,
586 const SourceManager *SM,
587 DiagOrStoredDiag D) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000588 llvm::BitstreamWriter &Stream = State->Stream;
589 RecordData &Record = State->Record;
590 AbbreviationMap &Abbrevs = State->Abbrevs;
591
Richard Smitha9f521f2012-08-21 03:11:53 +0000592 // Emit the RECORD_DIAG record.
593 Record.clear();
594 Record.push_back(RECORD_DIAG);
Jordan Rose7ef1c382014-03-03 18:29:52 +0000595 Record.push_back(getStableLevel(Level));
Richard Smitha9f521f2012-08-21 03:11:53 +0000596 AddLocToRecord(Loc, SM, PLoc, Record);
597
598 if (const Diagnostic *Info = D.dyn_cast<const Diagnostic*>()) {
599 // Emit the category string lazily and get the category ID.
600 unsigned DiagID = DiagnosticIDs::getCategoryNumberForDiag(Info->getID());
601 Record.push_back(getEmitCategory(DiagID));
602 // Emit the diagnostic flag string lazily and get the mapped ID.
603 Record.push_back(getEmitDiagnosticFlag(Level, Info->getID()));
604 } else {
605 Record.push_back(getEmitCategory());
606 Record.push_back(getEmitDiagnosticFlag(Level));
607 }
608
609 Record.push_back(Message.size());
610 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Message);
611}
612
Ted Kremenek4548e042011-12-17 05:26:11 +0000613void
614SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
615 PresumedLoc PLoc,
616 DiagnosticsEngine::Level Level,
617 StringRef Message,
618 ArrayRef<clang::CharSourceRange> Ranges,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000619 const SourceManager *SM,
Ted Kremenek0964cca2012-02-14 02:46:00 +0000620 DiagOrStoredDiag D) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000621 Writer.EmitDiagnosticMessage(Loc, PLoc, Level, Message, SM, D);
622}
Ted Kremenek4548e042011-12-17 05:26:11 +0000623
Richard Smitha9f521f2012-08-21 03:11:53 +0000624void SDiagsWriter::EnterDiagBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000625 State->Stream.EnterSubblock(BLOCK_DIAG, 4);
Richard Smitha9f521f2012-08-21 03:11:53 +0000626}
Ted Kremenek4548e042011-12-17 05:26:11 +0000627
Richard Smitha9f521f2012-08-21 03:11:53 +0000628void SDiagsWriter::ExitDiagBlock() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000629 State->Stream.ExitBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000630}
631
Ted Kremenek0964cca2012-02-14 02:46:00 +0000632void SDiagsRenderer::beginDiagnostic(DiagOrStoredDiag D,
Ted Kremenek4548e042011-12-17 05:26:11 +0000633 DiagnosticsEngine::Level Level) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000634 if (Level == DiagnosticsEngine::Note)
635 Writer.EnterDiagBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000636}
637
Ted Kremenek0964cca2012-02-14 02:46:00 +0000638void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
Ted Kremenek4548e042011-12-17 05:26:11 +0000639 DiagnosticsEngine::Level Level) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000640 // Only end note diagnostics here, because we can't be sure when we've seen
641 // the last note associated with a non-note diagnostic.
642 if (Level == DiagnosticsEngine::Note)
643 Writer.ExitDiagBlock();
644}
645
646void SDiagsWriter::EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges,
647 ArrayRef<FixItHint> Hints,
648 const SourceManager &SM) {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000649 llvm::BitstreamWriter &Stream = State->Stream;
650 RecordData &Record = State->Record;
651 AbbreviationMap &Abbrevs = State->Abbrevs;
652
Richard Smitha9f521f2012-08-21 03:11:53 +0000653 // Emit Source Ranges.
654 for (ArrayRef<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end();
655 I != E; ++I)
656 if (I->isValid())
657 EmitCharSourceRange(*I, SM);
658
659 // Emit FixIts.
660 for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
661 I != E; ++I) {
662 const FixItHint &Fix = *I;
663 if (Fix.isNull())
664 continue;
665 Record.clear();
666 Record.push_back(RECORD_FIXIT);
667 AddCharSourceRangeToRecord(Fix.RemoveRange, Record, SM);
668 Record.push_back(Fix.CodeToInsert.size());
669 Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_FIXIT), Record,
670 Fix.CodeToInsert);
671 }
Ted Kremenek4548e042011-12-17 05:26:11 +0000672}
673
674void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
675 DiagnosticsEngine::Level Level,
676 SmallVectorImpl<CharSourceRange> &Ranges,
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000677 ArrayRef<FixItHint> Hints,
Richard Smitha9f521f2012-08-21 03:11:53 +0000678 const SourceManager &SM) {
679 Writer.EmitCodeContext(Ranges, Hints, SM);
Ted Kremenek4610ea22011-10-29 00:12:39 +0000680}
681
Argyrios Kyrtzidisb16ff5d2012-05-10 05:03:45 +0000682void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
683 const SourceManager *SM) {
Richard Smitha9f521f2012-08-21 03:11:53 +0000684 Writer.EnterDiagBlock();
685 PresumedLoc PLoc = SM ? SM->getPresumedLoc(Loc) : PresumedLoc();
686 Writer.EmitDiagnosticMessage(Loc, PLoc, DiagnosticsEngine::Note,
687 Message, SM, DiagOrStoredDiag());
688 Writer.ExitDiagBlock();
Ted Kremenek4548e042011-12-17 05:26:11 +0000689}
690
Argyrios Kyrtzidis7910d7b2011-12-07 05:52:12 +0000691void SDiagsWriter::finish() {
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000692 // The original instance is responsible for writing the file.
693 if (!OriginalInstance)
694 return;
695
Richard Smitha9f521f2012-08-21 03:11:53 +0000696 // Finish off any diagnostic we were in the process of emitting.
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000697 if (State->EmittedAnyDiagBlocks)
Richard Smitha9f521f2012-08-21 03:11:53 +0000698 ExitDiagBlock();
Ted Kremenekf264a202011-11-05 00:10:11 +0000699
Ted Kremenek4610ea22011-10-29 00:12:39 +0000700 // Write the generated bitstream to "Out".
Douglas Gregorfa686fb2012-11-30 23:32:31 +0000701 State->OS->write((char *)&State->Buffer.front(), State->Buffer.size());
702 State->OS->flush();
Richard Smitha9f521f2012-08-21 03:11:53 +0000703
David Blaikie3875a822014-07-19 01:06:45 +0000704 State->OS.reset();
Ted Kremenek4610ea22011-10-29 00:12:39 +0000705}