1*67e74705SXin Li //===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li
10*67e74705SXin Li #include "clang/Frontend/SerializedDiagnosticReader.h"
11*67e74705SXin Li #include "clang/Basic/FileManager.h"
12*67e74705SXin Li #include "clang/Frontend/SerializedDiagnostics.h"
13*67e74705SXin Li #include "llvm/Support/ManagedStatic.h"
14*67e74705SXin Li #include "llvm/Support/MemoryBuffer.h"
15*67e74705SXin Li
16*67e74705SXin Li using namespace clang;
17*67e74705SXin Li using namespace clang::serialized_diags;
18*67e74705SXin Li
readDiagnostics(StringRef File)19*67e74705SXin Li std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
20*67e74705SXin Li // Open the diagnostics file.
21*67e74705SXin Li FileSystemOptions FO;
22*67e74705SXin Li FileManager FileMgr(FO);
23*67e74705SXin Li
24*67e74705SXin Li auto Buffer = FileMgr.getBufferForFile(File);
25*67e74705SXin Li if (!Buffer)
26*67e74705SXin Li return SDError::CouldNotLoad;
27*67e74705SXin Li
28*67e74705SXin Li llvm::BitstreamReader StreamFile;
29*67e74705SXin Li StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
30*67e74705SXin Li (const unsigned char *)(*Buffer)->getBufferEnd());
31*67e74705SXin Li
32*67e74705SXin Li llvm::BitstreamCursor Stream(StreamFile);
33*67e74705SXin Li
34*67e74705SXin Li // Sniff for the signature.
35*67e74705SXin Li if (Stream.Read(8) != 'D' ||
36*67e74705SXin Li Stream.Read(8) != 'I' ||
37*67e74705SXin Li Stream.Read(8) != 'A' ||
38*67e74705SXin Li Stream.Read(8) != 'G')
39*67e74705SXin Li return SDError::InvalidSignature;
40*67e74705SXin Li
41*67e74705SXin Li // Read the top level blocks.
42*67e74705SXin Li while (!Stream.AtEndOfStream()) {
43*67e74705SXin Li if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
44*67e74705SXin Li return SDError::InvalidDiagnostics;
45*67e74705SXin Li
46*67e74705SXin Li std::error_code EC;
47*67e74705SXin Li switch (Stream.ReadSubBlockID()) {
48*67e74705SXin Li case llvm::bitc::BLOCKINFO_BLOCK_ID:
49*67e74705SXin Li if (Stream.ReadBlockInfoBlock())
50*67e74705SXin Li return SDError::MalformedBlockInfoBlock;
51*67e74705SXin Li continue;
52*67e74705SXin Li case BLOCK_META:
53*67e74705SXin Li if ((EC = readMetaBlock(Stream)))
54*67e74705SXin Li return EC;
55*67e74705SXin Li continue;
56*67e74705SXin Li case BLOCK_DIAG:
57*67e74705SXin Li if ((EC = readDiagnosticBlock(Stream)))
58*67e74705SXin Li return EC;
59*67e74705SXin Li continue;
60*67e74705SXin Li default:
61*67e74705SXin Li if (!Stream.SkipBlock())
62*67e74705SXin Li return SDError::MalformedTopLevelBlock;
63*67e74705SXin Li continue;
64*67e74705SXin Li }
65*67e74705SXin Li }
66*67e74705SXin Li return std::error_code();
67*67e74705SXin Li }
68*67e74705SXin Li
69*67e74705SXin Li enum class SerializedDiagnosticReader::Cursor {
70*67e74705SXin Li Record = 1,
71*67e74705SXin Li BlockEnd,
72*67e74705SXin Li BlockBegin
73*67e74705SXin Li };
74*67e74705SXin Li
75*67e74705SXin Li llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
skipUntilRecordOrBlock(llvm::BitstreamCursor & Stream,unsigned & BlockOrRecordID)76*67e74705SXin Li SerializedDiagnosticReader::skipUntilRecordOrBlock(
77*67e74705SXin Li llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
78*67e74705SXin Li BlockOrRecordID = 0;
79*67e74705SXin Li
80*67e74705SXin Li while (!Stream.AtEndOfStream()) {
81*67e74705SXin Li unsigned Code = Stream.ReadCode();
82*67e74705SXin Li
83*67e74705SXin Li switch ((llvm::bitc::FixedAbbrevIDs)Code) {
84*67e74705SXin Li case llvm::bitc::ENTER_SUBBLOCK:
85*67e74705SXin Li BlockOrRecordID = Stream.ReadSubBlockID();
86*67e74705SXin Li return Cursor::BlockBegin;
87*67e74705SXin Li
88*67e74705SXin Li case llvm::bitc::END_BLOCK:
89*67e74705SXin Li if (Stream.ReadBlockEnd())
90*67e74705SXin Li return SDError::InvalidDiagnostics;
91*67e74705SXin Li return Cursor::BlockEnd;
92*67e74705SXin Li
93*67e74705SXin Li case llvm::bitc::DEFINE_ABBREV:
94*67e74705SXin Li Stream.ReadAbbrevRecord();
95*67e74705SXin Li continue;
96*67e74705SXin Li
97*67e74705SXin Li case llvm::bitc::UNABBREV_RECORD:
98*67e74705SXin Li return SDError::UnsupportedConstruct;
99*67e74705SXin Li
100*67e74705SXin Li default:
101*67e74705SXin Li // We found a record.
102*67e74705SXin Li BlockOrRecordID = Code;
103*67e74705SXin Li return Cursor::Record;
104*67e74705SXin Li }
105*67e74705SXin Li }
106*67e74705SXin Li
107*67e74705SXin Li return SDError::InvalidDiagnostics;
108*67e74705SXin Li }
109*67e74705SXin Li
110*67e74705SXin Li std::error_code
readMetaBlock(llvm::BitstreamCursor & Stream)111*67e74705SXin Li SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
112*67e74705SXin Li if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
113*67e74705SXin Li return SDError::MalformedMetadataBlock;
114*67e74705SXin Li
115*67e74705SXin Li bool VersionChecked = false;
116*67e74705SXin Li
117*67e74705SXin Li while (true) {
118*67e74705SXin Li unsigned BlockOrCode = 0;
119*67e74705SXin Li llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
120*67e74705SXin Li if (!Res)
121*67e74705SXin Li Res.getError();
122*67e74705SXin Li
123*67e74705SXin Li switch (Res.get()) {
124*67e74705SXin Li case Cursor::Record:
125*67e74705SXin Li break;
126*67e74705SXin Li case Cursor::BlockBegin:
127*67e74705SXin Li if (Stream.SkipBlock())
128*67e74705SXin Li return SDError::MalformedMetadataBlock;
129*67e74705SXin Li case Cursor::BlockEnd:
130*67e74705SXin Li if (!VersionChecked)
131*67e74705SXin Li return SDError::MissingVersion;
132*67e74705SXin Li return std::error_code();
133*67e74705SXin Li }
134*67e74705SXin Li
135*67e74705SXin Li SmallVector<uint64_t, 1> Record;
136*67e74705SXin Li unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
137*67e74705SXin Li
138*67e74705SXin Li if (RecordID == RECORD_VERSION) {
139*67e74705SXin Li if (Record.size() < 1)
140*67e74705SXin Li return SDError::MissingVersion;
141*67e74705SXin Li if (Record[0] > VersionNumber)
142*67e74705SXin Li return SDError::VersionMismatch;
143*67e74705SXin Li VersionChecked = true;
144*67e74705SXin Li }
145*67e74705SXin Li }
146*67e74705SXin Li }
147*67e74705SXin Li
148*67e74705SXin Li std::error_code
readDiagnosticBlock(llvm::BitstreamCursor & Stream)149*67e74705SXin Li SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
150*67e74705SXin Li if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
151*67e74705SXin Li return SDError::MalformedDiagnosticBlock;
152*67e74705SXin Li
153*67e74705SXin Li std::error_code EC;
154*67e74705SXin Li if ((EC = visitStartOfDiagnostic()))
155*67e74705SXin Li return EC;
156*67e74705SXin Li
157*67e74705SXin Li SmallVector<uint64_t, 16> Record;
158*67e74705SXin Li while (true) {
159*67e74705SXin Li unsigned BlockOrCode = 0;
160*67e74705SXin Li llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
161*67e74705SXin Li if (!Res)
162*67e74705SXin Li Res.getError();
163*67e74705SXin Li
164*67e74705SXin Li switch (Res.get()) {
165*67e74705SXin Li case Cursor::BlockBegin:
166*67e74705SXin Li // The only blocks we care about are subdiagnostics.
167*67e74705SXin Li if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
168*67e74705SXin Li if ((EC = readDiagnosticBlock(Stream)))
169*67e74705SXin Li return EC;
170*67e74705SXin Li } else if (!Stream.SkipBlock())
171*67e74705SXin Li return SDError::MalformedSubBlock;
172*67e74705SXin Li continue;
173*67e74705SXin Li case Cursor::BlockEnd:
174*67e74705SXin Li if ((EC = visitEndOfDiagnostic()))
175*67e74705SXin Li return EC;
176*67e74705SXin Li return std::error_code();
177*67e74705SXin Li case Cursor::Record:
178*67e74705SXin Li break;
179*67e74705SXin Li }
180*67e74705SXin Li
181*67e74705SXin Li // Read the record.
182*67e74705SXin Li Record.clear();
183*67e74705SXin Li StringRef Blob;
184*67e74705SXin Li unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
185*67e74705SXin Li
186*67e74705SXin Li if (RecID < serialized_diags::RECORD_FIRST ||
187*67e74705SXin Li RecID > serialized_diags::RECORD_LAST)
188*67e74705SXin Li continue;
189*67e74705SXin Li
190*67e74705SXin Li switch ((RecordIDs)RecID) {
191*67e74705SXin Li case RECORD_CATEGORY:
192*67e74705SXin Li // A category has ID and name size.
193*67e74705SXin Li if (Record.size() != 2)
194*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
195*67e74705SXin Li if ((EC = visitCategoryRecord(Record[0], Blob)))
196*67e74705SXin Li return EC;
197*67e74705SXin Li continue;
198*67e74705SXin Li case RECORD_DIAG:
199*67e74705SXin Li // A diagnostic has severity, location (4), category, flag, and message
200*67e74705SXin Li // size.
201*67e74705SXin Li if (Record.size() != 8)
202*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
203*67e74705SXin Li if ((EC = visitDiagnosticRecord(
204*67e74705SXin Li Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
205*67e74705SXin Li Record[5], Record[6], Blob)))
206*67e74705SXin Li return EC;
207*67e74705SXin Li continue;
208*67e74705SXin Li case RECORD_DIAG_FLAG:
209*67e74705SXin Li // A diagnostic flag has ID and name size.
210*67e74705SXin Li if (Record.size() != 2)
211*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
212*67e74705SXin Li if ((EC = visitDiagFlagRecord(Record[0], Blob)))
213*67e74705SXin Li return EC;
214*67e74705SXin Li continue;
215*67e74705SXin Li case RECORD_FILENAME:
216*67e74705SXin Li // A filename has ID, size, timestamp, and name size. The size and
217*67e74705SXin Li // timestamp are legacy fields that are always zero these days.
218*67e74705SXin Li if (Record.size() != 4)
219*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
220*67e74705SXin Li if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
221*67e74705SXin Li return EC;
222*67e74705SXin Li continue;
223*67e74705SXin Li case RECORD_FIXIT:
224*67e74705SXin Li // A fixit has two locations (4 each) and message size.
225*67e74705SXin Li if (Record.size() != 9)
226*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
227*67e74705SXin Li if ((EC = visitFixitRecord(
228*67e74705SXin Li Location(Record[0], Record[1], Record[2], Record[3]),
229*67e74705SXin Li Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
230*67e74705SXin Li return EC;
231*67e74705SXin Li continue;
232*67e74705SXin Li case RECORD_SOURCE_RANGE:
233*67e74705SXin Li // A source range is two locations (4 each).
234*67e74705SXin Li if (Record.size() != 8)
235*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
236*67e74705SXin Li if ((EC = visitSourceRangeRecord(
237*67e74705SXin Li Location(Record[0], Record[1], Record[2], Record[3]),
238*67e74705SXin Li Location(Record[4], Record[5], Record[6], Record[7]))))
239*67e74705SXin Li return EC;
240*67e74705SXin Li continue;
241*67e74705SXin Li case RECORD_VERSION:
242*67e74705SXin Li // A version is just a number.
243*67e74705SXin Li if (Record.size() != 1)
244*67e74705SXin Li return SDError::MalformedDiagnosticRecord;
245*67e74705SXin Li if ((EC = visitVersionRecord(Record[0])))
246*67e74705SXin Li return EC;
247*67e74705SXin Li continue;
248*67e74705SXin Li }
249*67e74705SXin Li }
250*67e74705SXin Li }
251*67e74705SXin Li
252*67e74705SXin Li namespace {
253*67e74705SXin Li class SDErrorCategoryType final : public std::error_category {
name() const254*67e74705SXin Li const char *name() const LLVM_NOEXCEPT override {
255*67e74705SXin Li return "clang.serialized_diags";
256*67e74705SXin Li }
message(int IE) const257*67e74705SXin Li std::string message(int IE) const override {
258*67e74705SXin Li SDError E = static_cast<SDError>(IE);
259*67e74705SXin Li switch (E) {
260*67e74705SXin Li case SDError::CouldNotLoad:
261*67e74705SXin Li return "Failed to open diagnostics file";
262*67e74705SXin Li case SDError::InvalidSignature:
263*67e74705SXin Li return "Invalid diagnostics signature";
264*67e74705SXin Li case SDError::InvalidDiagnostics:
265*67e74705SXin Li return "Parse error reading diagnostics";
266*67e74705SXin Li case SDError::MalformedTopLevelBlock:
267*67e74705SXin Li return "Malformed block at top-level of diagnostics";
268*67e74705SXin Li case SDError::MalformedSubBlock:
269*67e74705SXin Li return "Malformed sub-block in a diagnostic";
270*67e74705SXin Li case SDError::MalformedBlockInfoBlock:
271*67e74705SXin Li return "Malformed BlockInfo block";
272*67e74705SXin Li case SDError::MalformedMetadataBlock:
273*67e74705SXin Li return "Malformed Metadata block";
274*67e74705SXin Li case SDError::MalformedDiagnosticBlock:
275*67e74705SXin Li return "Malformed Diagnostic block";
276*67e74705SXin Li case SDError::MalformedDiagnosticRecord:
277*67e74705SXin Li return "Malformed Diagnostic record";
278*67e74705SXin Li case SDError::MissingVersion:
279*67e74705SXin Li return "No version provided in diagnostics";
280*67e74705SXin Li case SDError::VersionMismatch:
281*67e74705SXin Li return "Unsupported diagnostics version";
282*67e74705SXin Li case SDError::UnsupportedConstruct:
283*67e74705SXin Li return "Bitcode constructs that are not supported in diagnostics appear";
284*67e74705SXin Li case SDError::HandlerFailed:
285*67e74705SXin Li return "Generic error occurred while handling a record";
286*67e74705SXin Li }
287*67e74705SXin Li llvm_unreachable("Unknown error type!");
288*67e74705SXin Li }
289*67e74705SXin Li };
290*67e74705SXin Li }
291*67e74705SXin Li
292*67e74705SXin Li static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
SDErrorCategory()293*67e74705SXin Li const std::error_category &clang::serialized_diags::SDErrorCategory() {
294*67e74705SXin Li return *ErrorCategory;
295*67e74705SXin Li }
296