mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 08:40:55 +00:00 
			
		
		
		
	 f6a952599e
			
		
	
	
		f6a952599e
		
	
	
	
	
		
			
			Small change to cmd/gc to catch a "fallthrough" in the final case of a switch. R=golang-dev, rsc, mtj CC=golang-dev https://golang.org/cl/7841043
		
			
				
	
	
		
			403 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			403 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // run
 | |
| 
 | |
| // Copyright 2009 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| // Test switch statements.
 | |
| 
 | |
| package main
 | |
| 
 | |
| import "os"
 | |
| 
 | |
| func assert(cond bool, msg string) {
 | |
| 	if !cond {
 | |
| 		print("assertion fail: ", msg, "\n")
 | |
| 		panic(1)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	i5 := 5
 | |
| 	i7 := 7
 | |
| 	hello := "hello"
 | |
| 
 | |
| 	switch true {
 | |
| 	case i5 < 5:
 | |
| 		assert(false, "<")
 | |
| 	case i5 == 5:
 | |
| 		assert(true, "!")
 | |
| 	case i5 > 5:
 | |
| 		assert(false, ">")
 | |
| 	}
 | |
| 
 | |
| 	switch {
 | |
| 	case i5 < 5:
 | |
| 		assert(false, "<")
 | |
| 	case i5 == 5:
 | |
| 		assert(true, "!")
 | |
| 	case i5 > 5:
 | |
| 		assert(false, ">")
 | |
| 	}
 | |
| 
 | |
| 	switch x := 5; true {
 | |
| 	case i5 < x:
 | |
| 		assert(false, "<")
 | |
| 	case i5 == x:
 | |
| 		assert(true, "!")
 | |
| 	case i5 > x:
 | |
| 		assert(false, ">")
 | |
| 	}
 | |
| 
 | |
| 	switch x := 5; true {
 | |
| 	case i5 < x:
 | |
| 		assert(false, "<")
 | |
| 	case i5 == x:
 | |
| 		assert(true, "!")
 | |
| 	case i5 > x:
 | |
| 		assert(false, ">")
 | |
| 	}
 | |
| 
 | |
| 	switch i5 {
 | |
| 	case 0:
 | |
| 		assert(false, "0")
 | |
| 	case 1:
 | |
| 		assert(false, "1")
 | |
| 	case 2:
 | |
| 		assert(false, "2")
 | |
| 	case 3:
 | |
| 		assert(false, "3")
 | |
| 	case 4:
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		assert(true, "5")
 | |
| 	case 6:
 | |
| 		assert(false, "6")
 | |
| 	case 7:
 | |
| 		assert(false, "7")
 | |
| 	case 8:
 | |
| 		assert(false, "8")
 | |
| 	case 9:
 | |
| 		assert(false, "9")
 | |
| 	default:
 | |
| 		assert(false, "default")
 | |
| 	}
 | |
| 
 | |
| 	switch i5 {
 | |
| 	case 0, 1, 2, 3, 4:
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		assert(true, "5")
 | |
| 	case 6, 7, 8, 9:
 | |
| 		assert(false, "9")
 | |
| 	default:
 | |
| 		assert(false, "default")
 | |
| 	}
 | |
| 
 | |
| 	switch i5 {
 | |
| 	case 0:
 | |
| 	case 1:
 | |
| 	case 2:
 | |
| 	case 3:
 | |
| 	case 4:
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		assert(true, "5")
 | |
| 	case 6:
 | |
| 	case 7:
 | |
| 	case 8:
 | |
| 	case 9:
 | |
| 	default:
 | |
| 		assert(i5 == 5, "good")
 | |
| 	}
 | |
| 
 | |
| 	switch i5 {
 | |
| 	case 0:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 1:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 2:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 3:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 4:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 6:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 7:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 8:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 9:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		assert(i5 == 5, "good")
 | |
| 	}
 | |
| 
 | |
| 	fired := false
 | |
| 	switch i5 {
 | |
| 	case 0:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough // tests scoping of cases
 | |
| 	case 1:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 2:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 3:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 4:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 6:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 7:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 8:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	case 9:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		dummy := 0
 | |
| 		_ = dummy
 | |
| 		fired = !fired
 | |
| 		assert(i5 == 5, "good")
 | |
| 	}
 | |
| 	assert(fired, "fired")
 | |
| 
 | |
| 	count := 0
 | |
| 	switch i5 {
 | |
| 	case 0:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 1:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 2:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 3:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 4:
 | |
| 		count = count + 1
 | |
| 		assert(false, "4")
 | |
| 	case 5:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 6:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 7:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 8:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	case 9:
 | |
| 		count = count + 1
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		assert(i5 == count, "good")
 | |
| 	}
 | |
| 	assert(fired, "fired")
 | |
| 
 | |
| 	switch hello {
 | |
| 	case "wowie":
 | |
| 		assert(false, "wowie")
 | |
| 	case "hello":
 | |
| 		assert(true, "hello")
 | |
| 	case "jumpn":
 | |
| 		assert(false, "jumpn")
 | |
| 	default:
 | |
| 		assert(false, "default")
 | |
| 	}
 | |
| 
 | |
| 	fired = false
 | |
| 	switch i := i5 + 2; i {
 | |
| 	case i7:
 | |
| 		fired = true
 | |
| 	default:
 | |
| 		assert(false, "fail")
 | |
| 	}
 | |
| 	assert(fired, "var")
 | |
| 
 | |
| 	// switch on nil-only comparison types
 | |
| 	switch f := func() {}; f {
 | |
| 	case nil:
 | |
| 		assert(false, "f should not be nil")
 | |
| 	default:
 | |
| 	}
 | |
| 
 | |
| 	switch m := make(map[int]int); m {
 | |
| 	case nil:
 | |
| 		assert(false, "m should not be nil")
 | |
| 	default:
 | |
| 	}
 | |
| 
 | |
| 	switch a := make([]int, 1); a {
 | |
| 	case nil:
 | |
| 		assert(false, "m should not be nil")
 | |
| 	default:
 | |
| 	}
 | |
| 
 | |
| 	// switch on interface.
 | |
| 	switch i := interface{}("hello"); i {
 | |
| 	case 42:
 | |
| 		assert(false, `i should be "hello"`)
 | |
| 	case "hello":
 | |
| 		assert(true, "hello")
 | |
| 	default:
 | |
| 		assert(false, `i should be "hello"`)
 | |
| 	}
 | |
| 
 | |
| 	// switch on implicit bool converted to interface
 | |
| 	// was broken: see issue 3980
 | |
| 	switch i := interface{}(true); {
 | |
| 	case i:
 | |
| 		assert(true, "true")
 | |
| 	case false:
 | |
| 		assert(false, "i should be true")
 | |
| 	default:
 | |
| 		assert(false, "i should be true")
 | |
| 	}
 | |
| 
 | |
| 	// switch on interface with constant cases differing by type.
 | |
| 	// was rejected by compiler: see issue 4781
 | |
| 	type T int
 | |
| 	type B bool
 | |
| 	type F float64
 | |
| 	type S string
 | |
| 	switch i := interface{}(float64(1.0)); i {
 | |
| 	case nil:
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case (*int)(nil):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case 1:
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case T(1):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case F(1.0):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case 1.0:
 | |
| 		assert(true, "true")
 | |
| 	case "hello":
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case S("hello"):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case true, B(false):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	case false, B(true):
 | |
| 		assert(false, "i should be float64(1.0)")
 | |
| 	}
 | |
| 
 | |
| 	// switch on array.
 | |
| 	switch ar := [3]int{1, 2, 3}; ar {
 | |
| 	case [3]int{1, 2, 3}:
 | |
| 		assert(true, "[1 2 3]")
 | |
| 	case [3]int{4, 5, 6}:
 | |
| 		assert(false, "ar should be [1 2 3]")
 | |
| 	default:
 | |
| 		assert(false, "ar should be [1 2 3]")
 | |
| 	}
 | |
| 
 | |
| 	// switch on channel
 | |
| 	switch c1, c2 := make(chan int), make(chan int); c1 {
 | |
| 	case nil:
 | |
| 		assert(false, "c1 did not match itself")
 | |
| 	case c2:
 | |
| 		assert(false, "c1 did not match itself")
 | |
| 	case c1:
 | |
| 		assert(true, "chan")
 | |
| 	default:
 | |
| 		assert(false, "c1 did not match itself")
 | |
| 	}
 | |
| 
 | |
| 	// empty switch
 | |
| 	switch {
 | |
| 	}
 | |
| 
 | |
| 	// empty switch with default case.
 | |
| 	fired = false
 | |
| 	switch {
 | |
| 	default:
 | |
| 		fired = true
 | |
| 	}
 | |
| 	assert(fired, "fail")
 | |
| 
 | |
| 	// Default and fallthrough.
 | |
| 	count = 0
 | |
| 	switch {
 | |
| 	default:
 | |
| 		count++
 | |
| 		fallthrough
 | |
| 	case false:
 | |
| 		count++
 | |
| 	}
 | |
| 	assert(count == 2, "fail")
 | |
| 
 | |
| 	// fallthrough to default, which is not at end.
 | |
| 	count = 0
 | |
| 	switch i5 {
 | |
| 	case 5:
 | |
| 		count++
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		count++
 | |
| 	case 6:
 | |
| 		count++
 | |
| 	}
 | |
| 	assert(count == 2, "fail")
 | |
| 
 | |
| 	i := 0
 | |
| 	switch x := 5; {
 | |
| 	case i < x:
 | |
| 		os.Exit(0)
 | |
| 	case i == x:
 | |
| 	case i > x:
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| }
 |