Skip to content

Commit 9d6643b

Browse files
committed
Optimizer: fix a crash in keypath folding
The KeyPathProjector utility crashed for keypaths to stored objectiveC properties. rdar://132780588
1 parent 1869174 commit 9d6643b

File tree

2 files changed

+76
-18
lines changed

2 files changed

+76
-18
lines changed

lib/SILOptimizer/Utils/KeyPathProjector.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,7 @@ class StoredPropertyProjector : public ComponentProjector {
136136
while (Ref->getType().getClassOrBoundGenericClass() !=
137137
storedProperty->getDeclContext()) {
138138
SILType superCl = Ref->getType().getSuperclass();
139-
if (!superCl) {
140-
// This should never happen, because the property should be in the
141-
// decl or in a superclass of it. Just handle this to be on the safe
142-
// side.
143-
callback(SILValue());
144-
if (Borrow) {
145-
builder.createEndBorrow(loc, Borrow);
146-
}
147-
return;
148-
}
139+
ASSERT(superCl && "the property should be in the decl or in a superclass of it");
149140
Ref = builder.createUpcast(loc, Ref, superCl);
150141
}
151142

@@ -701,15 +692,28 @@ KeyPathProjector::create(SILValue keyPath, SILValue root,
701692
// Check if the keypath only contains patterns which we support.
702693
auto components = kpInst->getPattern()->getComponents();
703694
for (const KeyPathPatternComponent &comp : components) {
704-
if (comp.getKind() == KeyPathPatternComponent::Kind::GettableProperty ||
705-
comp.getKind() == KeyPathPatternComponent::Kind::SettableProperty) {
706-
if (!comp.getExternalSubstitutions().empty() ||
707-
!comp.getSubscriptIndices().empty()) {
708-
// TODO: right now we can't optimize computed properties that require
709-
// additional context for subscript indices or generic environment
710-
// See https://github.com/apple/swift/pull/28799#issuecomment-570299845
711-
return nullptr;
695+
switch (comp.getKind()) {
696+
case KeyPathPatternComponent::Kind::GettableProperty:
697+
case KeyPathPatternComponent::Kind::SettableProperty:
698+
if (!comp.getExternalSubstitutions().empty() ||
699+
!comp.getSubscriptIndices().empty()) {
700+
// TODO: right now we can't optimize computed properties that require
701+
// additional context for subscript indices or generic environment
702+
// See https://github.com/apple/swift/pull/28799#issuecomment-570299845
703+
return nullptr;
704+
}
705+
break;
706+
case KeyPathPatternComponent::Kind::StoredProperty: {
707+
auto *declCtxt = comp.getStoredPropertyDecl()->getDeclContext();
708+
if (!isa<StructDecl>(declCtxt) && !isa<ClassDecl>(declCtxt)) {
709+
// This can happen, e.g. for ObjectiveC class properties, which are
710+
// defined in an extension.
711+
return nullptr;
712+
}
713+
break;
712714
}
715+
default:
716+
break;
713717
}
714718
}
715719

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %target-sil-opt -I %t %t/test.sil -sil-combine | %FileCheck %s
4+
5+
// REQUIRES: objc_interop
6+
7+
//--- module.modulemap
8+
9+
module CModule {
10+
header "c-header.h"
11+
export *
12+
}
13+
14+
15+
//--- c-header.h
16+
17+
@import Foundation;
18+
19+
@interface ObjClass : NSObject
20+
@property (nonatomic, strong, readwrite, nonnull) NSObject *o;
21+
@end
22+
23+
24+
//--- test.sil
25+
26+
sil_stage canonical
27+
28+
import Swift
29+
import SwiftShims
30+
import Builtin
31+
import CModule
32+
33+
extension ObjClass {
34+
@objc @_hasStorage dynamic var o: NSObject { get set }
35+
}
36+
37+
sil @swift_getAtKeyPath : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
38+
39+
// Check that we don't crash
40+
41+
// CHECK-LABEL: sil @testObjcKeypath :
42+
// CHECK: keypath
43+
// CHECK: apply
44+
// CHECK: } // end sil function 'testObjcKeypath'
45+
sil @testObjcKeypath : $@convention(thin) (@in_guaranteed ObjClass) -> @out NSObject {
46+
bb0(%0 : $*NSObject, %1 : $*ObjClass):
47+
%2 = keypath $KeyPath<ObjClass, NSObject>, (root $ObjClass; stored_property #ObjClass.o : $NSObject)
48+
%3 = function_ref @swift_getAtKeyPath : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
49+
%4 = apply %3<ObjClass, NSObject>(%0, %1, %2) : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed KeyPath<τ_0_0, τ_0_1>) -> @out τ_0_1
50+
strong_release %2 : $KeyPath<ObjClass, NSObject>
51+
%6 = tuple ()
52+
return %6 : $()
53+
}
54+

0 commit comments

Comments
 (0)