xref: /aosp_15_r20/external/clang/lib/Frontend/SerializedDiagnosticReader.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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