@@ -67,6 +67,8 @@ public struct InlineInt {
67
67
}
68
68
sil @globalAddress : $@convention(thin) () -> Builtin.RawPointer
69
69
sil @addressInt : $@convention(thin) (@in_guaranteed InlineInt) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
70
+ sil @addressOfInt : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow address 0) @owned Span<Int>
71
+ sil @noAddressInt : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow 0) @owned Span<Int>
70
72
sil @useSpan : $@convention(thin) (@guaranteed Span<Int>) -> ()
71
73
72
74
// Test returning a owned dependence on a trivial value
@@ -259,10 +261,12 @@ bb0(%0 : $*NE, %1 : $*Holder):
259
261
// extends to the dealloc_stack.
260
262
//
261
263
// SILGen should never generate temporary stack copies for addressable dependencies, but we need to diagnose them anyway
262
- // so that a SILGen bug does not become a miscompile.
264
+ // so that a SILGen bug does not become a miscompile. Furthermore, LifetimeDependenceScopeFixup now automatically
265
+ // extends such local allocations, so this diagnostic only fires on source-level tests when scope extension is
266
+ // impossible.
263
267
//
264
268
// rdar://159680262 ([nonescapable] diagnose dependence on a temporary copy of a global array)
265
- sil hidden [noinline] [ossa] @testTrivialStackCopy : $@convention(thin) () -> () {
269
+ sil hidden [noinline] [ossa] @testTempTrivialStackCopy : $@convention(thin) () -> () {
266
270
bb0:
267
271
%0 = function_ref @globalAddress : $@convention(thin) () -> Builtin.RawPointer
268
272
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
@@ -287,3 +291,64 @@ bb0:
287
291
%18 = tuple ()
288
292
return %18
289
293
}
294
+
295
+ // Test an address dependency on a trivial value temporarily copied to the stack. The value's addressable range only
296
+ // extends to the dealloc_stack. This represents the SIL from @testTempTrivialStackCopy after
297
+ // LifetimeDependenceScopeFixup has extended the local allocation.
298
+ sil hidden [noinline] [ossa] @testExtendedTrivialStackCopy : $@convention(thin) () -> () {
299
+ bb0:
300
+ %0 = function_ref @globalAddress : $@convention(thin) () -> Builtin.RawPointer
301
+ %1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
302
+ %2 = pointer_to_address %1 to [strict] $*InlineInt
303
+ %3 = begin_access [read] [dynamic] %2
304
+ %4 = load [trivial] %3
305
+ end_access %3
306
+ %6 = alloc_stack $InlineInt
307
+ store %4 to [trivial] %6
308
+
309
+ %8 = function_ref @addressInt : $@convention(thin) (@in_guaranteed InlineInt) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
310
+ %9 = apply %8(%6) : $@convention(thin) (@in_guaranteed InlineInt) -> @lifetime(borrow address_for_deps 0) @owned Span<Int>
311
+ %10 = mark_dependence [unresolved] %9 on %6
312
+ %11 = move_value [var_decl] %10
313
+ %13 = begin_borrow %11
314
+
315
+ %14 = function_ref @useSpan : $@convention(thin) (@guaranteed Span<Int>) -> ()
316
+ %15 = apply %14(%13) : $@convention(thin) (@guaranteed Span<Int>) -> ()
317
+ end_borrow %13
318
+ destroy_value %11
319
+ dealloc_stack %6
320
+ %18 = tuple ()
321
+ return %18
322
+ }
323
+
324
+ // Test two address dependencies on the same temporay. The first dependency is addressable; it's uses are covered by the
325
+ // stack allocation. The second dependency is non-addressable; it's uses are not covered by the stack allocation. So,
326
+ // this is correct SIL but is falsely diagnosed as a lifetime error. This conservative error is fine because SILGen
327
+ // never reuses a temporary allocaiton for both an addressable and non-addressable dependency.
328
+ sil hidden [noinline] [ossa] @testFalseTempTrivialStackCopy : $@convention(thin) (Int) -> () {
329
+ bb0(%0: $Int):
330
+ %1 = alloc_stack $Int
331
+ store %0 to [trivial] %1
332
+
333
+ %3 = function_ref @addressOfInt : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow address 0) @owned Span<Int>
334
+ %4 = apply %3(%1) : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow address 0) @owned Span<Int>
335
+ %5 = mark_dependence [unresolved] %4 on %1
336
+ %6 = move_value [var_decl] %5
337
+ destroy_value %6
338
+
339
+ %8 = function_ref @noAddressInt : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow 0) @owned Span<Int>
340
+ %9 = apply %8(%1) : $@convention(thin) (@in_guaranteed Int) -> @lifetime(borrow 0) @owned Span<Int>
341
+ %10 = mark_dependence [unresolved] %9 on %1
342
+ %11 = move_value [var_decl] %10 // expected-error{{lifetime-dependent value escapes its scope}}
343
+ // expected-note@-15{{it depends on the lifetime of an argument of 'testFalseTempTrivialStackCopy'}}
344
+
345
+ dealloc_stack %1
346
+
347
+ %13 = begin_borrow %11
348
+ %14 = function_ref @useSpan : $@convention(thin) (@guaranteed Span<Int>) -> ()
349
+ %15 = apply %14(%13) : $@convention(thin) (@guaranteed Span<Int>) -> ()
350
+ end_borrow %13
351
+ destroy_value %11 // expected-note{{this use of the lifetime-dependent value is out of scope}}
352
+ %18 = tuple ()
353
+ return %18
354
+ }
0 commit comments