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