Revert "Frontend: Extract SerializedDiagnosticReader out of CXLoadedDiagnostic (NFC)"
The bots can't seem to find an include file. Reverting for now and I'll look into it in a bit. This reverts commits r219647 and r219648. llvm-svn: 219649
This commit is contained in:
parent
0b4ab665f9
commit
d776d67268
|
@ -11,7 +11,6 @@
|
|||
#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Frontend/SerializedDiagnostics.h"
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -25,6 +24,41 @@ class DiagnosticOptions;
|
|||
|
||||
namespace serialized_diags {
|
||||
|
||||
enum BlockIDs {
|
||||
/// \brief A top-level block which represents any meta data associated
|
||||
/// with the diagostics, including versioning of the format.
|
||||
BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID,
|
||||
|
||||
/// \brief The this block acts as a container for all the information
|
||||
/// for a specific diagnostic.
|
||||
BLOCK_DIAG
|
||||
};
|
||||
|
||||
enum RecordIDs {
|
||||
RECORD_VERSION = 1,
|
||||
RECORD_DIAG,
|
||||
RECORD_SOURCE_RANGE,
|
||||
RECORD_DIAG_FLAG,
|
||||
RECORD_CATEGORY,
|
||||
RECORD_FILENAME,
|
||||
RECORD_FIXIT,
|
||||
RECORD_FIRST = RECORD_VERSION,
|
||||
RECORD_LAST = RECORD_FIXIT
|
||||
};
|
||||
|
||||
/// A stable version of DiagnosticIDs::Level.
|
||||
///
|
||||
/// Do not change the order of values in this enum, and please increment the
|
||||
/// serialized diagnostics version number when you add to it.
|
||||
enum Level {
|
||||
Ignored = 0,
|
||||
Note,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal,
|
||||
Remark
|
||||
};
|
||||
|
||||
/// \brief Returns a DiagnosticConsumer that serializes diagnostics to
|
||||
/// a bitcode file.
|
||||
///
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
|
||||
#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Bitcode/BitstreamReader.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialized_diags {
|
||||
|
||||
enum class SDError {
|
||||
CouldNotLoad = 1,
|
||||
InvalidSignature,
|
||||
InvalidDiagnostics,
|
||||
MalformedTopLevelBlock,
|
||||
MalformedSubBlock,
|
||||
MalformedBlockInfoBlock,
|
||||
MalformedMetadataBlock,
|
||||
MalformedDiagnosticBlock,
|
||||
MalformedDiagnosticRecord,
|
||||
MissingVersion,
|
||||
VersionMismatch,
|
||||
UnsupportedConstruct,
|
||||
/// A generic error for subclass handlers that don't want or need to define
|
||||
/// their own error_category.
|
||||
HandlerFailed
|
||||
};
|
||||
|
||||
const std::error_category &SDErrorCategory();
|
||||
|
||||
inline std::error_code make_error_code(SDError E) {
|
||||
return std::error_code(static_cast<int>(E), SDErrorCategory());
|
||||
}
|
||||
|
||||
/// \brief A location that is represented in the serialized diagnostics.
|
||||
struct Location {
|
||||
unsigned FileID;
|
||||
unsigned Line;
|
||||
unsigned Col;
|
||||
unsigned Offset;
|
||||
Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset)
|
||||
: FileID(FileID), Line(Line), Col(Col), Offset(Offset) {}
|
||||
};
|
||||
|
||||
/// \brief A base class that handles reading serialized diagnostics from a file.
|
||||
///
|
||||
/// Subclasses should override the visit* methods with their logic for handling
|
||||
/// the various constructs that are found in serialized diagnostics.
|
||||
class SerializedDiagnosticReader {
|
||||
public:
|
||||
SerializedDiagnosticReader() {}
|
||||
virtual ~SerializedDiagnosticReader() {}
|
||||
|
||||
/// \brief Read the diagnostics in \c File
|
||||
std::error_code readDiagnostics(StringRef File);
|
||||
|
||||
private:
|
||||
enum class Cursor;
|
||||
|
||||
/// \brief Read to the next record or block to process.
|
||||
llvm::ErrorOr<Cursor> skipUntilRecordOrBlock(llvm::BitstreamCursor &Stream,
|
||||
unsigned &BlockOrRecordId);
|
||||
|
||||
/// \brief Read a metadata block from \c Stream.
|
||||
std::error_code readMetaBlock(llvm::BitstreamCursor &Stream);
|
||||
|
||||
/// \brief Read a diagnostic block from \c Stream.
|
||||
std::error_code readDiagnosticBlock(llvm::BitstreamCursor &Stream);
|
||||
|
||||
protected:
|
||||
/// \brief Visit the start of a diagnostic block.
|
||||
virtual std::error_code visitStartOfDiagnostic() {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit the end of a diagnostic block.
|
||||
virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); };
|
||||
/// \brief Visit a category. This associates the category \c ID to a \c Name.
|
||||
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit a flag. This associates the flag's \c ID to a \c Name.
|
||||
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit a diagnostic.
|
||||
virtual std::error_code
|
||||
visitDiagnosticRecord(unsigned Severity, const Location &Location,
|
||||
unsigned Category, unsigned Flag, StringRef Message) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit a filename. This associates the file's \c ID to a \c Name.
|
||||
virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
|
||||
unsigned Timestamp,
|
||||
StringRef Name) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit a fixit hint.
|
||||
virtual std::error_code
|
||||
visitFixitRecord(const Location &Start, const Location &End, StringRef Text) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit a source range.
|
||||
virtual std::error_code visitSourceRangeRecord(const Location &Start,
|
||||
const Location &End) {
|
||||
return std::error_code();
|
||||
};
|
||||
/// \brief Visit the version of the set of diagnostics.
|
||||
virtual std::error_code visitVersionRecord(unsigned Version) {
|
||||
return std::error_code();
|
||||
};
|
||||
};
|
||||
|
||||
} // end serialized_diags namespace
|
||||
} // end clang namespace
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,59 +0,0 @@
|
|||
//===--- SerializedDiagnostics.h - Common data for serialized diagnostics -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_
|
||||
#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_
|
||||
|
||||
#include "llvm/BitCode/BitCodes.h"
|
||||
|
||||
namespace clang {
|
||||
namespace serialized_diags {
|
||||
|
||||
enum BlockIDs {
|
||||
/// \brief A top-level block which represents any meta data associated
|
||||
/// with the diagostics, including versioning of the format.
|
||||
BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID,
|
||||
|
||||
/// \brief The this block acts as a container for all the information
|
||||
/// for a specific diagnostic.
|
||||
BLOCK_DIAG
|
||||
};
|
||||
|
||||
enum RecordIDs {
|
||||
RECORD_VERSION = 1,
|
||||
RECORD_DIAG,
|
||||
RECORD_SOURCE_RANGE,
|
||||
RECORD_DIAG_FLAG,
|
||||
RECORD_CATEGORY,
|
||||
RECORD_FILENAME,
|
||||
RECORD_FIXIT,
|
||||
RECORD_FIRST = RECORD_VERSION,
|
||||
RECORD_LAST = RECORD_FIXIT
|
||||
};
|
||||
|
||||
/// \brief A stable version of DiagnosticIDs::Level.
|
||||
///
|
||||
/// Do not change the order of values in this enum, and please increment the
|
||||
/// serialized diagnostics version number when you add to it.
|
||||
enum Level {
|
||||
Ignored = 0,
|
||||
Note,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal,
|
||||
Remark
|
||||
};
|
||||
|
||||
/// \brief The serialized diagnostics version number.
|
||||
enum { VersionNumber = 2 };
|
||||
|
||||
} // end serialized_diags namespace
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -1,7 +1,6 @@
|
|||
add_subdirectory(Rewrite)
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
BitReader
|
||||
Option
|
||||
Support
|
||||
)
|
||||
|
@ -32,7 +31,6 @@ add_clang_library(clangFrontend
|
|||
MultiplexConsumer.cpp
|
||||
PrintPreprocessedOutput.cpp
|
||||
SerializedDiagnosticPrinter.cpp
|
||||
SerializedDiagnosticReader.cpp
|
||||
TextDiagnostic.cpp
|
||||
TextDiagnosticBuffer.cpp
|
||||
TextDiagnosticPrinter.cpp
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
|
||||
#include "clang/Frontend/SerializedDiagnostics.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
|
@ -173,6 +172,9 @@ private:
|
|||
void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
|
||||
const SourceManager &SM);
|
||||
|
||||
/// \brief The version of the diagnostics file.
|
||||
enum { Version = 2 };
|
||||
|
||||
/// \brief Language options, which can differ from one clone of this client
|
||||
/// to another.
|
||||
const LangOptions *LangOpts;
|
||||
|
@ -464,7 +466,7 @@ void SDiagsWriter::EmitMetaBlock() {
|
|||
Stream.EnterSubblock(BLOCK_META, 3);
|
||||
Record.clear();
|
||||
Record.push_back(RECORD_VERSION);
|
||||
Record.push_back(VersionNumber);
|
||||
Record.push_back(Version);
|
||||
Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
|
|
@ -1,296 +0,0 @@
|
|||
//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Frontend/SerializedDiagnosticReader.h"
|
||||
#include "clang/Frontend/SerializedDiagnostics.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::serialized_diags;
|
||||
|
||||
std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
|
||||
// Open the diagnostics file.
|
||||
FileSystemOptions FO;
|
||||
FileManager FileMgr(FO);
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer = FileMgr.getBufferForFile(File);
|
||||
if (!Buffer)
|
||||
return SDError::CouldNotLoad;
|
||||
|
||||
llvm::BitstreamReader StreamFile;
|
||||
StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
|
||||
(const unsigned char *)Buffer->getBufferEnd());
|
||||
|
||||
llvm::BitstreamCursor Stream;
|
||||
Stream.init(StreamFile);
|
||||
|
||||
// Sniff for the signature.
|
||||
if (Stream.Read(8) != 'D' ||
|
||||
Stream.Read(8) != 'I' ||
|
||||
Stream.Read(8) != 'A' ||
|
||||
Stream.Read(8) != 'G')
|
||||
return SDError::InvalidSignature;
|
||||
|
||||
// Read the top level blocks.
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
|
||||
return SDError::InvalidDiagnostics;
|
||||
|
||||
std::error_code EC;
|
||||
switch (Stream.ReadSubBlockID()) {
|
||||
case llvm::bitc::BLOCKINFO_BLOCK_ID:
|
||||
if (Stream.ReadBlockInfoBlock())
|
||||
return SDError::MalformedBlockInfoBlock;
|
||||
continue;
|
||||
case BLOCK_META:
|
||||
if ((EC = readMetaBlock(Stream)))
|
||||
return EC;
|
||||
continue;
|
||||
case BLOCK_DIAG:
|
||||
if ((EC = readDiagnosticBlock(Stream)))
|
||||
return EC;
|
||||
continue;
|
||||
default:
|
||||
if (!Stream.SkipBlock())
|
||||
return SDError::MalformedTopLevelBlock;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
enum class SerializedDiagnosticReader::Cursor {
|
||||
Record = 1,
|
||||
BlockEnd,
|
||||
BlockBegin
|
||||
};
|
||||
|
||||
llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
|
||||
SerializedDiagnosticReader::skipUntilRecordOrBlock(
|
||||
llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
|
||||
BlockOrRecordID = 0;
|
||||
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
|
||||
switch ((llvm::bitc::FixedAbbrevIDs)Code) {
|
||||
case llvm::bitc::ENTER_SUBBLOCK:
|
||||
BlockOrRecordID = Stream.ReadSubBlockID();
|
||||
return Cursor::BlockBegin;
|
||||
|
||||
case llvm::bitc::END_BLOCK:
|
||||
if (Stream.ReadBlockEnd())
|
||||
return SDError::InvalidDiagnostics;
|
||||
return Cursor::BlockEnd;
|
||||
|
||||
case llvm::bitc::DEFINE_ABBREV:
|
||||
Stream.ReadAbbrevRecord();
|
||||
continue;
|
||||
|
||||
case llvm::bitc::UNABBREV_RECORD:
|
||||
return SDError::UnsupportedConstruct;
|
||||
|
||||
default:
|
||||
// We found a record.
|
||||
BlockOrRecordID = Code;
|
||||
return Cursor::Record;
|
||||
}
|
||||
}
|
||||
|
||||
return SDError::InvalidDiagnostics;
|
||||
}
|
||||
|
||||
std::error_code
|
||||
SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
|
||||
return SDError::MalformedMetadataBlock;
|
||||
|
||||
bool VersionChecked = false;
|
||||
|
||||
while (true) {
|
||||
unsigned BlockOrCode = 0;
|
||||
llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
|
||||
if (!Res)
|
||||
Res.getError();
|
||||
|
||||
switch (Res.get()) {
|
||||
case Cursor::Record:
|
||||
break;
|
||||
case Cursor::BlockBegin:
|
||||
if (Stream.SkipBlock())
|
||||
return SDError::MalformedMetadataBlock;
|
||||
case Cursor::BlockEnd:
|
||||
if (!VersionChecked)
|
||||
return SDError::MissingVersion;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
SmallVector<uint64_t, 1> Record;
|
||||
unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
|
||||
|
||||
if (RecordID == RECORD_VERSION) {
|
||||
if (Record.size() < 1)
|
||||
return SDError::MissingVersion;
|
||||
if (Record[0] > VersionNumber)
|
||||
return SDError::VersionMismatch;
|
||||
VersionChecked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::error_code
|
||||
SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
|
||||
return SDError::MalformedDiagnosticBlock;
|
||||
|
||||
std::error_code EC;
|
||||
if ((EC = visitStartOfDiagnostic()))
|
||||
return EC;
|
||||
|
||||
SmallVector<uint64_t, 16> Record;
|
||||
while (true) {
|
||||
unsigned BlockOrCode = 0;
|
||||
llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
|
||||
if (!Res)
|
||||
Res.getError();
|
||||
|
||||
switch (Res.get()) {
|
||||
case Cursor::BlockBegin:
|
||||
// The only blocks we care about are subdiagnostics.
|
||||
if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
|
||||
if ((EC = readDiagnosticBlock(Stream)))
|
||||
return EC;
|
||||
} else if (!Stream.SkipBlock())
|
||||
return SDError::MalformedSubBlock;
|
||||
continue;
|
||||
case Cursor::BlockEnd:
|
||||
if ((EC = visitEndOfDiagnostic()))
|
||||
return EC;
|
||||
return std::error_code();
|
||||
case Cursor::Record:
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the record.
|
||||
Record.clear();
|
||||
StringRef Blob;
|
||||
unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
|
||||
|
||||
if (RecID < serialized_diags::RECORD_FIRST ||
|
||||
RecID > serialized_diags::RECORD_LAST)
|
||||
continue;
|
||||
|
||||
switch ((RecordIDs)RecID) {
|
||||
case RECORD_CATEGORY:
|
||||
// A category has ID and name size.
|
||||
if (Record.size() != 2)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitCategoryRecord(Record[0], Blob)))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_DIAG:
|
||||
// A diagnostic has severity, location (4), category, flag, and message
|
||||
// size.
|
||||
if (Record.size() != 8)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitDiagnosticRecord(
|
||||
Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
|
||||
Record[5], Record[6], Blob)))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_DIAG_FLAG:
|
||||
// A diagnostic flag has ID and name size.
|
||||
if (Record.size() != 2)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitDiagFlagRecord(Record[0], Blob)))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_FILENAME:
|
||||
// A filename has ID, size, timestamp, and name size. The size and
|
||||
// timestamp are legacy fields that are always zero these days.
|
||||
if (Record.size() != 4)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_FIXIT:
|
||||
// A fixit has two locations (4 each) and message size.
|
||||
if (Record.size() != 9)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitFixitRecord(
|
||||
Location(Record[0], Record[1], Record[2], Record[3]),
|
||||
Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_SOURCE_RANGE:
|
||||
// A source range is two locations (4 each).
|
||||
if (Record.size() != 8)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitSourceRangeRecord(
|
||||
Location(Record[0], Record[1], Record[2], Record[3]),
|
||||
Location(Record[4], Record[5], Record[6], Record[7]))))
|
||||
return EC;
|
||||
continue;
|
||||
case RECORD_VERSION:
|
||||
// A version is just a number.
|
||||
if (Record.size() != 1)
|
||||
return SDError::MalformedDiagnosticRecord;
|
||||
if ((EC = visitVersionRecord(Record[0])))
|
||||
return EC;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SDErrorCategoryType final : public std::error_category {
|
||||
const char *name() const LLVM_NOEXCEPT override {
|
||||
return "clang.serialized_diags";
|
||||
}
|
||||
std::string message(int IE) const override {
|
||||
SDError E = static_cast<SDError>(IE);
|
||||
switch (E) {
|
||||
case SDError::CouldNotLoad:
|
||||
return "Failed to open diagnostics file";
|
||||
case SDError::InvalidSignature:
|
||||
return "Invalid diagnostics signature";
|
||||
case SDError::InvalidDiagnostics:
|
||||
return "Parse error reading diagnostics";
|
||||
case SDError::MalformedTopLevelBlock:
|
||||
return "Malformed block at top-level of diagnostics";
|
||||
case SDError::MalformedSubBlock:
|
||||
return "Malformed sub-block in a diagnostic";
|
||||
case SDError::MalformedBlockInfoBlock:
|
||||
return "Malformed BlockInfo block";
|
||||
case SDError::MalformedMetadataBlock:
|
||||
return "Malformed Metadata block";
|
||||
case SDError::MalformedDiagnosticBlock:
|
||||
return "Malformed Diagnostic block";
|
||||
case SDError::MalformedDiagnosticRecord:
|
||||
return "Malformed Diagnostic record";
|
||||
case SDError::MissingVersion:
|
||||
return "No version provided in diagnostics";
|
||||
case SDError::VersionMismatch:
|
||||
return "Unsupported diagnostics version";
|
||||
case SDError::UnsupportedConstruct:
|
||||
return "Bitcode constructs that are not supported in diagnostics appear";
|
||||
case SDError::HandlerFailed:
|
||||
return "Generic error occurred while handling a record";
|
||||
}
|
||||
llvm_unreachable("Unknown error type!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
|
||||
const std::error_category &clang::serialized_diags::SDErrorCategory() {
|
||||
return *ErrorCategory;
|
||||
}
|
|
@ -16,8 +16,7 @@
|
|||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Frontend/SerializedDiagnostics.h"
|
||||
#include "clang/Frontend/SerializedDiagnosticReader.h"
|
||||
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
@ -184,59 +183,67 @@ void CXLoadedDiagnostic::decodeLocation(CXSourceLocation location,
|
|||
// Deserialize diagnostics.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
enum { MaxSupportedVersion = 2 };
|
||||
typedef SmallVector<uint64_t, 64> RecordData;
|
||||
enum LoadResult { Failure = 1, Success = 0 };
|
||||
enum StreamResult { Read_EndOfStream,
|
||||
Read_BlockBegin,
|
||||
Read_Failure,
|
||||
Read_Record,
|
||||
Read_BlockEnd };
|
||||
|
||||
namespace {
|
||||
class DiagLoader : serialized_diags::SerializedDiagnosticReader {
|
||||
class DiagLoader {
|
||||
enum CXLoadDiag_Error *error;
|
||||
CXString *errorString;
|
||||
std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags;
|
||||
SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags;
|
||||
|
||||
std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
|
||||
void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
|
||||
if (error)
|
||||
*error = code;
|
||||
if (errorString)
|
||||
*errorString = cxstring::createDup(err);
|
||||
return serialized_diags::SDError::HandlerFailed;
|
||||
}
|
||||
|
||||
std::error_code reportInvalidFile(llvm::StringRef err) {
|
||||
void reportInvalidFile(llvm::StringRef err) {
|
||||
return reportBad(CXLoadDiag_InvalidFile, err);
|
||||
}
|
||||
|
||||
std::error_code readRange(const serialized_diags::Location &SDStart,
|
||||
const serialized_diags::Location &SDEnd,
|
||||
LoadResult readMetaBlock(llvm::BitstreamCursor &Stream);
|
||||
|
||||
LoadResult readDiagnosticBlock(llvm::BitstreamCursor &Stream,
|
||||
CXDiagnosticSetImpl &Diags,
|
||||
CXLoadedDiagnosticSetImpl &TopDiags);
|
||||
|
||||
StreamResult readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
|
||||
llvm::StringRef errorContext,
|
||||
unsigned &BlockOrRecordID,
|
||||
bool atTopLevel = false);
|
||||
|
||||
|
||||
LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
Strings &strings, llvm::StringRef errorContext,
|
||||
RecordData &Record,
|
||||
StringRef Blob,
|
||||
bool allowEmptyString = false);
|
||||
|
||||
LoadResult readString(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
const char *&RetStr,
|
||||
llvm::StringRef errorContext,
|
||||
RecordData &Record,
|
||||
StringRef Blob,
|
||||
bool allowEmptyString = false);
|
||||
|
||||
LoadResult readRange(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
RecordData &Record, unsigned RecStartIdx,
|
||||
CXSourceRange &SR);
|
||||
|
||||
std::error_code readLocation(const serialized_diags::Location &SDLoc,
|
||||
CXLoadedDiagnostic::Location &LoadedLoc);
|
||||
|
||||
protected:
|
||||
std::error_code visitStartOfDiagnostic() override;
|
||||
std::error_code visitEndOfDiagnostic() override;
|
||||
|
||||
std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
|
||||
|
||||
std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
|
||||
|
||||
std::error_code visitDiagnosticRecord(
|
||||
unsigned Severity, const serialized_diags::Location &Location,
|
||||
unsigned Category, unsigned Flag, StringRef Message) override;
|
||||
|
||||
std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
|
||||
unsigned Timestamp,
|
||||
StringRef Name) override;
|
||||
|
||||
std::error_code visitFixitRecord(const serialized_diags::Location &Start,
|
||||
const serialized_diags::Location &End,
|
||||
StringRef CodeToInsert) override;
|
||||
|
||||
std::error_code
|
||||
visitSourceRangeRecord(const serialized_diags::Location &Start,
|
||||
const serialized_diags::Location &End) override;
|
||||
LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
RecordData &Record, unsigned &offset,
|
||||
CXLoadedDiagnostic::Location &Loc);
|
||||
|
||||
public:
|
||||
DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
|
||||
: SerializedDiagnosticReader(), error(e), errorString(es) {
|
||||
: error(e), errorString(es) {
|
||||
if (error)
|
||||
*error = CXLoadDiag_None;
|
||||
if (errorString)
|
||||
|
@ -248,143 +255,403 @@ public:
|
|||
}
|
||||
|
||||
CXDiagnosticSet DiagLoader::load(const char *file) {
|
||||
TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>();
|
||||
// Open the diagnostics file.
|
||||
std::string ErrStr;
|
||||
FileSystemOptions FO;
|
||||
FileManager FileMgr(FO);
|
||||
|
||||
std::error_code EC = readDiagnostics(file);
|
||||
if (EC) {
|
||||
switch (EC.value()) {
|
||||
case static_cast<int>(serialized_diags::SDError::HandlerFailed):
|
||||
// We've already reported the problem.
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer = FileMgr.getBufferForFile(file);
|
||||
if (!Buffer) {
|
||||
reportBad(CXLoadDiag_CannotLoad, ErrStr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
llvm::BitstreamReader StreamFile;
|
||||
StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
|
||||
(const unsigned char *)Buffer->getBufferEnd());
|
||||
|
||||
llvm::BitstreamCursor Stream;
|
||||
Stream.init(StreamFile);
|
||||
|
||||
// Sniff for the signature.
|
||||
if (Stream.Read(8) != 'D' ||
|
||||
Stream.Read(8) != 'I' ||
|
||||
Stream.Read(8) != 'A' ||
|
||||
Stream.Read(8) != 'G') {
|
||||
reportBad(CXLoadDiag_InvalidFile,
|
||||
"Bad header in diagnostics file");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<CXLoadedDiagnosticSetImpl> Diags(
|
||||
new CXLoadedDiagnosticSetImpl());
|
||||
|
||||
while (true) {
|
||||
unsigned BlockID = 0;
|
||||
StreamResult Res = readToNextRecordOrBlock(Stream, "Top-level",
|
||||
BlockID, true);
|
||||
switch (Res) {
|
||||
case Read_EndOfStream:
|
||||
return (CXDiagnosticSet)Diags.release();
|
||||
case Read_Failure:
|
||||
return nullptr;
|
||||
case Read_Record:
|
||||
llvm_unreachable("Top-level does not have records");
|
||||
case Read_BlockEnd:
|
||||
continue;
|
||||
case Read_BlockBegin:
|
||||
break;
|
||||
case static_cast<int>(serialized_diags::SDError::CouldNotLoad):
|
||||
reportBad(CXLoadDiag_CannotLoad, EC.message());
|
||||
}
|
||||
|
||||
switch (BlockID) {
|
||||
case serialized_diags::BLOCK_META:
|
||||
if (readMetaBlock(Stream))
|
||||
return nullptr;
|
||||
break;
|
||||
case serialized_diags::BLOCK_DIAG:
|
||||
if (readDiagnosticBlock(Stream, *Diags.get(), *Diags.get()))
|
||||
return nullptr;
|
||||
break;
|
||||
default:
|
||||
reportInvalidFile(EC.message());
|
||||
if (!Stream.SkipBlock()) {
|
||||
reportInvalidFile("Malformed block at top-level of diagnostics file");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (CXDiagnosticSet)TopDiags.release();
|
||||
StreamResult DiagLoader::readToNextRecordOrBlock(llvm::BitstreamCursor &Stream,
|
||||
llvm::StringRef errorContext,
|
||||
unsigned &blockOrRecordID,
|
||||
bool atTopLevel) {
|
||||
|
||||
blockOrRecordID = 0;
|
||||
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
unsigned Code = Stream.ReadCode();
|
||||
|
||||
// Handle the top-level specially.
|
||||
if (atTopLevel) {
|
||||
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
|
||||
unsigned BlockID = Stream.ReadSubBlockID();
|
||||
if (BlockID == llvm::bitc::BLOCKINFO_BLOCK_ID) {
|
||||
if (Stream.ReadBlockInfoBlock()) {
|
||||
reportInvalidFile("Malformed BlockInfoBlock in diagnostics file");
|
||||
return Read_Failure;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
blockOrRecordID = BlockID;
|
||||
return Read_BlockBegin;
|
||||
}
|
||||
reportInvalidFile("Only blocks can appear at the top of a "
|
||||
"diagnostic file");
|
||||
return Read_Failure;
|
||||
}
|
||||
|
||||
std::error_code
|
||||
DiagLoader::readLocation(const serialized_diags::Location &SDLoc,
|
||||
CXLoadedDiagnostic::Location &LoadedLoc) {
|
||||
unsigned FileID = SDLoc.FileID;
|
||||
if (FileID == 0)
|
||||
LoadedLoc.file = nullptr;
|
||||
else {
|
||||
LoadedLoc.file = const_cast<FileEntry *>(TopDiags->Files[FileID]);
|
||||
if (!LoadedLoc.file)
|
||||
return reportInvalidFile("Corrupted file entry in source location");
|
||||
switch ((llvm::bitc::FixedAbbrevIDs)Code) {
|
||||
case llvm::bitc::ENTER_SUBBLOCK:
|
||||
blockOrRecordID = Stream.ReadSubBlockID();
|
||||
return Read_BlockBegin;
|
||||
|
||||
case llvm::bitc::END_BLOCK:
|
||||
if (Stream.ReadBlockEnd()) {
|
||||
reportInvalidFile("Cannot read end of block");
|
||||
return Read_Failure;
|
||||
}
|
||||
return Read_BlockEnd;
|
||||
|
||||
case llvm::bitc::DEFINE_ABBREV:
|
||||
Stream.ReadAbbrevRecord();
|
||||
continue;
|
||||
|
||||
case llvm::bitc::UNABBREV_RECORD:
|
||||
reportInvalidFile("Diagnostics file should have no unabbreviated "
|
||||
"records");
|
||||
return Read_Failure;
|
||||
|
||||
default:
|
||||
// We found a record.
|
||||
blockOrRecordID = Code;
|
||||
return Read_Record;
|
||||
}
|
||||
LoadedLoc.line = SDLoc.Line;
|
||||
LoadedLoc.column = SDLoc.Col;
|
||||
LoadedLoc.offset = SDLoc.Offset;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
std::error_code
|
||||
DiagLoader::readRange(const serialized_diags::Location &SDStart,
|
||||
const serialized_diags::Location &SDEnd,
|
||||
if (atTopLevel)
|
||||
return Read_EndOfStream;
|
||||
|
||||
reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
|
||||
errorContext.str());
|
||||
return Read_Failure;
|
||||
}
|
||||
|
||||
LoadResult DiagLoader::readMetaBlock(llvm::BitstreamCursor &Stream) {
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
|
||||
reportInvalidFile("Malformed metadata block");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
bool versionChecked = false;
|
||||
|
||||
while (true) {
|
||||
unsigned blockOrCode = 0;
|
||||
StreamResult Res = readToNextRecordOrBlock(Stream, "Metadata Block",
|
||||
blockOrCode);
|
||||
|
||||
switch(Res) {
|
||||
case Read_EndOfStream:
|
||||
llvm_unreachable("EndOfStream handled by readToNextRecordOrBlock");
|
||||
case Read_Failure:
|
||||
return Failure;
|
||||
case Read_Record:
|
||||
break;
|
||||
case Read_BlockBegin:
|
||||
if (Stream.SkipBlock()) {
|
||||
reportInvalidFile("Malformed metadata block");
|
||||
return Failure;
|
||||
}
|
||||
case Read_BlockEnd:
|
||||
if (!versionChecked) {
|
||||
reportInvalidFile("Diagnostics file does not contain version"
|
||||
" information");
|
||||
return Failure;
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
|
||||
RecordData Record;
|
||||
unsigned recordID = Stream.readRecord(blockOrCode, Record);
|
||||
|
||||
if (recordID == serialized_diags::RECORD_VERSION) {
|
||||
if (Record.size() < 1) {
|
||||
reportInvalidFile("malformed VERSION identifier in diagnostics file");
|
||||
return Failure;
|
||||
}
|
||||
if (Record[0] > MaxSupportedVersion) {
|
||||
reportInvalidFile("diagnostics file is a newer version than the one "
|
||||
"supported");
|
||||
return Failure;
|
||||
}
|
||||
versionChecked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
const char *&RetStr,
|
||||
llvm::StringRef errorContext,
|
||||
RecordData &Record,
|
||||
StringRef Blob,
|
||||
bool allowEmptyString) {
|
||||
|
||||
// Basic buffer overflow check.
|
||||
if (Blob.size() > 65536) {
|
||||
reportInvalidFile(std::string("Out-of-bounds string in ") +
|
||||
std::string(errorContext));
|
||||
return Failure;
|
||||
}
|
||||
|
||||
if (allowEmptyString && Record.size() >= 1 && Blob.size() == 0) {
|
||||
RetStr = "";
|
||||
return Success;
|
||||
}
|
||||
|
||||
if (Record.size() < 1 || Blob.size() == 0) {
|
||||
reportInvalidFile(std::string("Corrupted ") + std::string(errorContext)
|
||||
+ std::string(" entry"));
|
||||
return Failure;
|
||||
}
|
||||
|
||||
RetStr = TopDiags.copyString(Blob);
|
||||
return Success;
|
||||
}
|
||||
|
||||
LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
Strings &strings,
|
||||
llvm::StringRef errorContext,
|
||||
RecordData &Record,
|
||||
StringRef Blob,
|
||||
bool allowEmptyString) {
|
||||
const char *RetStr;
|
||||
if (readString(TopDiags, RetStr, errorContext, Record, Blob,
|
||||
allowEmptyString))
|
||||
return Failure;
|
||||
strings[Record[0]] = RetStr;
|
||||
return Success;
|
||||
}
|
||||
|
||||
LoadResult DiagLoader::readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
RecordData &Record, unsigned &offset,
|
||||
CXLoadedDiagnostic::Location &Loc) {
|
||||
if (Record.size() < offset + 4) {
|
||||
reportInvalidFile("Corrupted source location");
|
||||
return Failure;
|
||||
}
|
||||
auto Fields = makeArrayRef(Record).slice(offset);
|
||||
offset += 4;
|
||||
|
||||
unsigned fileID = Fields[0];
|
||||
if (fileID == 0) {
|
||||
// Sentinel value.
|
||||
Loc.file = nullptr;
|
||||
Loc.line = 0;
|
||||
Loc.column = 0;
|
||||
Loc.offset = 0;
|
||||
return Success;
|
||||
}
|
||||
|
||||
const FileEntry *FE = TopDiags.Files[fileID];
|
||||
if (!FE) {
|
||||
reportInvalidFile("Corrupted file entry in source location");
|
||||
return Failure;
|
||||
}
|
||||
Loc.file = const_cast<FileEntry *>(FE);
|
||||
Loc.line = Fields[1];
|
||||
Loc.column = Fields[2];
|
||||
Loc.offset = Fields[3];
|
||||
return Success;
|
||||
}
|
||||
|
||||
LoadResult DiagLoader::readRange(CXLoadedDiagnosticSetImpl &TopDiags,
|
||||
RecordData &Record,
|
||||
unsigned int RecStartIdx,
|
||||
CXSourceRange &SR) {
|
||||
CXLoadedDiagnostic::Location *Start, *End;
|
||||
Start = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
|
||||
End = TopDiags->Alloc.Allocate<CXLoadedDiagnostic::Location>();
|
||||
Start = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
|
||||
End = TopDiags.Alloc.Allocate<CXLoadedDiagnostic::Location>();
|
||||
|
||||
std::error_code EC;
|
||||
if ((EC = readLocation(SDStart, *Start)))
|
||||
return EC;
|
||||
if ((EC = readLocation(SDEnd, *End)))
|
||||
return EC;
|
||||
if (readLocation(TopDiags, Record, RecStartIdx, *Start))
|
||||
return Failure;
|
||||
if (readLocation(TopDiags, Record, RecStartIdx, *End))
|
||||
return Failure;
|
||||
|
||||
CXSourceLocation startLoc = makeLocation(Start);
|
||||
CXSourceLocation endLoc = makeLocation(End);
|
||||
SR = clang_getRange(startLoc, endLoc);
|
||||
return std::error_code();
|
||||
return Success;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitStartOfDiagnostic() {
|
||||
CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>());
|
||||
return std::error_code();
|
||||
LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
|
||||
CXDiagnosticSetImpl &Diags,
|
||||
CXLoadedDiagnosticSetImpl &TopDiags){
|
||||
|
||||
if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
|
||||
reportInvalidFile("malformed diagnostic block");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitEndOfDiagnostic() {
|
||||
auto D = CurrentDiags.pop_back_val();
|
||||
if (CurrentDiags.empty())
|
||||
TopDiags->appendDiagnostic(std::move(D));
|
||||
else
|
||||
CurrentDiags.back()->getChildDiagnostics().appendDiagnostic(std::move(D));
|
||||
return std::error_code();
|
||||
std::unique_ptr<CXLoadedDiagnostic> D(new CXLoadedDiagnostic());
|
||||
RecordData Record;
|
||||
|
||||
while (true) {
|
||||
unsigned blockOrCode = 0;
|
||||
StreamResult Res = readToNextRecordOrBlock(Stream, "Diagnostic Block",
|
||||
blockOrCode);
|
||||
switch (Res) {
|
||||
case Read_EndOfStream:
|
||||
llvm_unreachable("EndOfStream handled in readToNextRecordOrBlock");
|
||||
case Read_Failure:
|
||||
return Failure;
|
||||
case Read_BlockBegin: {
|
||||
// The only blocks we care about are subdiagnostics.
|
||||
if (blockOrCode != serialized_diags::BLOCK_DIAG) {
|
||||
if (!Stream.SkipBlock()) {
|
||||
reportInvalidFile("Invalid subblock in Diagnostics block");
|
||||
return Failure;
|
||||
}
|
||||
} else if (readDiagnosticBlock(Stream, D->getChildDiagnostics(),
|
||||
TopDiags)) {
|
||||
return Failure;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) {
|
||||
// FIXME: Why do we care about long strings?
|
||||
if (Name.size() > 65536)
|
||||
return reportInvalidFile("Out-of-bounds string in category");
|
||||
TopDiags->Categories[ID] = TopDiags->copyString(Name);
|
||||
return std::error_code();
|
||||
continue;
|
||||
}
|
||||
case Read_BlockEnd:
|
||||
Diags.appendDiagnostic(std::move(D));
|
||||
return Success;
|
||||
case Read_Record:
|
||||
break;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitDiagFlagRecord(unsigned ID, StringRef Name) {
|
||||
// FIXME: Why do we care about long strings?
|
||||
if (Name.size() > 65536)
|
||||
return reportInvalidFile("Out-of-bounds string in warning flag");
|
||||
TopDiags->WarningFlags[ID] = TopDiags->copyString(Name);
|
||||
return std::error_code();
|
||||
// Read the record.
|
||||
Record.clear();
|
||||
StringRef Blob;
|
||||
unsigned recID = Stream.readRecord(blockOrCode, Record, &Blob);
|
||||
|
||||
if (recID < serialized_diags::RECORD_FIRST ||
|
||||
recID > serialized_diags::RECORD_LAST)
|
||||
continue;
|
||||
|
||||
switch ((serialized_diags::RecordIDs)recID) {
|
||||
case serialized_diags::RECORD_VERSION:
|
||||
continue;
|
||||
case serialized_diags::RECORD_CATEGORY:
|
||||
if (readString(TopDiags, TopDiags.Categories, "category", Record,
|
||||
Blob, /* allowEmptyString */ true))
|
||||
return Failure;
|
||||
continue;
|
||||
|
||||
case serialized_diags::RECORD_DIAG_FLAG:
|
||||
if (readString(TopDiags, TopDiags.WarningFlags, "warning flag", Record,
|
||||
Blob))
|
||||
return Failure;
|
||||
continue;
|
||||
|
||||
case serialized_diags::RECORD_FILENAME: {
|
||||
if (readString(TopDiags, TopDiags.FileNames, "filename", Record,
|
||||
Blob))
|
||||
return Failure;
|
||||
|
||||
if (Record.size() < 3) {
|
||||
reportInvalidFile("Invalid file entry");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitFilenameRecord(unsigned ID, unsigned Size,
|
||||
unsigned Timestamp,
|
||||
StringRef Name) {
|
||||
// FIXME: Why do we care about long strings?
|
||||
if (Name.size() > 65536)
|
||||
return reportInvalidFile("Out-of-bounds string in filename");
|
||||
TopDiags->FileNames[ID] = TopDiags->copyString(Name);
|
||||
TopDiags->Files[ID] =
|
||||
TopDiags->FakeFiles.getVirtualFile(Name, Size, Timestamp);
|
||||
return std::error_code();
|
||||
const FileEntry *FE =
|
||||
TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
|
||||
/* size */ Record[1],
|
||||
/* time */ Record[2]);
|
||||
|
||||
TopDiags.Files[Record[0]] = FE;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::error_code
|
||||
DiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start,
|
||||
const serialized_diags::Location &End) {
|
||||
case serialized_diags::RECORD_SOURCE_RANGE: {
|
||||
CXSourceRange SR;
|
||||
if (std::error_code EC = readRange(Start, End, SR))
|
||||
return EC;
|
||||
CurrentDiags.back()->Ranges.push_back(SR);
|
||||
return std::error_code();
|
||||
if (readRange(TopDiags, Record, 0, SR))
|
||||
return Failure;
|
||||
D->Ranges.push_back(SR);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::error_code
|
||||
DiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
|
||||
const serialized_diags::Location &End,
|
||||
StringRef CodeToInsert) {
|
||||
case serialized_diags::RECORD_FIXIT: {
|
||||
CXSourceRange SR;
|
||||
if (std::error_code EC = readRange(Start, End, SR))
|
||||
return EC;
|
||||
// FIXME: Why do we care about long strings?
|
||||
if (CodeToInsert.size() > 65536)
|
||||
return reportInvalidFile("Out-of-bounds string in FIXIT");
|
||||
CurrentDiags.back()->FixIts.push_back(
|
||||
std::make_pair(SR, TopDiags->copyString(CodeToInsert)));
|
||||
return std::error_code();
|
||||
if (readRange(TopDiags, Record, 0, SR))
|
||||
return Failure;
|
||||
const char *RetStr;
|
||||
if (readString(TopDiags, RetStr, "FIXIT", Record, Blob,
|
||||
/* allowEmptyString */ true))
|
||||
return Failure;
|
||||
D->FixIts.push_back(std::make_pair(SR, RetStr));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::error_code DiagLoader::visitDiagnosticRecord(
|
||||
unsigned Severity, const serialized_diags::Location &Location,
|
||||
unsigned Category, unsigned Flag, StringRef Message) {
|
||||
CXLoadedDiagnostic &D = *CurrentDiags.back();
|
||||
D.severity = Severity;
|
||||
if (std::error_code EC = readLocation(Location, D.DiagLoc))
|
||||
return EC;
|
||||
D.category = Category;
|
||||
D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : "";
|
||||
D.CategoryText = Category ? TopDiags->Categories[Category] : "";
|
||||
D.Spelling = TopDiags->copyString(Message);
|
||||
return std::error_code();
|
||||
case serialized_diags::RECORD_DIAG: {
|
||||
D->severity = Record[0];
|
||||
unsigned offset = 1;
|
||||
if (readLocation(TopDiags, Record, offset, D->DiagLoc))
|
||||
return Failure;
|
||||
D->category = Record[offset++];
|
||||
unsigned diagFlag = Record[offset++];
|
||||
D->DiagOption = diagFlag ? TopDiags.WarningFlags[diagFlag] : "";
|
||||
D->CategoryText = D->category ? TopDiags.Categories[D->category] : "";
|
||||
D->Spelling = TopDiags.copyString(Blob);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
Loading…
Reference in New Issue