summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReaderDecl.cpp
diff options
context:
space:
mode:
authorJF Bastien <jfbastien@apple.com>2019-06-26 19:50:12 +0000
committerJF Bastien <jfbastien@apple.com>2019-06-26 19:50:12 +0000
commit0e828958264734e60115ba2482437008c822d7db (patch)
tree3fc2aa5876f36d46ae328df9b7a5ee7dfa781894 /clang/lib/Serialization/ASTReaderDecl.cpp
parentafa58b6ba19a54e6fd41ab3994e114f0f6bcb239 (diff)
downloadbcm5719-llvm-0e828958264734e60115ba2482437008c822d7db.tar.gz
bcm5719-llvm-0e828958264734e60115ba2482437008c822d7db.zip
BitStream reader: propagate errors
The bitstream reader handles errors poorly. This has two effects: * Bugs in file handling (especially modules) manifest as an "unexpected end of file" crash * Users of clang as a library end up aborting because the code unconditionally calls `report_fatal_error` The bitstream reader should be more resilient and return Expected / Error as soon as an error is encountered, not way late like it does now. This patch starts doing so and adopting the error handling where I think it makes sense. There's plenty more to do: this patch propagates errors to be minimally useful, and follow-ups will propagate them further and improve diagnostics. https://bugs.llvm.org/show_bug.cgi?id=42311 <rdar://problem/33159405> Differential Revision: https://reviews.llvm.org/D63518 llvm-svn: 364464
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp65
1 files changed, 52 insertions, 13 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 359c86d0199..bd7880c3395 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -3679,14 +3679,28 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// Note that we are loading a declaration record.
Deserializing ADecl(this);
- DeclsCursor.JumpToBit(Loc.Offset);
+ auto Fail = [](const char *what, llvm::Error &&Err) {
+ llvm::report_fatal_error(Twine("ASTReader::ReadDeclRecord failed ") + what +
+ ": " + toString(std::move(Err)));
+ };
+
+ if (llvm::Error JumpFailed = DeclsCursor.JumpToBit(Loc.Offset))
+ Fail("jumping", std::move(JumpFailed));
ASTRecordReader Record(*this, *Loc.F);
ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc);
- unsigned Code = DeclsCursor.ReadCode();
+ Expected<unsigned> MaybeCode = DeclsCursor.ReadCode();
+ if (!MaybeCode)
+ Fail("reading code", MaybeCode.takeError());
+ unsigned Code = MaybeCode.get();
ASTContext &Context = getContext();
Decl *D = nullptr;
- switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) {
+ Expected<unsigned> MaybeDeclCode = Record.readRecord(DeclsCursor, Code);
+ if (!MaybeDeclCode)
+ llvm::report_fatal_error(
+ "ASTReader::ReadDeclRecord failed reading decl code: " +
+ toString(MaybeDeclCode.takeError()));
+ switch ((DeclCode)MaybeDeclCode.get()) {
case DECL_CONTEXT_LEXICAL:
case DECL_CONTEXT_VISIBLE:
llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
@@ -4025,12 +4039,25 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
uint64_t Offset = FileAndOffset.second;
llvm::BitstreamCursor &Cursor = F->DeclsCursor;
SavedStreamPosition SavedPosition(Cursor);
- Cursor.JumpToBit(Offset);
- unsigned Code = Cursor.ReadCode();
+ if (llvm::Error JumpFailed = Cursor.JumpToBit(Offset))
+ // FIXME don't do a fatal error.
+ llvm::report_fatal_error(
+ "ASTReader::loadDeclUpdateRecords failed jumping: " +
+ toString(std::move(JumpFailed)));
+ Expected<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode)
+ llvm::report_fatal_error(
+ "ASTReader::loadDeclUpdateRecords failed reading code: " +
+ toString(MaybeCode.takeError()));
+ unsigned Code = MaybeCode.get();
ASTRecordReader Record(*this, *F);
- unsigned RecCode = Record.readRecord(Cursor, Code);
- (void)RecCode;
- assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");
+ if (Expected<unsigned> MaybeRecCode = Record.readRecord(Cursor, Code))
+ assert(MaybeRecCode.get() == DECL_UPDATES &&
+ "Expected DECL_UPDATES record!");
+ else
+ llvm::report_fatal_error(
+ "ASTReader::loadDeclUpdateRecords failed reading rec code: " +
+ toString(MaybeCode.takeError()));
ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
SourceLocation());
@@ -4094,13 +4121,25 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
llvm::BitstreamCursor &Cursor = M->DeclsCursor;
SavedStreamPosition SavedPosition(Cursor);
- Cursor.JumpToBit(LocalOffset);
+ if (llvm::Error JumpFailed = Cursor.JumpToBit(LocalOffset))
+ llvm::report_fatal_error(
+ "ASTReader::loadPendingDeclChain failed jumping: " +
+ toString(std::move(JumpFailed)));
RecordData Record;
- unsigned Code = Cursor.ReadCode();
- unsigned RecCode = Cursor.readRecord(Code, Record);
- (void)RecCode;
- assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");
+ Expected<unsigned> MaybeCode = Cursor.ReadCode();
+ if (!MaybeCode)
+ llvm::report_fatal_error(
+ "ASTReader::loadPendingDeclChain failed reading code: " +
+ toString(MaybeCode.takeError()));
+ unsigned Code = MaybeCode.get();
+ if (Expected<unsigned> MaybeRecCode = Cursor.readRecord(Code, Record))
+ assert(MaybeRecCode.get() == LOCAL_REDECLARATIONS &&
+ "expected LOCAL_REDECLARATIONS record!");
+ else
+ llvm::report_fatal_error(
+ "ASTReader::loadPendingDeclChain failed reading rec code: " +
+ toString(MaybeCode.takeError()));
// FIXME: We have several different dispatches on decl kind here; maybe
// we should instead generate one loop per kind and dispatch up-front?
OpenPOWER on IntegriCloud