Skip to content

Commit 8a0e706

Browse files
authored
Merge pull request #36026 from bnbarham/allow-errors-sil-crash
[Serialization] Emit an error on deserializing an invalid declaration
2 parents 077d96c + 47b068d commit 8a0e706

File tree

3 files changed

+124
-4
lines changed

3 files changed

+124
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,13 @@ NOTE(serialization_compatibility_version_mismatch,none,
776776
"(this is supported but may expose additional compiler issues)",
777777
(StringRef, StringRef, StringRef))
778778

779+
ERROR(serialization_allowing_invalid_decl,none,
780+
"allowing deserialization of invalid declaration %0 from module '%1'",
781+
(DeclName, StringRef))
782+
ERROR(serialization_invalid_decl,Fatal,
783+
"invalid declaration %0 read from module '%1'; "
784+
SWIFT_BUG_REPORT_MESSAGE, ())
785+
779786
ERROR(reserved_member_name,none,
780787
"type member must not be named %0, since it would conflict with the"
781788
" 'foo.%1' expression", (DeclName, StringRef))

lib/Serialization/Deserialization.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4083,6 +4083,22 @@ ModuleFile::getDeclChecked(
40834083
matchAttributes);
40844084
if (!deserialized)
40854085
return deserialized;
4086+
4087+
auto *decl = declOrOffset.get();
4088+
if (decl->isInvalid()) {
4089+
if (!isAllowModuleWithCompilerErrorsEnabled()) {
4090+
getContext().Diags.diagnose(SourceLoc(),
4091+
diag::serialization_invalid_decl);
4092+
} else if (!isa<ParamDecl>(decl) && !decl->isImplicit()) {
4093+
// The parent function will be invalid if the parameter is invalid,
4094+
// implicits should have an invalid explicit as well
4095+
if (auto *VD = dyn_cast<ValueDecl>(decl)) {
4096+
getContext().Diags.diagnose(
4097+
VD->getLoc(), diag::serialization_allowing_invalid_decl,
4098+
VD->getName(), VD->getModuleContext()->getNameStr());
4099+
}
4100+
}
4101+
}
40864102
} else if (matchAttributes) {
40874103
// Decl was cached but we may need to filter it
40884104
if (!matchAttributes(declOrOffset.get()->getAttrs()))

test/Frontend/allow-errors.swift

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,111 @@
11
// RUN: %empty-directory(%t)
22

33
// The module should be generated regardless of errors and diagnostic should still be output
4-
// RUN: %target-swift-frontend -verify -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors %s
4+
// RUN: %target-swift-frontend -verify -emit-module -o %t/errors.swiftmodule -experimental-allow-module-with-compiler-errors -D ERROR_MODULE %s
55
// RUN: llvm-bcanalyzer %t/errors.swiftmodule | %FileCheck -check-prefix=CHECK-BC %s
66
// CHECK-BC-NOT: UnknownCode
7+
#if ERROR_MODULE
8+
public struct ValidStructInvalidMember {
9+
public var member: String
10+
public let memberMissingType: undefined // expected-error {{cannot find type 'undefined'}}
711

8-
struct InvalidStruct {
9-
let memberMissingType: undefined // expected-error {{cannot find type 'undefined'}}
12+
public var memberMissingTypeValidSets: undefined { // expected-error {{cannot find type 'undefined'}}
13+
willSet {
14+
print("Setting value \(newValue)")
15+
}
16+
didSet {
17+
print("Set value \(oldValue)")
18+
}
19+
}
20+
public var memberInvalidSets: Int {
21+
willSet {
22+
undefined // expected-error {{cannot find 'undefined'}}
23+
}
24+
didSet {
25+
undefined // expected-error {{cannot find 'undefined'}}
26+
}
27+
}
28+
29+
public lazy var lazyMemberMissingTypeValidBody: undefined = { // expected-error {{cannot find type 'undefined'}}
30+
return ""
31+
}()
32+
public lazy var lazyMemberInvalidBody: String = {
33+
return undefined // expected-error {{cannot find 'undefined'}}
34+
}()
35+
36+
public var memberMissingTypeValidGetSets: String {
37+
get { member }
38+
set { member = "" }
39+
}
40+
public var memberInvalidGetSet: String {
41+
get { undefined } // expected-error {{cannot find 'undefined'}}
42+
set { undefined = "" } // expected-error {{cannot find 'undefined'}}
43+
}
44+
45+
public func funcBadArg(_ arg: undefined? = nil) {} // expected-error {{cannot find type 'undefined'}}
1046
}
1147

12-
func invalidFunc() -> InvalidStruct {
48+
public func validFunc() -> String { "" }
49+
50+
public func invalidFuncBody() -> ValidStructInvalidMember {
1351
ret // expected-error {{cannot find 'ret'}}
1452
}
53+
54+
public func invalidFunc() -> undefined {} // expected-error {{cannot find type 'undefined'}}
55+
#endif
56+
57+
// RUN: %target-swift-frontend -emit-module -o %t/validUses.swiftmodule -experimental-allow-module-with-compiler-errors -I%t -D VALID_USES %s 2>&1 | %FileCheck -check-prefix=CHECK-VALID %s
58+
// RUN: llvm-bcanalyzer %t/validUses.swiftmodule | %FileCheck -check-prefix=CHECK-BC %s
59+
#if VALID_USES
60+
import errors
61+
func test(s: ValidStructInvalidMember) {
62+
print(s.member)
63+
print(validFunc())
64+
print(invalidFuncBody())
65+
}
66+
67+
// Check SIL diagnostics are still output (no reason not to output SIL since
68+
// there were no errors)
69+
func other() -> Int {}
70+
// CHECK-VALID: allow-errors.swift:[[@LINE-1]]:22: error: missing return in a function expected to return 'Int'
71+
#endif
72+
73+
// All invalid uses should have no errors in the file itself, all referenced
74+
// invalid declarations should have an error elsewhere (but we don't care what
75+
// that location is)
76+
77+
// RUN: %target-swift-frontend -emit-module -o %t/invalidTopUse.swiftmodule -experimental-allow-module-with-compiler-errors -I%t -D INVALID_TOP_LEVEL_USE %s 2>&1 | %FileCheck -check-prefix=CHECK-INVALID-TOP %s
78+
// RUN: llvm-bcanalyzer %t/invalidTopUse.swiftmodule | %FileCheck -check-prefix=CHECK-BC %s
79+
#if INVALID_TOP_LEVEL_USE
80+
import errors
81+
func test() {
82+
invalidFunc()
83+
}
84+
// CHECK-INVALID-TOP-NOT: allow-errors.swift:{{.*}} error:
85+
// CHECK-INVALID-TOP: error: allowing deserialization of invalid declaration 'invalidFunc()' from module 'errors'
86+
// CHECK-INVALID-TOP-NOT: allow-errors.swift:{{.*}} error:
87+
#endif
88+
89+
// RUN: %target-swift-frontend -emit-module -o %t/invalidMemberUse.swiftmodule -experimental-allow-module-with-compiler-errors -I%t -D INVALID_MEMBER_USE %s 2>&1 | %FileCheck -check-prefix=CHECK-INVALID-MEMBER %s
90+
// RUN: llvm-bcanalyzer %t/invalidMemberUse.swiftmodule | %FileCheck -check-prefix=CHECK-BC %s
91+
#if INVALID_MEMBER_USE
92+
import errors
93+
func test(s: ValidStructInvalidMember) {
94+
print(s.memberMissingType)
95+
}
96+
// CHECK-INVALID-MEMBER-NOT: allow-errors.swift:{{.*}} error:
97+
// CHECK-INVALID-MEMBER: error: allowing deserialization of invalid declaration 'memberMissingType' from module 'errors'
98+
// CHECK-INVALID-MEMBER-NOT: allow-errors.swift:{{.*}} error:
99+
#endif
100+
101+
// RUN: %target-swift-frontend -emit-module -o %t/invalidMethodUse.swiftmodule -experimental-allow-module-with-compiler-errors -I%t -D INVALID_METHOD_USE %s 2>&1 | %FileCheck -check-prefix=CHECK-INVALID-METHOD %s
102+
// RUN: llvm-bcanalyzer %t/invalidMethodUse.swiftmodule | %FileCheck -check-prefix=CHECK-BC %s
103+
#if INVALID_METHOD_USE
104+
import errors
105+
func test(s: ValidStructInvalidMember) {
106+
s.funcBadArg()
107+
}
108+
// CHECK-INVALID-METHOD-NOT: allow-errors.swift:{{.*}} error:
109+
// CHECK-INVALID-METHOD: error: allowing deserialization of invalid declaration 'funcBadArg' from module 'errors'
110+
// CHECK-INVALID-METHOD-NOT: allow-errors.swift:{{.*}} error:
111+
#endif

0 commit comments

Comments
 (0)