github.com/golangci/go-tools@v0.0.0-20190318060251-af6baa5dc196/ssa/ssautil/testdata/switches.go (about) 1 // +build ignore 2 3 package 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 15 func SimpleSwitch(x, y 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 2, 3: 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 39 func four() int { return 4 } 40 41 // A non-constant case makes a switch "impure", but its pure 42 // cases form two separate switches. 43 func 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 2, 3: 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 74 func ImplicitSwitches(x, y 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 104 func 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 119 func 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") 132 L1: 133 print(1) 134 goto end 135 L2: 136 print(2) 137 end: 138 } 139 140 func 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 // } 146 loop: 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. 163 func 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 // } 169 loop: 170 print("head") 171 if x == 1 { 172 goto L1 173 } 174 if x == 2 { 175 goto L2 176 } 177 goto loop 178 L1: 179 print(1) 180 goto end 181 L2: 182 print(2) 183 end: 184 } 185 186 func 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 205 func 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 222 func 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. 240 func MakeInterfaceIsNotAConstant(x interface{}) { 241 if x == "foo" { 242 print("foo") 243 } else if x == 1 { 244 print(1) 245 } 246 } 247 248 func 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. 266 func 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. 286 func 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. 306 func 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 int, bool: 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. 326 func 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. 344 func 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 i, ok := x.(int); ok { 351 println(i) 352 } else if s, ok := x.(string); ok { 353 println(s) 354 } else { 355 print("default") 356 } 357 }