Skip to content

Commit 65ea9c8

Browse files
committed
Serialization: Skip custom attributes with invalid types.
Prevents a crash during module emission with `-enable-lazy-typechecking` when the type corresponding to a `CustomAttr` cannot be resolved.
1 parent 72da8f4 commit 65ea9c8

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,9 @@ ERROR(sema_opening_import,Fatal,
811811
REMARK(serialization_skipped_invalid_decl,none,
812812
"serialization skipped invalid %kind0",
813813
(const Decl *))
814+
REMARK(serialization_skipped_invalid_type,none,
815+
"serialization skipped for invalid type %0",
816+
(TypeRepr *))
814817
ERROR(serialization_failed,none,
815818
"serialization of module %0 failed due to the errors above",
816819
(const ModuleDecl *))

lib/Serialization/Serialization.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,12 +3048,12 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
30483048
if (D->getResolvedMacro(const_cast<CustomAttr *>(theAttr)))
30493049
return;
30503050

3051-
auto typeID = S.addTypeRef(
3052-
D->getResolvedCustomAttrType(const_cast<CustomAttr *>(theAttr)));
3053-
if (!typeID && !S.allowCompilerErrors()) {
3054-
llvm::PrettyStackTraceString message("CustomAttr has no type");
3055-
abort();
3056-
}
3051+
auto attrType =
3052+
D->getResolvedCustomAttrType(const_cast<CustomAttr *>(theAttr));
3053+
if (S.skipTypeIfInvalid(attrType, theAttr->getTypeRepr()))
3054+
return;
3055+
3056+
auto typeID = S.addTypeRef(attrType);
30573057
CustomDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode,
30583058
theAttr->isImplicit(),
30593059
typeID, theAttr->isArgUnsafe());
@@ -6812,6 +6812,19 @@ bool Serializer::skipDeclIfInvalid(const Decl *decl) {
68126812
return true;
68136813
}
68146814

6815+
bool Serializer::skipTypeIfInvalid(Type ty, TypeRepr *tyRepr) {
6816+
if (ty || allowCompilerErrors())
6817+
return false;
6818+
6819+
if (Options.EnableSerializationRemarks) {
6820+
getASTContext().Diags.diagnose(
6821+
tyRepr->getLoc(), diag::serialization_skipped_invalid_type, tyRepr);
6822+
}
6823+
6824+
hadError = true;
6825+
return true;
6826+
}
6827+
68156828
void serialization::writeToStream(
68166829
raw_ostream &os, ModuleOrSourceFile DC, const SILModule *M,
68176830
const SerializationOptions &options,

lib/Serialization/Serialization.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ class Serializer : public SerializerBase {
579579
/// If the declaration is invalid, records that an error occurred and returns
580580
/// true if the decl should be skipped.
581581
bool skipDeclIfInvalid(const Decl *decl);
582+
583+
/// If the type is invalid, records that an error occurred and returns
584+
/// true if the type should be skipped.
585+
bool skipTypeIfInvalid(Type ty, TypeRepr *tyRepr);
582586
};
583587

584588
} // end namespace serialization

test/Serialization/lazy-typecheck-errors.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ public func returnsInvalidType() -> InvalidType { fatalError() }
1616
public func takesInvalidType(_ x: InvalidType) {}
1717
// expected-error@-1 {{cannot find type 'InvalidType' in scope}}
1818
// expected-serialization-remark@-2 {{serialization skipped invalid global function 'takesInvalidType'}}
19+
20+
@InvalidCustomAttr public struct HasInvalidCustomAttr {}
21+
// FIXME: An error should be emitted for the invalid attribute
22+
// expected-serialization-remark@-2 {{serialization skipped for invalid type 'InvalidCustomAttr'}}

0 commit comments

Comments
 (0)