1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
// Some fake predicates for pattern guards.
func runced() -> Bool { return true }
func funged() -> Bool { return true }
func ansed() -> Bool { return true }
func foo() -> Int { return 0 }
func bar() -> Int { return 0 }
func a() {}
func b() {}
func c() {}
func d() {}
func e() {}
func f() {}
func g() {}
func z(_ i: Int) {}
// CHECK-LABEL: sil hidden [ossa] @$s18switch_fallthrough5test1yyF
func test1() {
switch foo() {
// CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], {{bb[0-9]+}}
// CHECK: [[YES_CASE1]]:
case foo():
// CHECK: function_ref @$s18switch_fallthrough1ayyF
// CHECK: br [[CASE2:bb[0-9]+]]
a()
fallthrough
case bar():
// CHECK: [[CASE2]]:
// CHECK: function_ref @$s18switch_fallthrough1byyF
// CHECK: br [[CASE3:bb[0-9]+]]
b()
fallthrough
case _:
// CHECK: [[CASE3]]:
// CHECK: function_ref @$s18switch_fallthrough1cyyF
c()
}
// CHECK: function_ref @$s18switch_fallthrough1dyyF
d()
}
// Fallthrough should work even if the next case is normally unreachable
// CHECK-LABEL: sil hidden [ossa] @$s18switch_fallthrough5test2yyF
func test2() {
switch foo() {
// CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], {{bb[0-9]+}}
// CHECK: [[YES_CASE1]]:
case foo():
// CHECK: function_ref @$s18switch_fallthrough1ayyF
// CHECK: br [[CASE2:bb[0-9]+]]
a()
fallthrough
case _:
// CHECK: [[CASE2]]:
// CHECK: function_ref @$s18switch_fallthrough1byyF
// CHECK: br [[CASE3:bb[0-9]+]]
b()
fallthrough
case _:
// CHECK: [[CASE3]]:
// CHECK: function_ref @$s18switch_fallthrough1cyyF
c()
}
// CHECK: function_ref @$s18switch_fallthrough1dyyF
d()
}
// CHECK-LABEL: sil hidden [ossa] @$s18switch_fallthrough5test3yyF
func test3() {
switch (foo(), bar()) {
// CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], {{bb[0-9]+}}
// CHECK: [[YES_CASE1]]:
case (foo(), bar()):
// CHECK: function_ref @$s18switch_fallthrough1ayyF
// CHECK: br [[CASE2:bb[0-9]+]]
a()
fallthrough
case (foo(), _):
// CHECK: [[CASE2]]:
// CHECK: function_ref @$s18switch_fallthrough1byyF
// CHECK: br [[CASE3:bb[0-9]+]]
b()
fallthrough
case (_, _):
// CHECK: [[CASE3]]:
// CHECK: function_ref @$s18switch_fallthrough1cyyF
// CHECK: br [[CASE4:bb[0-9]+]]
c()
fallthrough
case (_, _):
// CHECK: [[CASE4]]:
// CHECK: function_ref @$s18switch_fallthrough1dyyF
d()
}
// CHECK: function_ref @$s18switch_fallthrough1eyyF
e()
}
// Fallthrough should clean up nested pattern variables from the exited scope.
func test4() {
switch (foo(), bar()) {
// CHECK: [[A:%.*]] = alloc_box ${ var (Int, Int) }
// CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], {{bb[0-9]+}}
case var a where runced():
// CHECK: [[CASE1]]:
// CHECK: br [[CASE2:bb[0-9]+]]
fallthrough
case _ where funged():
// CHECK: [[CASE2]]:
// CHECK: br [[CONT:bb[0-9]+]]
()
// CHECK: [[B:%.*]] = alloc_box ${ var Int }
// CHECK: [[C:%.*]] = alloc_box ${ var Int }
// CHECK: cond_br {{%.*}}, [[CASE4:bb[0-9]+]],
case (var b, var c) where ansed():
// CHECK: [[CASE4]]:
// CHECK: br [[CASE5:bb[0-9]+]]
fallthrough
case _:
// CHECK: [[CASE5]]:
// CHECK: br [[CONT]]
()
}
// CHECK: [[CONT]]:
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
}
// Fallthrough into case block with binding // CHECK-LABEL: sil hidden [ossa] @$s18switch_fallthrough5test5yyF
func test5() {
switch (foo(), bar()) {
// CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], {{bb[0-9]+}}
// CHECK: [[YES_CASE1]]:
case (var n, foo()):
// Check that the var is boxed and unboxed and the final value is the one that falls through into the next case
// CHECK: [[BOX:%.*]] = alloc_box ${ var Int }, var, name "n"
// CHECK: [[N_LIFETIME:%.*]] = begin_borrow [var_decl] [[BOX]]
// CHECK: [[N_BOX:%.*]] = project_box [[N_LIFETIME]] : ${ var Int }, 0
// CHECK: function_ref @$s18switch_fallthrough1ayyF
// CHECK: [[N:%.*]] = load [trivial] [[N_BOX]] : $*Int
// CHECK: destroy_value [[BOX]] : ${ var Int }
// CHECK: br [[CASE2:bb[0-9]+]]([[N]] : $Int)
a()
fallthrough
case (foo(), let n):
// CHECK: cond_br {{%.*}}, [[YES_SECOND_CONDITION:bb[0-9]+]], {{bb[0-9]+}}
// CHECK: [[YES_SECOND_CONDITION]]:
// CHECK: br [[CASE2]]([[SECOND_N:%.*]] : $Int)
// CHECK: [[CASE2]]([[INCOMING_N:%.*]] : $Int):
// CHECK: debug_value [[INCOMING_N]] : $Int, let, name "n"
// CHECK: [[Z:%.*]] = function_ref @$s18switch_fallthrough1zyySiF
// CHECK: apply [[Z]]([[INCOMING_N]]) : $@convention(thin) (Int) -> ()
// CHECK: br [[CONT:bb[0-9]+]]
z(n)
case (_, _):
break
}
// CHECK: [[CONT]]:
// CHECK: function_ref @$s18switch_fallthrough1eyyF
e()
}
// rdar://problem/67704651 - crash due to nested fallthrough
func testNestedFallthrough(x: (Int, String), y: (Int, Int)) {
switch x {
case (17, let s):
switch y {
case (42, let i):
print("the answer")
default:
print("nope")
}
fallthrough
case (42, let s):
print("42 and \(s)")
default:
print("done")
}
}
|