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  }