Skip to content

Commit 81e2638

Browse files
authored
[SILOpt] Don't do callee analysis on destructors of imported classes. (#6313)
If by chance we haven't imported the members of a particular class, SIL should not fault them in if at all possible. The test case was a pain to come up with; it involves a class using a forward-declared protocol that's actually defined in Swift /in a non-primary file/, where that protocol is never mentioned in the primary file and the class's members are never accessed otherwise. rdar://problem/29535170
1 parent e830110 commit 81e2638

File tree

4 files changed

+25
-6
lines changed

4 files changed

+25
-6
lines changed

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ CalleeCache::getOrCreateCalleesForMethod(SILDeclRef Decl) {
7575
/// Update the callees for each method of a given class, along with
7676
/// all the overridden methods from superclasses.
7777
void CalleeCache::computeClassMethodCalleesForClass(ClassDecl *CD) {
78+
assert(!CD->hasClangNode());
79+
7880
for (auto *Member : CD->getMembers()) {
7981
auto *AFD = dyn_cast<AbstractFunctionDecl>(Member);
8082
if (!AFD)
@@ -229,7 +231,7 @@ CalleeList CalleeCache::getCalleeList(SILInstruction *I) const {
229231
->getAnyOptionalObjectType()
230232
.getCanonicalTypeOrNull());
231233
auto Class = Ty.getSwiftRValueType().getClassOrBoundGenericClass();
232-
if (!Class || !Class->hasDestructor())
234+
if (!Class || Class->hasClangNode() || !Class->hasDestructor())
233235
return CalleeList();
234236
auto Destructor = Class->getDestructor();
235237
return getCalleeList(Destructor);

test/ClangImporter/MixedSource/Inputs/mixed-target/header.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
#import "used-by-both-headers.h"
88

99
@class ForwardClass;
10+
@protocol ForwardProto;
11+
1012
void doSomething(ForwardClass *arg);
13+
void doSomethingProto(id <ForwardProto> arg);
1114

1215
@interface Base
1316
- (NSObject *)safeOverride:(ForwardClass *)arg;
@@ -21,9 +24,6 @@ void doSomething(ForwardClass *arg);
2124
@end
2225

2326

24-
@protocol ForwardProto;
25-
void doSomethingProto(id <ForwardProto> arg);
26-
2727
@interface Base ()
2828
- (NSObject *)safeOverrideProto:(id <ForwardProto>)arg;
2929
- (NSObject *)unsafeOverrideProtoParam:(NSObject *)arg;
@@ -69,3 +69,9 @@ typedef int NameInProtocol;
6969
@interface WrapperInterface (Category)
7070
typedef int NameInCategory;
7171
@end
72+
73+
74+
@protocol ForwardProtoFromOtherFile;
75+
@interface ClassThatHasAProtocolTypedPropertyButMembersAreNeverLoaded
76+
@property (weak) id <ForwardProtoFromOtherFile> weakProtoProp;
77+
@end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@objc protocol ForwardProtoFromOtherFile {}

test/ClangImporter/MixedSource/mixed-target-using-header.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -import-objc-header %S/Inputs/mixed-target/header.h -typecheck %s -disable-objc-attr-requires-foundation-module -verify
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -import-objc-header %S/Inputs/mixed-target/header.h -typecheck -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -verify
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/../Inputs/custom-modules -import-objc-header %S/Inputs/mixed-target/header.h -emit-sil -primary-file %s %S/Inputs/mixed-target/other-file.swift -disable-objc-attr-requires-foundation-module -o /dev/null -D SILGEN
23

34
// REQUIRES: objc_interop
45

@@ -37,17 +38,21 @@ class ProtoConformer : ForwardClassUser {
3738
func testProtocolWrapper(_ conformer: ForwardClassUser) {
3839
conformer.consumeForwardClass(conformer.forward)
3940
}
40-
testProtocolWrapper(ProtoConformer())
41+
func useProtocolWrapper() {
42+
testProtocolWrapper(ProtoConformer())
43+
}
4144

4245
func testStruct(_ p: Point2D) -> Point2D {
4346
var result = p
4447
result.y += 5
4548
return result
4649
}
4750

51+
#if !SILGEN
4852
func testSuppressed() {
4953
let _: __int128_t? = nil // expected-error{{use of undeclared type '__int128_t'}}
5054
}
55+
#endif
5156

5257
func testMacro() {
5358
_ = CONSTANT as CInt
@@ -58,6 +63,7 @@ func testFoundationOverlay() {
5863
_ = NSUTF8StringEncoding as UInt // and we should get the overlay version
5964
}
6065

66+
#if !SILGEN
6167
func testProtocolNamingConflict() {
6268
let a: ConflictingName1?
6369
var b: ConflictingName1Protocol?
@@ -69,9 +75,13 @@ func testProtocolNamingConflict() {
6975
d = c // expected-error {{cannot assign value of type 'ConflictingName2?' to type 'ConflictingName2Protocol?'}}
7076
_ = d
7177
}
78+
#endif
7279

7380
func testDeclsNestedInObjCContainers() {
7481
let _: NameInInterface = 0
7582
let _: NameInProtocol = 0
7683
let _: NameInCategory = 0
7784
}
85+
86+
func testReleaseClassWhoseMembersAreNeverLoaded(
87+
obj: ClassThatHasAProtocolTypedPropertyButMembersAreNeverLoaded) {}

0 commit comments

Comments
 (0)