summaryrefslogtreecommitdiffstats
path: root/tools/libclang/CXLoadedDiagnostic.cpp
diff options
context:
space:
mode:
authorJustin Bogner <mail@justinbogner.com>2014-10-14 06:30:31 +0000
committerJustin Bogner <mail@justinbogner.com>2014-10-14 06:30:31 +0000
commita905ad1646b0e5967bdb927a0a8c05b56fa7bc24 (patch)
treee021cb58a7aba0f0b2d3090b749f0fff8c4ffb40 /tools/libclang/CXLoadedDiagnostic.cpp
parentaaa733793e84107f8cd869ceae1662b6bf8a9d9f (diff)
Re-apply "Frontend: Extract SerializedDiagnosticReader out of CXLoadedDiagnostic (NFC)"
I'd mispelled "Bitcode/BitCodes.h" before, and tested on a case insensitive filesystem. This reverts commit r219649, effectively re-applying r219647 and r219648. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219664 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/libclang/CXLoadedDiagnostic.cpp')
-rw-r--r--tools/libclang/CXLoadedDiagnostic.cpp591
1 files changed, 162 insertions, 429 deletions
diff --git a/tools/libclang/CXLoadedDiagnostic.cpp b/tools/libclang/CXLoadedDiagnostic.cpp
index 0e0075fc38..c923b26be9 100644
--- a/tools/libclang/CXLoadedDiagnostic.cpp
+++ b/tools/libclang/CXLoadedDiagnostic.cpp
@@ -16,7 +16,8 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LLVM.h"
-#include "clang/Frontend/SerializedDiagnosticPrinter.h"
+#include "clang/Frontend/SerializedDiagnostics.h"
+#include "clang/Frontend/SerializedDiagnosticReader.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -183,475 +184,207 @@ 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 {
+class DiagLoader : serialized_diags::SerializedDiagnosticReader {
enum CXLoadDiag_Error *error;
CXString *errorString;
-
- void reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
+ std::unique_ptr<CXLoadedDiagnosticSetImpl> TopDiags;
+ SmallVector<std::unique_ptr<CXLoadedDiagnostic>, 8> CurrentDiags;
+
+ std::error_code reportBad(enum CXLoadDiag_Error code, llvm::StringRef err) {
if (error)
*error = code;
if (errorString)
*errorString = cxstring::createDup(err);
+ return serialized_diags::SDError::HandlerFailed;
}
- void reportInvalidFile(llvm::StringRef err) {
+ std::error_code reportInvalidFile(llvm::StringRef err) {
return reportBad(CXLoadDiag_InvalidFile, err);
}
- 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);
-
- LoadResult readLocation(CXLoadedDiagnosticSetImpl &TopDiags,
- RecordData &Record, unsigned &offset,
- CXLoadedDiagnostic::Location &Loc);
-
+ std::error_code readRange(const serialized_diags::Location &SDStart,
+ const serialized_diags::Location &SDEnd,
+ 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;
+
public:
DiagLoader(enum CXLoadDiag_Error *e, CXString *es)
- : error(e), errorString(es) {
- if (error)
- *error = CXLoadDiag_None;
- if (errorString)
- *errorString = cxstring::createEmpty();
- }
+ : SerializedDiagnosticReader(), error(e), errorString(es) {
+ if (error)
+ *error = CXLoadDiag_None;
+ if (errorString)
+ *errorString = cxstring::createEmpty();
+ }
CXDiagnosticSet load(const char *file);
};
}
CXDiagnosticSet DiagLoader::load(const char *file) {
- // Open the diagnostics file.
- std::string ErrStr;
- FileSystemOptions FO;
- FileManager FileMgr(FO);
-
- 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;
- }
-
- 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:
- if (!Stream.SkipBlock()) {
- reportInvalidFile("Malformed block at top-level of diagnostics file");
- return nullptr;
- }
- break;
+ TopDiags = llvm::make_unique<CXLoadedDiagnosticSetImpl>();
+
+ 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.
+ break;
+ case static_cast<int>(serialized_diags::SDError::CouldNotLoad):
+ reportBad(CXLoadDiag_CannotLoad, EC.message());
+ break;
+ default:
+ reportInvalidFile(EC.message());
+ break;
}
+ return 0;
}
-}
-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;
- }
-
- 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;
- }
- }
-
- if (atTopLevel)
- return Read_EndOfStream;
-
- reportInvalidFile(Twine("Premature end of diagnostics file within ").str() +
- errorContext.str());
- return Read_Failure;
+ return (CXDiagnosticSet)TopDiags.release();
}
-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;
- }
+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");
}
+ LoadedLoc.line = SDLoc.Line;
+ LoadedLoc.column = SDLoc.Col;
+ LoadedLoc.offset = SDLoc.Offset;
+ return std::error_code();
}
-LoadResult DiagLoader::readString(CXLoadedDiagnosticSetImpl &TopDiags,
- const char *&RetStr,
- llvm::StringRef errorContext,
- RecordData &Record,
- StringRef Blob,
- bool allowEmptyString) {
+std::error_code
+DiagLoader::readRange(const serialized_diags::Location &SDStart,
+ const serialized_diags::Location &SDEnd,
+ CXSourceRange &SR) {
+ CXLoadedDiagnostic::Location *Start, *End;
+ 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;
- // Basic buffer overflow check.
- if (Blob.size() > 65536) {
- reportInvalidFile(std::string("Out-of-bounds string in ") +
- std::string(errorContext));
- return Failure;
- }
+ CXSourceLocation startLoc = makeLocation(Start);
+ CXSourceLocation endLoc = makeLocation(End);
+ SR = clang_getRange(startLoc, endLoc);
+ return std::error_code();
+}
- 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;
+std::error_code DiagLoader::visitStartOfDiagnostic() {
+ CurrentDiags.push_back(llvm::make_unique<CXLoadedDiagnostic>());
+ return std::error_code();
}
-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;
+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();
}
-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;
- }
+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();
+}
- 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;
+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();
}
-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>();
-
- 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 Success;
+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();
}
-LoadResult DiagLoader::readDiagnosticBlock(llvm::BitstreamCursor &Stream,
- CXDiagnosticSetImpl &Diags,
- CXLoadedDiagnosticSetImpl &TopDiags){
+std::error_code
+DiagLoader::visitSourceRangeRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End) {
+ CXSourceRange SR;
+ if (std::error_code EC = readRange(Start, End, SR))
+ return EC;
+ CurrentDiags.back()->Ranges.push_back(SR);
+ return std::error_code();
+}
- if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
- reportInvalidFile("malformed diagnostic block");
- return Failure;
- }
+std::error_code
+DiagLoader::visitFixitRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End,
+ StringRef CodeToInsert) {
+ 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();
+}
- 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;
- }
-
- continue;
- }
- case Read_BlockEnd:
- Diags.appendDiagnostic(std::move(D));
- return Success;
- case Read_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 ((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;
- }
-
- const FileEntry *FE =
- TopDiags.FakeFiles.getVirtualFile(TopDiags.FileNames[Record[0]],
- /* size */ Record[1],
- /* time */ Record[2]);
-
- TopDiags.Files[Record[0]] = FE;
- continue;
- }
-
- case serialized_diags::RECORD_SOURCE_RANGE: {
- CXSourceRange SR;
- if (readRange(TopDiags, Record, 0, SR))
- return Failure;
- D->Ranges.push_back(SR);
- continue;
- }
-
- case serialized_diags::RECORD_FIXIT: {
- CXSourceRange SR;
- 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;
- }
-
- 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;
- }
- }
- }
+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();
}
extern "C" {