Skip to content

Commit 9048e97

Browse files
committed
Executable test case for passing a noescape closure to Objective-c which
escapes the closure. We expect the program to crash with an explanation. rdar://39682865
1 parent b2c4234 commit 9048e97

File tree

4 files changed

+85
-0
lines changed

4 files changed

+85
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Foundation
2+
3+
@objc(DangerousEscaper)
4+
public protocol DangerousEscaper {
5+
@objc
6+
func mightBeNaughty(_ mayActuallyEscape: () -> ())
7+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#import <Foundation/Foundation.h>
2+
3+
@interface Escaper : NSObject
4+
@property void (^escape)(void);
5+
- (id) init;
6+
@end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#import "Escaper.h"
2+
3+
#import "DangerousEscaper.h"
4+
5+
@interface Escaper () <DangerousEscaper>
6+
-(void)mightBeNaughty:(void (^)(void))completion;
7+
@end
8+
9+
@implementation Escaper
10+
11+
- (id)init {
12+
if ((self = [super init]) != nil) {
13+
self.escape = ^{};
14+
}
15+
return self;
16+
}
17+
18+
-(void)mightBeNaughty:(void (^)(void))completion {
19+
self.escape = completion;
20+
completion();
21+
}
22+
23+
@end
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swiftc_driver -emit-objc-header %S/../Inputs/objc-escape/DangerousEscaper.swift -emit-objc-header-path %t/DangerousEscaper.h
3+
// RUN: %target-clang -c %S/../Inputs/objc-escape/Escaper.m -fobjc-arc -I %t -o %t/Escaper.o
4+
// RUN: %target-swiftc_driver -import-objc-header %S/../Inputs/objc-escape/Escaper.h %S/../Inputs/objc-escape/DangerousEscaper.swift %s %t/Escaper.o -o %t/TestObjcProto
5+
// RUN: %target-run %t/TestObjcProto 2>&1 | %FileCheck %s
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: objc_interop
9+
10+
import Foundation
11+
import Dispatch
12+
import StdlibUnittest
13+
14+
15+
var testSuite = TestSuite("ObjectiveCClosureEscape")
16+
17+
18+
public func couldActuallyEscape(_ closure: @escaping () -> (), _ villian: DangerousEscaper) {
19+
villian.mightBeNaughty(closure)
20+
}
21+
22+
class Harmless : DangerousEscaper {
23+
@objc
24+
func mightBeNaughty(_ mayActuallyEscape: () -> ()) {
25+
mayActuallyEscape()
26+
}
27+
}
28+
29+
class Printer {
30+
func printIt() {
31+
print("Printer")
32+
}
33+
}
34+
35+
public func test() {
36+
var x = Printer()
37+
couldActuallyEscape( {x.printIt() } , Harmless())
38+
39+
var y = Escaper()
40+
couldActuallyEscape( {x.printIt() } , y as! DangerousEscaper)
41+
}
42+
43+
testSuite.test("testEscaping") {
44+
// CHECK: closure argument was escaped in withoutActuallyEscaping block
45+
expectCrashLater()
46+
test()
47+
}
48+
49+
runAllTests()

0 commit comments

Comments
 (0)