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