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