Skip to content

Commit d931c20

Browse files
committed
Fix incorrect scopes of variables declared in guard let statements
This leads to an assertion failure in IRGen. A `guard let foo = foo` statement needs to introduce a new lexical scope so the newely introduced binding can be distinguished from the one it shadows. rdar://86579287
1 parent 52d8fdf commit d931c20

File tree

4 files changed

+44
-11
lines changed

4 files changed

+44
-11
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,8 +1375,13 @@ void SILGenFunction::emitStmtCondition(StmtCondition Cond, JumpDest FalseDest,
13751375

13761376
switch (elt.getKind()) {
13771377
case StmtConditionElement::CK_PatternBinding: {
1378-
InitializationPtr initialization =
1379-
emitPatternBindingInitialization(elt.getPattern(), FalseDest);
1378+
// Begin a new binding scope, which is popped when the next innermost debug
1379+
// scope ends. The cleanup location loc isn't the perfect source location
1380+
// but it's close enough.
1381+
B.getSILGenFunction().enterDebugScope(loc,
1382+
/*isBindingScope=*/true);
1383+
InitializationPtr initialization =
1384+
emitPatternBindingInitialization(elt.getPattern(), FalseDest);
13801385

13811386
// Emit the initial value into the initialization.
13821387
FullExpr Scope(Cleanups, CleanupLocation(elt.getInitializer()));

test/DebugInfo/guard-let-scope.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ func f(c: AnyObject?) {
44
let x = c
55
// CHECK: sil_scope [[S1:[0-9]+]] { {{.*}} parent @{{.*}}1f
66
// CHECK: sil_scope [[S2:[0-9]+]] { {{.*}} parent [[S1]] }
7-
// CHECK: sil_scope [[S3:[0-9]+]] { loc "{{.*}}":[[@LINE+3]]:17 parent [[S2]] }
7+
// CHECK: sil_scope [[S3:[0-9]+]] { {{.*}} parent [[S2]] }
8+
// CHECK: sil_scope [[S4:[0-9]+]] { loc "{{.*}}":[[@LINE+3]]:17 parent [[S3]] }
89
// CHECK: debug_value %{{.*}} : $Optional<AnyObject>, let, name "x"{{.*}} scope [[S2]]
9-
// CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S3]]
10+
// CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S4]]
1011
guard let x = x else {
1112
fatalError(".")
1213
}

test/DebugInfo/guard-let-scope2.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// REQUIRES: objc_interop
2+
// RUN: %target-swift-frontend -emit-sil -Xllvm -sil-print-debuginfo %s \
3+
// RUN: | %FileCheck %s
4+
import Foundation
5+
6+
func takeClosure2 (_ closure: @escaping () -> Bool) { assert(closure()) }
7+
8+
struct SomeObject {
9+
var s = ""
10+
var today = Date()
11+
}
12+
13+
public func f(x: String?) throws {
14+
var s : SomeObject? = nil
15+
takeClosure2 {
16+
s = SomeObject()
17+
return s != nil
18+
}
19+
// CHECK: sil_scope [[S1:[0-9]+]] { {{.*}} parent @{{.*}}1f
20+
// CHECK: sil_scope [[S2:[0-9]+]] { {{.*}} parent [[S1]] }
21+
// CHECK: sil_scope [[S3:[0-9]+]] { {{.*}} parent [[S2]] }
22+
// CHECK: alloc_stack $SomeObject, let, name "s", {{.*}} scope [[S3]]
23+
guard let s = s else {
24+
assert(false)
25+
return
26+
}
27+
}

test/SILOptimizer/definite-init-wrongscope.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ public class M {
3333

3434
// CHECK-LABEL: sil [ossa] @$s3del1MC4fromAcA12WithDelegate_p_tKcfc : $@convention(method) (@in WithDelegate, @owned M) -> (@owned M, @error Error)
3535

36-
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int2, 1, loc {{.*}}:23:12, scope 5
37-
// CHECK: [[V:%.*]] = load [trivial] %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 5
38-
// CHECK: [[OR:%.*]] = builtin "or_Int2"([[V]] : $Builtin.Int2, [[I]] : $Builtin.Int2) : $Builtin.Int2, loc {{.*}}:23:12, scope 5
39-
// CHECK: store [[OR]] to [trivial] %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 5
40-
// CHECK: store %{{.*}} to [init] %{{.*}} : $*C, loc {{.*}}:26:20, scope 5
36+
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int2, 1, loc {{.*}}:23:12, scope 6
37+
// CHECK: [[V:%.*]] = load [trivial] %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 6
38+
// CHECK: [[OR:%.*]] = builtin "or_Int2"([[V]] : $Builtin.Int2, [[I]] : $Builtin.Int2) : $Builtin.Int2, loc {{.*}}:23:12, scope 6
39+
// CHECK: store [[OR]] to [trivial] %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 6
40+
// CHECK: store %{{.*}} to [init] %{{.*}} : $*C, loc {{.*}}:26:20, scope 6
4141

4242
// Make sure the dealloc_stack gets the same scope of the instructions surrounding it.
4343

44-
// CHECK: destroy_addr %0 : $*WithDelegate, loc {{.*}}:29:5, scope 5
45-
// CHECK: dealloc_stack %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 5
44+
// CHECK: destroy_addr %0 : $*WithDelegate, loc {{.*}}:29:5, scope 6
45+
// CHECK: dealloc_stack %2 : $*Builtin.Int2, loc {{.*}}:23:12, scope 6
4646
// CHECK: throw %{{.*}} : $Error, loc {{.*}}:23:12, scope 1

0 commit comments

Comments
 (0)