GoPLS Viewer

Home|gopls/go/ssa/ssautil/testdata/switches.go
1// +build ignore
2
3package main
4
5// This file is the input to TestSwitches in switch_test.go.
6// Each multiway conditional with constant or type cases (Switch)
7// discovered by Switches is printed, and compared with the
8// comments.
9//
10// The body of each case is printed as the value of its first
11// instruction.
12
13// -------- Value switches --------
14
15func SimpleSwitch(xy int) {
16    // switch x {
17    // case 1:int: print(1:int)
18    // case 2:int: print(23:int)
19    // case 3:int: print(23:int)
20    // case 4:int: print(3:int)
21    // default: x == y
22    // }
23    switch x {
24    case 1:
25        print(1)
26    case 23:
27        print(23)
28        fallthrough
29    case 4:
30        print(3)
31    default:
32        print(4)
33    case y:
34        print(5)
35    }
36    print(6)
37}
38
39func four() int { return 4 }
40
41// A non-constant case makes a switch "impure", but its pure
42// cases form two separate switches.
43func SwitchWithNonConstantCase(x int) {
44    // switch x {
45    // case 1:int: print(1:int)
46    // case 2:int: print(23:int)
47    // case 3:int: print(23:int)
48    // default: four()
49    // }
50
51    // switch x {
52    // case 5:int: print(5:int)
53    // case 6:int: print(6:int)
54    // default: print("done":string)
55    // }
56    switch x {
57    case 1:
58        print(1)
59    case 23:
60        print(23)
61    case four():
62        print(3)
63    case 5:
64        print(5)
65    case 6:
66        print(6)
67    }
68    print("done")
69}
70
71// Switches may be found even where the source
72// program doesn't have a switch statement.
73
74func ImplicitSwitches(xy int) {
75    // switch x {
76    // case 1:int: print(12:int)
77    // case 2:int: print(12:int)
78    // default: x < 5:int
79    // }
80    if x == 1 || 2 == x || x < 5 {
81        print(12)
82    }
83
84    // switch x {
85    // case 3:int: print(34:int)
86    // case 4:int: print(34:int)
87    // default: x == y
88    // }
89    if x == 3 || 4 == x || x == y {
90        print(34)
91    }
92
93    // Not a switch: no consistent variable.
94    if x == 5 || y == 6 {
95        print(56)
96    }
97
98    // Not a switch: only one constant comparison.
99    if x == 7 || x == y {
100        print(78)
101    }
102}
103
104func IfElseBasedSwitch(x int) {
105    // switch x {
106    // case 1:int: print(1:int)
107    // case 2:int: print(2:int)
108    // default: print("else":string)
109    // }
110    if x == 1 {
111        print(1)
112    } else if x == 2 {
113        print(2)
114    } else {
115        print("else")
116    }
117}
118
119func GotoBasedSwitch(x int) {
120    // switch x {
121    // case 1:int: print(1:int)
122    // case 2:int: print(2:int)
123    // default: print("else":string)
124    // }
125    if x == 1 {
126        goto L1
127    }
128    if x == 2 {
129        goto L2
130    }
131    print("else")
132L1:
133    print(1)
134    goto end
135L2:
136    print(2)
137end:
138}
139
140func SwitchInAForLoop(x int) {
141    // switch x {
142    // case 1:int: print(1:int)
143    // case 2:int: print(2:int)
144    // default: print("head":string)
145    // }
146loop:
147    for {
148        print("head")
149        switch x {
150        case 1:
151            print(1)
152            break loop
153        case 2:
154            print(2)
155            break loop
156        }
157    }
158}
159
160// This case is a switch in a for-loop, both constructed using goto.
161// As before, the default case points back to the block containing the
162// switch, but that's ok.
163func SwitchInAForLoopUsingGoto(x int) {
164    // switch x {
165    // case 1:int: print(1:int)
166    // case 2:int: print(2:int)
167    // default: print("head":string)
168    // }
169loop:
170    print("head")
171    if x == 1 {
172        goto L1
173    }
174    if x == 2 {
175        goto L2
176    }
177    goto loop
178L1:
179    print(1)
180    goto end
181L2:
182    print(2)
183end:
184}
185
186func UnstructuredSwitchInAForLoop(x int) {
187    // switch x {
188    // case 1:int: print(1:int)
189    // case 2:int: x == 1:int
190    // default: print("end":string)
191    // }
192    for {
193        if x == 1 {
194            print(1)
195            return
196        }
197        if x == 2 {
198            continue
199        }
200        break
201    }
202    print("end")
203}
204
205func CaseWithMultiplePreds(x int) {
206    for {
207        if x == 1 {
208            print(1)
209            return
210        }
211    loop:
212        // This block has multiple predecessors,
213        // so can't be treated as a switch case.
214        if x == 2 {
215            goto loop
216        }
217        break
218    }
219    print("end")
220}
221
222func DuplicateConstantsAreNotEliminated(x int) {
223    // switch x {
224    // case 1:int: print(1:int)
225    // case 1:int: print("1a":string)
226    // case 2:int: print(2:int)
227    // default: return
228    // }
229    if x == 1 {
230        print(1)
231    } else if x == 1 { // duplicate => unreachable
232        print("1a")
233    } else if x == 2 {
234        print(2)
235    }
236}
237
238// Interface values (created by comparisons) are not constants,
239// so ConstSwitch.X is never of interface type.
240func MakeInterfaceIsNotAConstant(x interface{}) {
241    if x == "foo" {
242        print("foo")
243    } else if x == 1 {
244        print(1)
245    }
246}
247
248func ZeroInitializedVarsAreConstants(x int) {
249    // switch x {
250    // case 0:int: print(1:int)
251    // case 2:int: print(2:int)
252    // default: print("end":string)
253    // }
254    var zero int // SSA construction replaces zero with 0
255    if x == zero {
256        print(1)
257    } else if x == 2 {
258        print(2)
259    }
260    print("end")
261}
262
263// -------- Select --------
264
265// NB, potentially fragile reliance on register number.
266func SelectDesugarsToSwitch(ch chan int) {
267    // switch t1 {
268    // case 0:int: extract t0 #2
269    // case 1:int: println(0:int)
270    // case 2:int: println(1:int)
271    // default: println("default":string)
272    // }
273    select {
274    case x := <-ch:
275        println(x)
276    case <-ch:
277        println(0)
278    case ch <- 1:
279        println(1)
280    default:
281        println("default")
282    }
283}
284
285// NB, potentially fragile reliance on register number.
286func NonblockingSelectDefaultCasePanics(ch chan int) {
287    // switch t1 {
288    // case 0:int: extract t0 #2
289    // case 1:int: println(0:int)
290    // case 2:int: println(1:int)
291    // default: make interface{} <- string ("blocking select m...":string)
292    // }
293    select {
294    case x := <-ch:
295        println(x)
296    case <-ch:
297        println(0)
298    case ch <- 1:
299        println(1)
300    }
301}
302
303// -------- Type switches --------
304
305// NB, reliance on fragile register numbering.
306func SimpleTypeSwitch(x interface{}) {
307    // switch x.(type) {
308    // case t3 int: println(x)
309    // case t7 bool: println(x)
310    // case t10 string: println(t10)
311    // default: println(x)
312    // }
313    switch y := x.(type) {
314    case nil:
315        println(y)
316    case intbool:
317        println(y)
318    case string:
319        println(y)
320    default:
321        println(y)
322    }
323}
324
325// NB, potentially fragile reliance on register number.
326func DuplicateTypesAreNotEliminated(x interface{}) {
327    // switch x.(type) {
328    // case t1 string: println(1:int)
329    // case t5 interface{}: println(t5)
330    // case t9 int: println(3:int)
331    // default: return
332    // }
333    switch y := x.(type) {
334    case string:
335        println(1)
336    case interface{}:
337        println(y)
338    case int:
339        println(3// unreachable!
340    }
341}
342
343// NB, potentially fragile reliance on register number.
344func AdHocTypeSwitch(x interface{}) {
345    // switch x.(type) {
346    // case t1 int: println(t1)
347    // case t5 string: println(t5)
348    // default: print("default":string)
349    // }
350    if iok := x.(int); ok {
351        println(i)
352    } else if sok := x.(string); ok {
353        println(s)
354    } else {
355        print("default")
356    }
357}
358
MembersX
SimpleSwitch
SimpleSwitch.y
SwitchWithNonConstantCase
UnstructuredSwitchInAForLoop
NonblockingSelectDefaultCasePanics.ch
SimpleSwitch.x
ZeroInitializedVarsAreConstants.zero
SimpleTypeSwitch
MakeInterfaceIsNotAConstant.x
ZeroInitializedVarsAreConstants.x
SwitchWithNonConstantCase.x
ImplicitSwitches.x
GotoBasedSwitch.x
UnstructuredSwitchInAForLoop.x
MakeInterfaceIsNotAConstant
ImplicitSwitches
DuplicateConstantsAreNotEliminated.x
AdHocTypeSwitch
SelectDesugarsToSwitch.ch
SimpleTypeSwitch.x
AdHocTypeSwitch.x
IfElseBasedSwitch
SwitchInAForLoop
CaseWithMultiplePreds
CaseWithMultiplePreds.x
SelectDesugarsToSwitch
GotoBasedSwitch
SwitchInAForLoopUsingGoto
DuplicateTypesAreNotEliminated.x
DuplicateTypesAreNotEliminated
DuplicateConstantsAreNotEliminated
ZeroInitializedVarsAreConstants
SelectDesugarsToSwitch.BlockStmt.x
NonblockingSelectDefaultCasePanics
NonblockingSelectDefaultCasePanics.BlockStmt.x
four
ImplicitSwitches.y
IfElseBasedSwitch.x
SwitchInAForLoop.x
SwitchInAForLoopUsingGoto.x
Members
X