[Serialization] Properly skip invalid destructors when allowing errors

7856f2d83d only partially skipped writing
out destructors when they were invalid, ie. it skipped writing the decl
itself but not the records common to all decls. This would cause any
records on the destructor to be applied on the next serialized decl.

Make sure to skip serializing anything to do with the destructor when
it's invalid and does not have a class context.
This commit is contained in:
Ben Barham
2021-08-06 13:00:47 +10:00
parent b12ab969b2
commit 462ce0584d
3 changed files with 43 additions and 13 deletions

View File

@@ -3957,9 +3957,6 @@ public:
using namespace decls_block;
verifyAttrSerializable(dtor);
if (S.allowCompilerErrors() && dtor->isInvalid())
return;
auto contextID = S.addDeclContextRef(dtor->getDeclContext());
unsigned abbrCode = S.DeclTypeAbbrCodes[DestructorLayout::Code];
@@ -4001,12 +3998,34 @@ public:
}
};
/// When allowing modules with errors there may be cases where there's little
/// point in serializing a declaration and doing so would create a maintenance
/// burden on the deserialization side. Returns \c true if the given declaration
/// should be skipped and \c false otherwise.
static bool canSkipWhenInvalid(const Decl *D) {
// There's no point writing out the deinit when its context is not a class
// as nothing would be able to reference it
if (auto *deinit = dyn_cast<DestructorDecl>(D)) {
if (!isa<ClassDecl>(D->getDeclContext()))
return true;
}
return false;
}
void Serializer::writeASTBlockEntity(const Decl *D) {
using namespace decls_block;
PrettyStackTraceDecl trace("serializing", D);
assert(DeclsToSerialize.hasRef(D));
if (D->isInvalid()) {
assert(allowCompilerErrors() &&
"cannot create a module with an invalid decl");
if (canSkipWhenInvalid(D))
return;
}
BitOffset initialOffset = Out.GetCurrentBitNo();
SWIFT_DEFER {
// This is important enough to leave on in Release builds.
@@ -4016,8 +4035,6 @@ void Serializer::writeASTBlockEntity(const Decl *D) {
}
};
assert((allowCompilerErrors() || !D->isInvalid()) &&
"cannot create a module with an invalid decl");
if (isDeclXRef(D)) {
writeCrossReference(D);
return;