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