13#include "llvm/ADT/SmallVector.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Bitstream/BitCodes.h"
16#include "llvm/Bitstream/BitstreamReader.h"
17#include "llvm/Support/Compiler.h"
18#include "llvm/Support/ErrorHandling.h"
19#include "llvm/Support/ErrorOr.h"
20#include "llvm/Support/ManagedStatic.h"
23#include <system_error>
26using namespace serialized_diags;
28std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef
File) {
33 auto Buffer = FileMgr.getBufferForFile(
File);
37 llvm::BitstreamCursor Stream(**Buffer);
38 std::optional<llvm::BitstreamBlockInfo> BlockInfo;
40 if (Stream.AtEndOfStream())
44 for (
unsigned char C : {
'D',
'I',
'A',
'G'}) {
50 consumeError(Res.takeError());
56 while (!Stream.AtEndOfStream()) {
58 if (Res.get() != llvm::bitc::ENTER_SUBBLOCK)
62 consumeError(Res.takeError());
68 if (!MaybeSubBlockID) {
70 consumeError(MaybeSubBlockID.takeError());
74 switch (MaybeSubBlockID.get()) {
75 case llvm::bitc::BLOCKINFO_BLOCK_ID: {
77 Stream.ReadBlockInfoBlock();
78 if (!MaybeBlockInfo) {
80 consumeError(MaybeBlockInfo.takeError());
83 BlockInfo = std::move(MaybeBlockInfo.get());
87 Stream.setBlockInfo(&*BlockInfo);
90 if ((EC = readMetaBlock(Stream)))
94 if ((EC = readDiagnosticBlock(Stream)))
98 if (llvm::Error Err = Stream.SkipBlock()) {
100 consumeError(std::move(Err));
115llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
116SerializedDiagnosticReader::skipUntilRecordOrBlock(
117 llvm::BitstreamCursor &Stream,
unsigned &BlockOrRecordID) {
120 while (!Stream.AtEndOfStream()) {
125 return llvm::errorToErrorCode(Res.takeError());
127 if (Code >=
static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
129 BlockOrRecordID = Code;
130 return Cursor::Record;
132 switch (
static_cast<llvm::bitc::FixedAbbrevIDs
>(Code)) {
133 case llvm::bitc::ENTER_SUBBLOCK:
135 BlockOrRecordID = Res.get();
137 return llvm::errorToErrorCode(Res.takeError());
138 return Cursor::BlockBegin;
140 case llvm::bitc::END_BLOCK:
141 if (Stream.ReadBlockEnd())
143 return Cursor::BlockEnd;
145 case llvm::bitc::DEFINE_ABBREV:
146 if (llvm::Error Err = Stream.ReadAbbrevRecord())
147 return llvm::errorToErrorCode(std::move(Err));
150 case llvm::bitc::UNABBREV_RECORD:
153 case llvm::bitc::FIRST_APPLICATION_ABBREV:
154 llvm_unreachable(
"Unexpected abbrev id.");
162SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
163 if (llvm::Error Err =
166 consumeError(std::move(Err));
170 bool VersionChecked =
false;
173 unsigned BlockOrCode = 0;
174 llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
181 case Cursor::BlockBegin:
182 if (llvm::Error Err = Stream.SkipBlock()) {
184 consumeError(std::move(Err));
188 case Cursor::BlockEnd:
197 return errorToErrorCode(MaybeRecordID.takeError());
198 unsigned RecordID = MaybeRecordID.get();
205 VersionChecked =
true;
211SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
212 if (llvm::Error Err =
215 consumeError(std::move(Err));
225 unsigned BlockOrCode = 0;
226 llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
231 case Cursor::BlockBegin:
234 if ((EC = readDiagnosticBlock(Stream)))
236 }
else if (llvm::Error Err = Stream.SkipBlock()) {
238 consumeError(std::move(Err));
242 case Cursor::BlockEnd:
254 Stream.readRecord(BlockOrCode,
Record, &Blob);
256 return errorToErrorCode(MaybeRecID.takeError());
257 unsigned RecID = MaybeRecID.get();
327class SDErrorCategoryType final :
public std::error_category {
328 const char *
name() const noexcept
override {
329 return "clang.serialized_diags";
332 std::string message(
int IE)
const override {
335 case SDError::CouldNotLoad:
336 return "Failed to open diagnostics file";
337 case SDError::InvalidSignature:
338 return "Invalid diagnostics signature";
339 case SDError::InvalidDiagnostics:
340 return "Parse error reading diagnostics";
341 case SDError::MalformedTopLevelBlock:
342 return "Malformed block at top-level of diagnostics";
343 case SDError::MalformedSubBlock:
344 return "Malformed sub-block in a diagnostic";
345 case SDError::MalformedBlockInfoBlock:
346 return "Malformed BlockInfo block";
347 case SDError::MalformedMetadataBlock:
348 return "Malformed Metadata block";
349 case SDError::MalformedDiagnosticBlock:
350 return "Malformed Diagnostic block";
351 case SDError::MalformedDiagnosticRecord:
352 return "Malformed Diagnostic record";
353 case SDError::MissingVersion:
354 return "No version provided in diagnostics";
355 case SDError::VersionMismatch:
356 return "Unsupported diagnostics version";
357 case SDError::UnsupportedConstruct:
358 return "Bitcode constructs that are not supported in diagnostics appear";
359 case SDError::HandlerFailed:
360 return "Generic error occurred while handling a record";
362 llvm_unreachable(
"Unknown error type!");
Defines the clang::FileManager interface and associated types.
Defines the clang::FileSystemOptions interface.
llvm::MachO::Record Record
static llvm::ManagedStatic< SDErrorCategoryType > ErrorCategory
Implements support for file system lookup, file system caching, and directory search management.
Keeps track of options that affect how file operations are performed.
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name)
Visit a category. This associates the category ID to a Name.
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name)
Visit a flag. This associates the flag's ID to a Name.
virtual std::error_code visitStartOfDiagnostic()
Visit the start of a diagnostic block.
virtual std::error_code visitDiagnosticRecord(unsigned Severity, const Location &Location, unsigned Category, unsigned Flag, StringRef Message)
Visit a diagnostic.
virtual std::error_code visitSourceRangeRecord(const Location &Start, const Location &End)
Visit a source range.
virtual std::error_code visitVersionRecord(unsigned Version)
Visit the version of the set of diagnostics.
virtual std::error_code visitFixitRecord(const Location &Start, const Location &End, StringRef Text)
Visit a fixit hint.
virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size, unsigned Timestamp, StringRef Name)
Visit a filename. This associates the file's ID to a Name.
virtual std::error_code visitEndOfDiagnostic()
Visit the end of a diagnostic block.
const std::error_category & SDErrorCategory()
@ BLOCK_DIAG
The this block acts as a container for all the information for a specific diagnostic.
@ BLOCK_META
A top-level block which represents any meta data associated with the diagostics, including versioning...
@ MalformedDiagnosticBlock
@ MalformedBlockInfoBlock
@ MalformedDiagnosticRecord
The JSON file list parser is used to communicate input to InstallAPI.
A location that is represented in the serialized diagnostics.