@@ -12,6 +12,11 @@ public func takesInout(_ i: inout Int) {
12
12
// Helper taking a basic, no-escape closure.
13
13
func takeClosure( _: ( ) -> Int ) { }
14
14
15
+ // Helper taking a basic, no-escape closure.
16
+ func takeClosureAndInout( _: inout Int , _: ( ) -> Int ) { }
17
+
18
+ // Helper taking an escaping closure.
19
+ func takeEscapingClosure( _: @escaping ( ) -> Int ) { }
15
20
16
21
// Generate an alloc_stack that escapes into a closure.
17
22
public func captureStack( ) -> Int {
@@ -21,8 +26,10 @@ public func captureStack() -> Int {
21
26
return x
22
27
}
23
28
// CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection12captureStackSiyF
24
- // Static access for `return x`.
25
- // CHECK: Static Access: %{{.*}} = begin_access [read] [static] %{{.*}} : $*Int
29
+ // Dynamic access for `return x`. Since the closure is non-escaping, using
30
+ // dynamic enforcement here is more conservative than it needs to be -- static
31
+ // is sufficient here.
32
+ // CHECK: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
26
33
27
34
// The access inside the closure is dynamic, until we have the logic necessary to
28
35
// prove that no other closures are passed to `takeClosure` that may write to
@@ -31,6 +38,49 @@ public func captureStack() -> Int {
31
38
// CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection12captureStackSiyFSiycfU_
32
39
// CHECK: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
33
40
41
+
42
+ // Generate an alloc_stack that does not escape into a closure.
43
+ public func nocaptureStack( ) -> Int {
44
+ var x = 3
45
+ takeClosure { return 5 }
46
+ return x
47
+ }
48
+ // CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection14nocaptureStackSiyF
49
+ // Static access for `return x`.
50
+ // CHECK: Static Access: %{{.*}} = begin_access [read] [static] %{{.*}} : $*Int
51
+ //
52
+ // CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection14nocaptureStackSiyFSiycfU_
53
+
54
+ // Generate an alloc_stack that escapes into a closure while an access is
55
+ // in progress.
56
+ public func captureStackWithInoutInProgress( ) -> Int {
57
+ // Use a `var` so `x` isn't treated as a literal.
58
+ var x = 3
59
+ takeClosureAndInout ( & x) { return x }
60
+ return x
61
+ }
62
+ // CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection31captureStackWithInoutInProgressSiyF
63
+ // Dynamic access for `&x`. This must be dynamic so that we catch the conflict
64
+ // in the closure.
65
+ // CHECK-DAG: Dynamic Access: %{{.*}} = begin_access [modify] [dynamic] %{{.*}} : $*Int
66
+ // Dynamic access for `return x`. This is more conservative than it needs
67
+ // to be; it can be static.
68
+ // CHECK-DAG: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
69
+ //
70
+ // CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection31captureStackWithInoutInProgressSiyFSiycfU_
71
+ // CHECK: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
72
+
73
+ // Generate an alloc_box that escapes into a closure.
74
+ public func captureBox( ) -> Int {
75
+ var x = 3
76
+ takeEscapingClosure { x = 4 ; return x }
77
+ return x
78
+ }
79
+ // CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection10captureBoxSiyF
80
+ // Dynamic access for `return x`.
81
+ // CHECK: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
82
+ // CHECK-LABEL: _T028access_enforcement_selection10captureBoxSiyFSiycfU_
83
+
34
84
// Generate a closure in which the @inout_aliasing argument
35
85
// escapes to an @inout function `bar`.
36
86
public func recaptureStack( ) -> Int {
@@ -40,8 +90,9 @@ public func recaptureStack() -> Int {
40
90
}
41
91
// CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection14recaptureStackSiyF
42
92
//
43
- // Static access for `return x`.
44
- // CHECK: Static Access: %{{.*}} = begin_access [read] [static] %{{.*}} : $*Int
93
+ // Dynamic access for `return x`. This is more conservative than it needs
94
+ // to be; static is sufficient.
95
+ // CHECK: Dynamic Access: %{{.*}} = begin_access [read] [dynamic] %{{.*}} : $*Int
45
96
46
97
// CHECK-LABEL: Access Enforcement Selection in _T028access_enforcement_selection14recaptureStackSiyFSiycfU_
47
98
//
0 commit comments