Skip to content

Commit d20e00e

Browse files
authored
[NFC] Improve deserialization errors for wrong record kind
There are a bunch of places where we expect to find a record with a particular record ID/kind in the decls_block and have to bail out if we see something we don’t expect. Add an `InvalidRecordKindError` we can use in this situation to produce a useful error message and adopt it in various places. This change also makes deserialization errors print the path to the invalid file.
1 parent 6075af2 commit d20e00e

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ const char ExtensionError::ID = '\0';
149149
void ExtensionError::anchor() {}
150150
const char DeclAttributesDidNotMatch::ID = '\0';
151151
void DeclAttributesDidNotMatch::anchor() {}
152+
const char InvalidRecordKindError::ID = '\0';
153+
void InvalidRecordKindError::anchor() {}
152154

153155
/// Skips a single record in the bitstream.
154156
///
@@ -239,8 +241,8 @@ ParameterList *ModuleFile::readParameterList() {
239241
fatalIfUnexpected(DeclTypeCursor.advance(AF_DontPopBlockAtEnd));
240242
unsigned recordID =
241243
fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, scratch));
242-
assert(recordID == PARAMETERLIST);
243-
(void) recordID;
244+
if (recordID != PARAMETERLIST)
245+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
244246

245247
ArrayRef<uint64_t> rawMemberIDs;
246248
decls_block::ParameterListLayout::readRecord(scratch, rawMemberIDs);
@@ -312,7 +314,8 @@ Expected<Pattern *> ModuleFile::readPattern(DeclContext *owningDC) {
312314
assert(next.Kind == llvm::BitstreamEntry::Record);
313315

314316
kind = fatalIfUnexpected(DeclTypeCursor.readRecord(next.ID, scratch));
315-
assert(kind == decls_block::TUPLE_PATTERN_ELT);
317+
if (kind != decls_block::TUPLE_PATTERN_ELT)
318+
fatal(llvm::make_error<InvalidRecordKindError>(kind));
316319

317320
// FIXME: Add something for this record or remove it.
318321
IdentifierID labelID;
@@ -393,7 +396,7 @@ Expected<Pattern *> ModuleFile::readPattern(DeclContext *owningDC) {
393396
}
394397

395398
default:
396-
return nullptr;
399+
return llvm::make_error<InvalidRecordKindError>(kind);
397400
}
398401
}
399402

@@ -432,7 +435,7 @@ SILLayout *ModuleFile::readSILLayout(llvm::BitstreamCursor &Cursor) {
432435
return SILLayout::get(getContext(), canSig, fields, capturesGenerics);
433436
}
434437
default:
435-
fatal();
438+
fatal(llvm::make_error<InvalidRecordKindError>(kind));
436439
}
437440
}
438441

@@ -503,7 +506,7 @@ ProtocolConformanceDeserializer::read(
503506

504507
// Not a protocol conformance.
505508
default:
506-
MF.fatal();
509+
MF.fatal(llvm::make_error<InvalidRecordKindError>(kind));
507510
}
508511
}
509512

@@ -1172,7 +1175,7 @@ ModuleFile::getGenericSignatureChecked(serialization::GenericSignatureID ID) {
11721175
}
11731176
default:
11741177
// Not a generic signature; no way to recover.
1175-
fatal();
1178+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
11761179
}
11771180

11781181
// If we've already deserialized this generic signature, start over to return
@@ -1214,7 +1217,7 @@ ModuleFile::getGenericEnvironmentChecked(serialization::GenericEnvironmentID ID)
12141217
unsigned recordID = fatalIfUnexpected(
12151218
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
12161219
if (recordID != GENERIC_ENVIRONMENT)
1217-
fatal();
1220+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
12181221

12191222
GenericSignatureID parentSigID;
12201223
TypeID existentialID;
@@ -1273,7 +1276,7 @@ ModuleFile::getSubstitutionMapChecked(serialization::SubstitutionMapID id) {
12731276
unsigned recordID = fatalIfUnexpected(
12741277
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
12751278
if (recordID != SUBSTITUTION_MAP)
1276-
fatal();
1279+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
12771280

12781281
GenericSignatureID genericSigID;
12791282
uint64_t numReplacementIDs;
@@ -1629,7 +1632,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
16291632
default:
16301633
// Unknown xref kind.
16311634
pathTrace.addUnknown(recordID);
1632-
fatal();
1635+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
16331636
}
16341637

16351638
auto getXRefDeclNameForError = [&]() -> DeclName {
@@ -1894,7 +1897,8 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
18941897
}
18951898

18961899
default:
1897-
llvm_unreachable("Unhandled path piece");
1900+
fatal(llvm::make_error<InvalidRecordKindError>(recordID,
1901+
"Unhandled path piece"));
18981902
}
18991903

19001904
pathTrace.addValue(memberName);
@@ -2100,7 +2104,7 @@ ModuleFile::resolveCrossReference(ModuleID MID, uint32_t pathLen) {
21002104
default:
21012105
// Unknown xref path piece.
21022106
pathTrace.addUnknown(recordID);
2103-
fatal();
2107+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
21042108
}
21052109

21062110
Optional<PrettyStackTraceModuleFile> traceMsg;
@@ -2273,7 +2277,8 @@ DeclContext *ModuleFile::getLocalDeclContext(LocalDeclContextID DCID) {
22732277
}
22742278

22752279
default:
2276-
llvm_unreachable("Unknown record ID found when reading local DeclContext.");
2280+
fatal(llvm::make_error<InvalidRecordKindError>(recordID,
2281+
"Unknown record ID found when reading local DeclContext."));
22772282
}
22782283
return declContextOrOffset;
22792284
}
@@ -5085,7 +5090,7 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
50855090

50865091
default:
50875092
// We don't know how to deserialize this kind of attribute.
5088-
MF.fatal();
5093+
MF.fatal(llvm::make_error<InvalidRecordKindError>(recordID));
50895094
}
50905095

50915096
if (!skipAttr) {
@@ -5211,7 +5216,7 @@ DeclDeserializer::getDeclCheckedImpl(
52115216

52125217
default:
52135218
// We don't know how to deserialize this kind of decl.
5214-
MF.fatal();
5219+
MF.fatal(llvm::make_error<InvalidRecordKindError>(recordID));
52155220
}
52165221
}
52175222

@@ -6431,7 +6436,7 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
64316436
#undef TYPE
64326437
default:
64336438
// We don't know how to deserialize this kind of type.
6434-
fatal();
6439+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
64356440
}
64366441
}
64376442

@@ -6550,7 +6555,7 @@ ModuleFile::getClangType(ClangTypeID TID) {
65506555
DeclTypeCursor.readRecord(entry.ID, scratch, &blobData));
65516556

65526557
if (recordID != decls_block::CLANG_TYPE)
6553-
fatal();
6558+
fatal(llvm::make_error<InvalidRecordKindError>(recordID));
65546559

65556560
auto &clangLoader = *getContext().getClangModuleLoader();
65566561
auto clangType =
@@ -6640,8 +6645,8 @@ void ModuleFile::loadAllMembers(Decl *container, uint64_t contextData) {
66406645

66416646
unsigned kind =
66426647
fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, memberIDBuffer));
6643-
assert(kind == decls_block::MEMBERS);
6644-
(void)kind;
6648+
if (kind != decls_block::MEMBERS)
6649+
fatal(llvm::make_error<InvalidRecordKindError>(kind));
66456650

66466651
ArrayRef<uint64_t> rawMemberIDs;
66476652
decls_block::MembersLayout::readRecord(memberIDBuffer, rawMemberIDs);
@@ -6845,9 +6850,10 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance,
68456850

68466851
unsigned kind =
68476852
fatalIfUnexpected(DeclTypeCursor.readRecord(entry.ID, scratch));
6848-
(void) kind;
6849-
assert(kind == NORMAL_PROTOCOL_CONFORMANCE &&
6850-
"registered lazy loader incorrectly");
6853+
if (kind != NORMAL_PROTOCOL_CONFORMANCE)
6854+
fatal(llvm::make_error<InvalidRecordKindError>(kind,
6855+
"registered lazy loader incorrectly"));
6856+
68516857
NormalProtocolConformanceLayout::readRecord(scratch, protoID,
68526858
contextID, typeCount,
68536859
valueCount, conformanceCount,

lib/Serialization/DeserializationErrors.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,38 @@ class DeclAttributesDidNotMatch : public llvm::ErrorInfo<DeclAttributesDidNotMat
445445
}
446446
};
447447

448+
class InvalidRecordKindError :
449+
public llvm::ErrorInfo<InvalidRecordKindError, DeclDeserializationError> {
450+
friend ErrorInfo;
451+
static const char ID;
452+
void anchor() override;
453+
454+
unsigned recordKind;
455+
const char *extraText;
456+
457+
public:
458+
explicit InvalidRecordKindError(unsigned kind,
459+
const char *extraText = nullptr) {
460+
this->recordKind = kind;
461+
this->extraText = extraText;
462+
}
463+
464+
void log(raw_ostream &OS) const override {
465+
OS << "don't know how to deserialize record with code " << recordKind;
466+
if (recordKind >= decls_block::SILGenName_DECL_ATTR)
467+
OS << " (attribute kind "
468+
<< recordKind - decls_block::SILGenName_DECL_ATTR << ")";
469+
if (extraText)
470+
OS << ": " << extraText;
471+
OS << "; this may be a compiler bug, or a file on disk may have changed "
472+
"during compilation";
473+
}
474+
475+
std::error_code convertToErrorCode() const override {
476+
return llvm::inconvertibleErrorCode();
477+
}
478+
};
479+
448480
LLVM_NODISCARD
449481
static inline std::unique_ptr<llvm::ErrorInfoBase>
450482
takeErrorInfo(llvm::Error error) {

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ void ModuleFileSharedCore::outputDiagnosticInfo(llvm::raw_ostream &os) const {
585585
<< "'";
586586
if (Bits.IsAllowModuleWithCompilerErrorsEnabled)
587587
os << " (built with -experimental-allow-module-with-compiler-errors)";
588+
if (ModuleInputBuffer)
589+
os << " at '" << ModuleInputBuffer->getBufferIdentifier() << "'";
588590
}
589591

590592
ModuleFileSharedCore::~ModuleFileSharedCore() { }

0 commit comments

Comments
 (0)