Files
swift-mirror/test/SILGen/switch_debuginfo.swift
Vedant Kumar 60ec3f1b90 Fix debug description for cases with multiple items (#32282)
* [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
2020-06-10 13:31:10 -07:00

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()
}
}