mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* [SILGenFunction] Don't create redundant nested debug scopes
Instead of emitting:
```
sil_scope 4 { loc "main.swift":6:19 parent 3 }
sil_scope 5 { loc "main.swift":7:3 parent 4 }
sil_scope 6 { loc "main.swift":7:3 parent 5 }
sil_scope 7 { loc "main.swift":7:3 parent 5 }
sil_scope 8 { loc "main.swift":9:5 parent 4 }
```
Emit:
```
sil_scope 4 { loc "main.swift":6:19 parent 3 }
sil_scope 5 { loc "main.swift":7:3 parent 4 }
sil_scope 6 { loc "main.swift":9:5 parent 5 }
```
* [IRGenSIL] Diagnose conflicting shadow copies
If we attempt to store a value with the wrong type into a slot reserved
for a shadow copy, diagnose what went wrong.
* [SILGenPattern] Defer debug description of case variables
Create unique nested debug scopes for a switch, each of its case labels,
and each of its case bodies. This looks like:
```
switch ... { // Enter scope 1.
case ... : // Enter scope 2, nested within scope 1.
<body-1> // Enter scope 3, nested within scope 2.
case ... : // Enter scope 4, nested within scope 1.
<body-2> // Enter scope 5, nested within scope 4.
}
```
Use the new scope structure to defer emitting debug descriptions of case
bindings. Specifically, defer the work until we can nest the scope for a
case body under the scope for a pattern match.
This fixes SR-7973, a problem where it was impossible to inspect a case
binding in lldb when stopped at a case with multiple items.
Previously, we would emit the debug descriptions too early (in the
pattern match), leading to duplicate/conflicting descriptions. The only
reason that the ambiguous description was allowed to compile was because
the debug scopes were nested incorrectly.
rdar://41048339
* Update tests
101 lines
2.5 KiB
Swift
101 lines
2.5 KiB
Swift
// RUN: %target-swift-emit-silgen -g -Xllvm -sil-print-debuginfo %s | %FileCheck %s
|
|
|
|
func nop1() {}
|
|
func nop2() {}
|
|
|
|
enum Binary {
|
|
case On
|
|
case Off
|
|
}
|
|
|
|
func isOn(_ b: Binary) -> Bool {
|
|
return b == .On
|
|
}
|
|
|
|
// CHECK: [[LOC:loc "[^"]+"]]
|
|
|
|
// First, check that we don't assign fresh locations to each case statement,
|
|
// except for any relevant debug value instructions.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s16switch_debuginfo5test11iySi_tF
|
|
func test1(i: Int) {
|
|
switch i {
|
|
case 0: // CHECK-NOT: [[LOC]]:[[@LINE]]
|
|
nop1()
|
|
|
|
case 1: // CHECK-NOT: [[LOC]]:[[@LINE]]
|
|
nop1()
|
|
|
|
default: // CHECK-NOT: [[LOC]]:[[@LINE]]
|
|
nop1()
|
|
}
|
|
}
|
|
|
|
// Next, check that case statements and switch subjects have the same locations.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s16switch_debuginfo5test21sySS_tF
|
|
func test2(s: String) {
|
|
switch s {
|
|
case "a": // CHECK: string_literal utf8 "a", [[LOC]]:[[@LINE-1]]:10
|
|
nop1()
|
|
case "b": // CHECK: string_literal utf8 "b", [[LOC]]:[[@LINE-3]]:10
|
|
nop2()
|
|
default:
|
|
nop1()
|
|
}
|
|
}
|
|
|
|
// Fallthrough shouldn't affect case statement locations.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s16switch_debuginfo5test31sySS_tF
|
|
func test3(s: String) {
|
|
switch s {
|
|
case "a", "b":
|
|
// CHECK: string_literal utf8 "a", [[LOC]]:[[@LINE-2]]:10
|
|
// CHECK: string_literal utf8 "b", [[LOC]]:[[@LINE-3]]:10
|
|
nop1()
|
|
fallthrough
|
|
case "b", "c":
|
|
// CHECK: string_literal utf8 "b", [[LOC]]:[[@LINE-7]]:10
|
|
// CHECK: string_literal utf8 "c", [[LOC]]:[[@LINE-8]]:10
|
|
nop2()
|
|
fallthrough
|
|
default:
|
|
nop1()
|
|
}
|
|
}
|
|
|
|
// It should be possible to set breakpoints on where clauses.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s16switch_debuginfo5test41byAA6BinaryO_tF
|
|
func test4(b: Binary) {
|
|
switch b {
|
|
case let _ // CHECK-NOT: [[LOC]]:[[@LINE]]
|
|
where isOn(b): // CHECK: [[LOC]]:[[@LINE]]:11
|
|
nop1()
|
|
case let _ // CHECK-NOT: [[LOC]]:[[@LINE]]
|
|
where !isOn(b): // CHECK: [[LOC]]:[[@LINE]]:11
|
|
nop2()
|
|
default:
|
|
nop1()
|
|
}
|
|
}
|
|
|
|
// Check that we set the right locations before/after nested switches.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s16switch_debuginfo5test51sySS_tF
|
|
func test5(s: String) {
|
|
switch s {
|
|
case "a": // CHECK: string_literal utf8 "a", [[LOC]]:[[@LINE-1]]:10
|
|
switch "b" {
|
|
case "b": // CHECK: string_literal utf8 "b", [[LOC]]:[[@LINE-1]]:12
|
|
nop1()
|
|
default:
|
|
nop2()
|
|
}
|
|
if "c" == "c" { // CHECK: string_literal utf8 "c", [[LOC]]:[[@LINE]]
|
|
nop1()
|
|
}
|
|
default:
|
|
nop1()
|
|
}
|
|
if "d" == "d" { // CHECK: string_literal utf8 "d", [[LOC]]:[[@LINE]]
|
|
nop1()
|
|
}
|
|
}
|