Skip to content

Commit 873f7b4

Browse files
authored
Merge pull request #13155 from rjmccall/addObserver-anyobject
Extend the addObserver/removeObserver to AnyObject lookup idioms
2 parents 0c53bbf + 02d7fe3 commit 873f7b4

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,19 +267,44 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
267267
unsigned uncurryLevel = 0;
268268
while (auto conv = dyn_cast<ImplicitConversionExpr>(base))
269269
base = conv->getSubExpr();
270+
271+
const auto findDynamicMemberRefExpr =
272+
[](Expr *e) -> DynamicMemberRefExpr* {
273+
if (auto open = dyn_cast<OpenExistentialExpr>(e)) {
274+
return dyn_cast<DynamicMemberRefExpr>(open->getSubExpr());
275+
}
276+
return nullptr;
277+
};
278+
279+
if (auto force = dyn_cast<ForceValueExpr>(base)) {
280+
if (auto ref = findDynamicMemberRefExpr(force->getSubExpr()))
281+
base = ref;
282+
} else if (auto bind = dyn_cast<BindOptionalExpr>(base)) {
283+
if (auto ref = findDynamicMemberRefExpr(bind->getSubExpr()))
284+
base = ref;
285+
}
286+
270287
while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(base))
271288
base = ignoredBase->getRHS();
272-
auto *calleeDRE = dyn_cast<DeclRefExpr>(base);
273-
if (calleeDRE) {
289+
290+
ConcreteDeclRef callee;
291+
if (auto *calleeDRE = dyn_cast<DeclRefExpr>(base)) {
274292
checkNoEscapeParameterUse(calleeDRE, Call, OperandKind::Callee);
275293
checkForSuspiciousBitCasts(calleeDRE, Call);
294+
callee = calleeDRE->getDeclRef();
276295

277296
// Otherwise, try to drill down through member calls for the purposes
278297
// of argument-matching code below.
279298
} else if (auto selfApply = dyn_cast<SelfApplyExpr>(base)) {
280299
uncurryLevel++;
281300
base = selfApply->getSemanticFn();
282-
calleeDRE = dyn_cast<DeclRefExpr>(base);
301+
if (auto calleeDRE = dyn_cast<DeclRefExpr>(base))
302+
callee = calleeDRE->getDeclRef();
303+
304+
// Otherwise, check for a dynamic member.
305+
} else if (auto dynamicMRE = dyn_cast<DynamicMemberRefExpr>(base)) {
306+
uncurryLevel++;
307+
callee = dynamicMRE->getMember();
283308
}
284309

285310
visitArguments(Call, [&](unsigned argIndex, Expr *arg) {
@@ -305,9 +330,8 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
305330

306331
// Also do some additional work based on how the function uses
307332
// the argument.
308-
if (calleeDRE) {
309-
checkConvertedPointerArgument(calleeDRE->getDeclRef(),
310-
uncurryLevel, argIndex,
333+
if (callee) {
334+
checkConvertedPointerArgument(callee, uncurryLevel, argIndex,
311335
unwrapped, operand);
312336
}
313337
}

test/SILGen/pointer_conversion_nonaccessing_objc.swift

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,44 @@ var global = 0
1414
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc15testAddObserverySo8NSObjectC6object_AD8observertF
1515
func testAddObserver(object: NSObject, observer: NSObject) {
1616
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
17-
// CHECK: address_to_pointer [[T0]]
17+
// CHECK: address_to_pointer [[T0]] :
1818
object.addObserver(observer, forKeyPath: "", options: 0, context: &global)
1919
}
2020

2121
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc18testRemoveObserverySo8NSObjectC6object_AD8observertF
2222
func testRemoveObserver(object: NSObject, observer: NSObject) {
2323
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
24-
// CHECK: address_to_pointer [[T0]]
24+
// CHECK: address_to_pointer [[T0]] :
2525
object.removeObserver(observer, forKeyPath: "", context: &global)
2626
}
27+
28+
// rdar://33850465
29+
// Make sure this applies to AnyObject dispatch, too.
30+
31+
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc28testDynamicForcedAddObserveryyXl6object_So8NSObjectC8observertF
32+
func testDynamicForcedAddObserver(object: AnyObject, observer: NSObject) {
33+
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
34+
// CHECK: address_to_pointer [[T0]] :
35+
object.addObserver!(observer, forKeyPath: "", options: 0, context: &global)
36+
}
37+
38+
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc31testDynamicForcedRemoveObserveryyXl6object_So8NSObjectC8observertF
39+
func testDynamicForcedRemoveObserver(object: AnyObject, observer: NSObject) {
40+
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
41+
// CHECK: address_to_pointer [[T0]] :
42+
object.removeObserver!(observer, forKeyPath: "", context: &global)
43+
}
44+
45+
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc30testDynamicOptionalAddObserveryyXl6object_So8NSObjectC8observertF
46+
func testDynamicOptionalAddObserver(object: AnyObject, observer: NSObject) {
47+
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
48+
// CHECK: address_to_pointer [[T0]] :
49+
object.addObserver?(observer, forKeyPath: "", options: 0, context: &global)
50+
}
51+
52+
// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc33testDynamicOptionalRemoveObserveryyXl6object_So8NSObjectC8observertF
53+
func testDynamicOptionalRemoveObserver(object: AnyObject, observer: NSObject) {
54+
// CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
55+
// CHECK: address_to_pointer [[T0]] :
56+
object.removeObserver?(observer, forKeyPath: "", context: &global)
57+
}

0 commit comments

Comments
 (0)