13#include "llvm/ADT/SmallVector.h"
14#include "llvm/Bitstream/BitstreamReader.h"
15#include "llvm/Support/Compiler.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/ErrorOr.h"
18#include "llvm/Support/ManagedStatic.h"
21#include <system_error>
24using namespace serialized_diags;
26std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef
File) {
31 auto Buffer = FileMgr.getBufferForFile(
File);
35 llvm::BitstreamCursor Stream(**Buffer);
36 std::optional<llvm::BitstreamBlockInfo> BlockInfo;
38 if (Stream.AtEndOfStream())
42 for (
unsigned char C : {
'D',
'I',
'A',
'G'}) {
48 consumeError(Res.takeError());
54 while (!Stream.AtEndOfStream()) {
56 if (Res.get() != llvm::bitc::ENTER_SUBBLOCK)
60 consumeError(Res.takeError());
66 if (!MaybeSubBlockID) {
68 consumeError(MaybeSubBlockID.takeError());
72 switch (MaybeSubBlockID.get()) {
73 case llvm::bitc::BLOCKINFO_BLOCK_ID: {
75 Stream.ReadBlockInfoBlock();
76 if (!MaybeBlockInfo) {
78 consumeError(MaybeBlockInfo.takeError());
81 BlockInfo = std::move(MaybeBlockInfo.get());
85 Stream.setBlockInfo(&*BlockInfo);
88 if ((EC = readMetaBlock(Stream)))
92 if ((EC = readDiagnosticBlock(Stream)))
96 if (llvm::Error Err = Stream.SkipBlock()) {
98 consumeError(std::move(Err));
113llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
114SerializedDiagnosticReader::skipUntilRecordOrBlock(
115 llvm::BitstreamCursor &Stream,
unsigned &BlockOrRecordID) {
118 while (!Stream.AtEndOfStream()) {
123 return llvm::errorToErrorCode(Res.takeError());
125 if (Code >=
static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
127 BlockOrRecordID = Code;
128 return Cursor::Record;
130 switch (
static_cast<llvm::bitc::FixedAbbrevIDs
>(Code)) {
131 case llvm::bitc::ENTER_SUBBLOCK:
133 BlockOrRecordID = Res.get();
135 return llvm::errorToErrorCode(Res.takeError());
136 return Cursor::BlockBegin;
138 case llvm::bitc::END_BLOCK:
139 if (Stream.ReadBlockEnd())
141 return Cursor::BlockEnd;
143 case llvm::bitc::DEFINE_ABBREV:
144 if (llvm::Error Err = Stream.ReadAbbrevRecord())
145 return llvm::errorToErrorCode(std::move(Err));
148 case llvm::bitc::UNABBREV_RECORD:
151 case llvm::bitc::FIRST_APPLICATION_ABBREV:
152 llvm_unreachable(
"Unexpected abbrev id.");
160SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
161 if (llvm::Error Err =
164 consumeError(std::move(Err));
168 bool VersionChecked =
false;
171 unsigned BlockOrCode = 0;
172 llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
179 case Cursor::BlockBegin:
180 if (llvm::Error Err = Stream.SkipBlock()) {
182 consumeError(std::move(Err));
186 case Cursor::BlockEnd:
195 return errorToErrorCode(MaybeRecordID.takeError());
196 unsigned RecordID = MaybeRecordID.get();
203 VersionChecked =
true;
209SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
210 if (llvm::Error Err =
213 consumeError(std::move(Err));
223 unsigned BlockOrCode = 0;
224 llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
229 case Cursor::BlockBegin:
232 if ((EC = readDiagnosticBlock(Stream)))
234 }
else if (llvm::Error Err = Stream.SkipBlock()) {
236 consumeError(std::move(Err));
240 case Cursor::BlockEnd:
252 Stream.readRecord(BlockOrCode,
Record, &Blob);
254 return errorToErrorCode(MaybeRecID.takeError());
255 unsigned RecID = MaybeRecID.get();
325class SDErrorCategoryType final :
public std::error_category {
326 const char *
name() const noexcept
override {
327 return "clang.serialized_diags";
330 std::string message(
int IE)
const override {
333 case SDError::CouldNotLoad:
334 return "Failed to open diagnostics file";
335 case SDError::InvalidSignature:
336 return "Invalid diagnostics signature";
337 case SDError::InvalidDiagnostics:
338 return "Parse error reading diagnostics";
339 case SDError::MalformedTopLevelBlock:
340 return "Malformed block at top-level of diagnostics";
341 case SDError::MalformedSubBlock:
342 return "Malformed sub-block in a diagnostic";
343 case SDError::MalformedBlockInfoBlock:
344 return "Malformed BlockInfo block";
345 case SDError::MalformedMetadataBlock:
346 return "Malformed Metadata block";
347 case SDError::MalformedDiagnosticBlock:
348 return "Malformed Diagnostic block";
349 case SDError::MalformedDiagnosticRecord:
350 return "Malformed Diagnostic record";
351 case SDError::MissingVersion:
352 return "No version provided in diagnostics";
353 case SDError::VersionMismatch:
354 return "Unsupported diagnostics version";
355 case SDError::UnsupportedConstruct:
356 return "Bitcode constructs that are not supported in diagnostics appear";
357 case SDError::HandlerFailed:
358 return "Generic error occurred while handling a record";
360 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.