diff options
author | Dan Willemsen <dwillemsen@google.com> | 2018-02-27 19:36:27 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2018-02-27 19:36:27 -0800 |
commit | e1b3b188ff03c41213dca621c46c39702d79f3ee (patch) | |
tree | 67ab03d7ee51c5fafa1602c28e0d9033a8e3f26d /test | |
parent | 3c27c3f6c42dbb890c67820f2897812e16f01be1 (diff) | |
download | platform_prebuilts_go_linux-x86-e1b3b188ff03c41213dca621c46c39702d79f3ee.tar.gz platform_prebuilts_go_linux-x86-e1b3b188ff03c41213dca621c46c39702d79f3ee.tar.bz2 platform_prebuilts_go_linux-x86-e1b3b188ff03c41213dca621c46c39702d79f3ee.zip |
Update prebuilts to go1.10 ab/4625579android-wear-p-preview-2android-p-preview-5android-p-preview-4android-p-preview-3android-p-preview-2android-p-preview-1android-o-mr1-iot-release-1.0.2android-o-mr1-iot-release-1.0.1android-o-mr1-iot-release-1.0.0android-o-mr1-iot-preview-8android-o-mr1-iot-preview-7android-n-iot-release-smart-display-r2android-n-iot-release-smart-displayandroid-n-iot-release-polk-at1android-n-iot-release-lg-thinq-wk7o-mr1-iot-preview-8o-mr1-iot-preview-7
Test: m -j blueprint_tools
Change-Id: I12d0286a2978fcbafa50880625700ba69c4581d8
Diffstat (limited to 'test')
115 files changed, 2576 insertions, 158 deletions
diff --git a/test/chan/sendstmt.go b/test/chan/sendstmt.go index c0f1a29f..d296a55c 100644 --- a/test/chan/sendstmt.go +++ b/test/chan/sendstmt.go @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file. // Test various parsing cases that are a little -// different now that send is a statement, not a expression. +// different now that send is a statement, not an expression. package main diff --git a/test/chancap.go b/test/chancap.go index b3e40233..b08478a1 100644 --- a/test/chancap.go +++ b/test/chancap.go @@ -8,8 +8,17 @@ package main +import ( + "strings" + "unsafe" +) + +type T chan int + +const ptrSize = unsafe.Sizeof((*byte)(nil)) + func main() { - c := make(chan int, 10) + c := make(T, 10) if len(c) != 0 || cap(c) != 10 { println("chan len/cap ", len(c), cap(c), " want 0 10") panic("fail") @@ -23,9 +32,39 @@ func main() { panic("fail") } - c = make(chan int) + c = make(T) if len(c) != 0 || cap(c) != 0 { println("chan len/cap ", len(c), cap(c), " want 0 0") panic("fail") } + + n := -1 + shouldPanic("makechan: size out of range", func() { _ = make(T, n) }) + shouldPanic("makechan: size out of range", func() { _ = make(T, int64(n)) }) + if ptrSize == 8 { + n = 1 << 20 + n <<= 20 + shouldPanic("makechan: size out of range", func() { _ = make(T, n) }) + n <<= 20 + shouldPanic("makechan: size out of range", func() { _ = make(T, n) }) + } else { + n = 1<<31 - 1 + shouldPanic("makechan: size out of range", func() { _ = make(T, n) }) + shouldPanic("makechan: size out of range", func() { _ = make(T, int64(n)) }) + } +} + +func shouldPanic(str string, f func()) { + defer func() { + err := recover() + if err == nil { + panic("did not panic") + } + s := err.(error).Error() + if !strings.Contains(s, str) { + panic("got panic " + s + ", want " + str) + } + }() + + f() } diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go new file mode 100644 index 00000000..43643431 --- /dev/null +++ b/test/closure3.dir/main.go @@ -0,0 +1,283 @@ +// Copyright 2017 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. + +// Check correctness of various closure corner cases that +// that are expected to be inlined + +package main + +var ok bool +var sink int + +func main() { + { + if x := func() int { // ERROR "can inline main.func1" + return 1 + }(); x != 1 { // ERROR "inlining call to main.func1" + panic("x != 1") + } + if x := func() int { // ERROR "can inline main.func2" "func literal does not escape" + return 1 + }; x() != 1 { // ERROR "inlining call to main.func2" + panic("x() != 1") + } + } + + { + if y := func(x int) int { // ERROR "can inline main.func3" + return x + 2 + }(40); y != 42 { // ERROR "inlining call to main.func3" + panic("y != 42") + } + if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape" + return x + 2 + }; y(40) != 42 { // ERROR "inlining call to main.func4" + panic("y(40) != 42") + } + } + + { + y := func(x int) int { // ERROR "can inline main.func5" "func literal does not escape" + return x + 2 + } + y = func(x int) int { // ERROR "can inline main.func6" "func literal does not escape" + return x + 1 + } + if y(40) != 41 { + panic("y(40) != 41") + } + } + + { + func() { // ERROR "func literal does not escape" + y := func(x int) int { // ERROR "can inline main.func7.1" "func literal does not escape" + return x + 2 + } + y = func(x int) int { // ERROR "can inline main.func7.2" "func literal does not escape" + return x + 1 + } + if y(40) != 41 { + panic("y(40) != 41") + } + }() + } + + { + y := func(x int) int { // ERROR "can inline main.func8" "func literal does not escape" + return x + 2 + } + y, sink = func(x int) int { // ERROR "can inline main.func9" "func literal does not escape" + return x + 1 + }, 42 + if y(40) != 41 { + panic("y(40) != 41") + } + } + + { + func() { // ERROR "func literal does not escape" + y := func(x int) int { // ERROR "can inline main.func10.1" "func literal does not escape" + return x + 2 + } + y, sink = func(x int) int { // ERROR "can inline main.func10.2" "func literal does not escape" + return x + 1 + }, 42 + if y(40) != 41 { + panic("y(40) != 41") + } + }() + } + + { + y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape" + return x + 2 + } + y, sink = func() (func(int)int, int) { // ERROR "func literal does not escape" + return func(x int) int { // ERROR "can inline main.func12" "func literal escapes" + return x + 1 + }, 42 + }() + if y(40) != 41 { + panic("y(40) != 41") + } + } + + { + func() { // ERROR "func literal does not escape" + y := func(x int) int { // ERROR "can inline main.func13.1" "func literal does not escape" + return x + 2 + } + y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape" + return func(x int) int { // ERROR "can inline main.func13.2" "func literal escapes" + return x + 1 + }, 42 + }() + if y(40) != 41 { + panic("y(40) != 41") + } + }() + } + + { + y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape" + return x + 2 + } + y, ok = map[int]func(int)int { // ERROR "does not escape" + 0: func (x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes" + }[0] + if y(40) != 41 { + panic("y(40) != 41") + } + } + + { + func() { // ERROR "func literal does not escape" + y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape" + return x + 2 + } + y, ok = map[int]func(int) int{// ERROR "does not escape" + 0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes" + }[0] + if y(40) != 41 { + panic("y(40) != 41") + } + }() + } + + { + y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape" + return x + 2 + } + y, ok = interface{}(func (x int) int { // ERROR "can inline main.func18" "does not escape" + return x + 1 + }).(func(int)int) + if y(40) != 41 { + panic("y(40) != 41") + } + } + + { + func() { // ERROR "func literal does not escape" + y := func(x int) int { // ERROR "can inline main.func19.1" "func literal does not escape" + return x + 2 + } + y, ok = interface{}(func(x int) int { // ERROR "can inline main.func19.2" "does not escape" + return x + 1 + }).(func(int) int) + if y(40) != 41 { + panic("y(40) != 41") + } + }() + } + + { + x := 42 + if y := func() int { // ERROR "can inline main.func20" + return x + }(); y != 42 { // ERROR "inlining call to main.func20" + panic("y != 42") + } + if y := func() int { // ERROR "can inline main.func21" "func literal does not escape" + return x + }; y() != 42 { // ERROR "inlining call to main.func21" + panic("y() != 42") + } + } + + { + x := 42 + if z := func(y int) int { // ERROR "func literal does not escape" + return func() int { // ERROR "can inline main.func22.1" + return x + y + }() // ERROR "inlining call to main.func22.1" + }(1); z != 43 { + panic("z != 43") + } + if z := func(y int) int { // ERROR "func literal does not escape" + return func() int { // ERROR "can inline main.func23.1" + return x + y + }() // ERROR "inlining call to main.func23.1" + }; z(1) != 43 { + panic("z(1) != 43") + } + } + + { + a := 1 + func() { // ERROR "func literal does not escape" + func() { // ERROR "can inline main.func24" + a = 2 + }() // ERROR "inlining call to main.func24" "&a does not escape" + }() + if a != 2 { + panic("a != 2") + } + } + + { + b := 2 + func(b int) { // ERROR "func literal does not escape" + func() { // ERROR "can inline main.func25.1" + b = 3 + }() // ERROR "inlining call to main.func25.1" "&b does not escape" + if b != 3 { + panic("b != 3") + } + }(b) + if b != 2 { + panic("b != 2") + } + } + + { + c := 3 + func() { // ERROR "func literal does not escape" + c = 4 + func() { // ERROR "func literal does not escape" + if c != 4 { + panic("c != 4") + } + }() + }() + if c != 4 { + panic("c != 4") + } + } + + { + a := 2 + if r := func(x int) int { // ERROR "func literal does not escape" + b := 3 + return func(y int) int { // ERROR "func literal does not escape" + c := 5 + return func(z int) int { // ERROR "can inline main.func27.1.1" + return a*x + b*y + c*z + }(10) // ERROR "inlining call to main.func27.1.1" + }(100) + }(1000); r != 2350 { + panic("r != 2350") + } + } + + { + a := 2 + if r := func(x int) int { // ERROR "func literal does not escape" + b := 3 + return func(y int) int { // ERROR "func literal does not escape" + c := 5 + func(z int) { // ERROR "can inline main.func28.1.1" + a = a * x + b = b * y + c = c * z + }(10) // ERROR "inlining call to main.func28.1.1" "&a does not escape" "&b does not escape" "&c does not escape" + return a + c + }(100) + b + }(1000); r != 2350 { + panic("r != 2350") + } + if a != 2000 { + panic("a != 2000") + } + } +} diff --git a/test/closure3.go b/test/closure3.go new file mode 100644 index 00000000..263d8fcb --- /dev/null +++ b/test/closure3.go @@ -0,0 +1,10 @@ +// errorcheckandrundir -0 -m + +// Copyright 2017 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. + +// Check correctness of various closure corner cases that +// that are expected to be inlined + +package ignored diff --git a/test/ddd1.go b/test/ddd1.go index 4284e321..b4ad80b6 100644 --- a/test/ddd1.go +++ b/test/ddd1.go @@ -53,8 +53,7 @@ func bad(args ...int) { _ = new(int...) // ERROR "[.][.][.]" n := 10 _ = make([]byte, n...) // ERROR "[.][.][.]" - // TODO(rsc): enable after gofmt bug is fixed - // _ = make([]byte, 10 ...) // error "[.][.][.]" + _ = make([]byte, 10 ...) // ERROR "[.][.][.]" var x int _ = unsafe.Pointer(&x...) // ERROR "[.][.][.]" _ = unsafe.Sizeof(x...) // ERROR "[.][.][.]" diff --git a/test/errchk b/test/errchk index bc8ef19c..1cb57bb9 100755 --- a/test/errchk +++ b/test/errchk @@ -65,6 +65,9 @@ $out = join('', <CMD>); close CMD; +# Remove lines beginning with #, printed by go command to indicate package. +@out = grep {!/^#/} @out; + if($exitcode != 0 && $? == 0) { print STDERR "BUG: errchk: command succeeded unexpectedly\n"; print STDERR @out; diff --git a/test/escape2.go b/test/escape2.go index e10dbc2a..ef3d6a88 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -1204,7 +1204,7 @@ func foo126() { // loopdepth 1 var i int // ERROR "moved to heap: i$" func() { // ERROR "foo126 func literal does not escape$" - px = &i // ERROR "&i escapes to heap$" "leaking closure reference i" + px = &i // ERROR "&i escapes to heap$" "leaking closure reference i" }() } _ = px diff --git a/test/escape2n.go b/test/escape2n.go index 74f6f8dd..b1130d3c 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -1824,3 +1824,18 @@ func issue11387(x int) func() int { copy(slice2, slice1) return slice2[0] } + +func issue12397(x, y int) { // ERROR "moved to heap: y$" + // x does not escape below, because all relevant code is dead. + if false { + gxx = &x + } else { + gxx = &y // ERROR "&y escapes to heap$" + } + + if true { + gxx = &y // ERROR "&y escapes to heap$" + } else { + gxx = &x + } +} diff --git a/test/escape4.go b/test/escape4.go index 69a54ac7..22a37c1d 100644 --- a/test/escape4.go +++ b/test/escape4.go @@ -22,9 +22,9 @@ func f1() { // Escape analysis used to miss inlined code in closures. - func() { // ERROR "func literal does not escape" "can inline f1.func1" - p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x" - }() + func() { // ERROR "can inline f1.func1" + p = alloc(3) // ERROR "inlining call to alloc" + }() // ERROR "inlining call to f1.func1" "inlining call to alloc" "&x escapes to heap" "moved to heap: x" f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2" p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x" diff --git a/test/fixedbugs/bug289.go b/test/fixedbugs/bug289.go index a3f72955..3fc7fb2e 100644 --- a/test/fixedbugs/bug289.go +++ b/test/fixedbugs/bug289.go @@ -9,14 +9,14 @@ package main func f1() { - a, b := f() // ERROR "cannot assign|does not match" + a, b := f() // ERROR "assignment mismatch|does not match" _ = a _ = b } func f2() { var a, b int - a, b = f() // ERROR "cannot assign|does not match" + a, b = f() // ERROR "assignment mismatch|does not match" _ = a _ = b } diff --git a/test/fixedbugs/bug388.go b/test/fixedbugs/bug388.go index af0c9d9c..2d508501 100644 --- a/test/fixedbugs/bug388.go +++ b/test/fixedbugs/bug388.go @@ -14,7 +14,7 @@ func foo(runtime.UintType, i int) { // ERROR "cannot declare name runtime.UintT } func bar(i int) { - runtime.UintType := i // ERROR "cannot declare name runtime.UintType|non-name on left side|undefined identifier" + runtime.UintType := i // ERROR "non-name runtime.UintType|non-name on left side|undefined identifier" println(runtime.UintType) // GCCGO_ERROR "invalid use of type|undefined identifier" } diff --git a/test/fixedbugs/bug487.go b/test/fixedbugs/bug487.go index 60a4ea98..ab61a19a 100644 --- a/test/fixedbugs/bug487.go +++ b/test/fixedbugs/bug487.go @@ -14,8 +14,8 @@ func G() (int, int, int) { } func F() { - a, b := G() // ERROR "cannot assign" - a, b = G() // ERROR "cannot assign" + a, b := G() // ERROR "assignment mismatch" + a, b = G() // ERROR "assignment mismatch" _, _ = a, b } diff --git a/test/fixedbugs/bug503.go b/test/fixedbugs/bug503.go new file mode 100644 index 00000000..7bbc7981 --- /dev/null +++ b/test/fixedbugs/bug503.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2017 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. + +// gccgo crashed compiling this file, due to failing to correctly emit +// the type descriptor for a named alias. + +package p + +type entry = struct { + a, b, c int +} + +var V entry diff --git a/test/fixedbugs/bug504.dir/a.go b/test/fixedbugs/bug504.dir/a.go new file mode 100644 index 00000000..ac0be937 --- /dev/null +++ b/test/fixedbugs/bug504.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2017 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. + +package a + +type MyInt = int diff --git a/test/fixedbugs/bug504.dir/b.go b/test/fixedbugs/bug504.dir/b.go new file mode 100644 index 00000000..e8f8da9a --- /dev/null +++ b/test/fixedbugs/bug504.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +package b + +import "./a" + +func F() a.MyInt { + return 0 +} diff --git a/test/fixedbugs/bug504.dir/c.go b/test/fixedbugs/bug504.dir/c.go new file mode 100644 index 00000000..5a6e8899 --- /dev/null +++ b/test/fixedbugs/bug504.dir/c.go @@ -0,0 +1,9 @@ +// Copyright 2017 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. + +package c + +import "./b" + +var V = b.F() diff --git a/test/fixedbugs/bug504.dir/main.go b/test/fixedbugs/bug504.dir/main.go new file mode 100644 index 00000000..bdbd95c7 --- /dev/null +++ b/test/fixedbugs/bug504.dir/main.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +package main + +import "./c" + +func main() { + println(c.V) +} diff --git a/test/fixedbugs/bug504.go b/test/fixedbugs/bug504.go new file mode 100644 index 00000000..ae1f2e52 --- /dev/null +++ b/test/fixedbugs/bug504.go @@ -0,0 +1,10 @@ +// compiledir + +// Copyright 2017 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. + +// Gccgo mishandled a reference to a type alias in a package that was +// not directly imported. + +package ignored diff --git a/test/fixedbugs/bug505.go b/test/fixedbugs/bug505.go new file mode 100644 index 00000000..062a0871 --- /dev/null +++ b/test/fixedbugs/bug505.go @@ -0,0 +1,20 @@ +// compile + +// Copyright 2017 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. + +// gccgo crashed compiling this file with a failed conversion to the +// alias type when constructing the composite literal. + +package p + +type I interface{ M() } +type A = I +type S struct { + f A +} + +func F(i I) S { + return S{f: i} +} diff --git a/test/fixedbugs/issue13265.go b/test/fixedbugs/issue13265.go new file mode 100644 index 00000000..3036ba7c --- /dev/null +++ b/test/fixedbugs/issue13265.go @@ -0,0 +1,15 @@ +// errorcheck -0 -race + +// Copyright 2017 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. + +// Issue 13265: nil pointer deref. + +package p + +func f() { + var c chan chan chan int + for ; ; <-<-<-c { + } +} diff --git a/test/fixedbugs/issue14006.go b/test/fixedbugs/issue14006.go index d69bdd48..02041cc2 100644 --- a/test/fixedbugs/issue14006.go +++ b/test/fixedbugs/issue14006.go @@ -50,7 +50,10 @@ func f() { labelname: // ERROR "missing statement after label" case false: } +} +func g() { + var z bool switch { case z: labelname: // ERROR "label labelname defined and not used" diff --git a/test/fixedbugs/issue14540.go b/test/fixedbugs/issue14540.go new file mode 100644 index 00000000..62b17a04 --- /dev/null +++ b/test/fixedbugs/issue14540.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +func f(x int) { + switch x { + case 0: + fallthrough + ; // ok + case 1: + fallthrough // ERROR "fallthrough statement out of place" + {} + case 2: + fallthrough // ERROR "cannot fallthrough" + } +} diff --git a/test/fixedbugs/issue15747.go b/test/fixedbugs/issue15747.go index 836d0eab..decabc75 100644 --- a/test/fixedbugs/issue15747.go +++ b/test/fixedbugs/issue15747.go @@ -1,4 +1,4 @@ -// errorcheck -0 -live +// errorcheck -0 -live -d=eagerwb // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -7,6 +7,10 @@ // Issue 15747: liveness analysis was marking heap-escaped params live too much, // and worse was using the wrong bitmap bits to do so. +// TODO(austin): This expects function calls to the write barrier, so +// we enable the legacy eager write barrier. Fix this once the +// buffered write barrier works on all arches. + package p var global *[]byte diff --git a/test/fixedbugs/issue15747b.go b/test/fixedbugs/issue15747b.go index 9620d3d0..bdb2a940 100644 --- a/test/fixedbugs/issue15747b.go +++ b/test/fixedbugs/issue15747b.go @@ -4,7 +4,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Issue 15747: If a ODCL is dropped, for example when inlining, +// Issue 15747: If an ODCL is dropped, for example when inlining, // then it's easy to end up not initializing the '&x' pseudo-variable // to point to an actual allocation. The liveness analysis will detect // this and abort the computation, so this test just checks that the diff --git a/test/fixedbugs/issue18902.go b/test/fixedbugs/issue18902.go index f5bca16a..78c92187 100644 --- a/test/fixedbugs/issue18902.go +++ b/test/fixedbugs/issue18902.go @@ -50,13 +50,16 @@ func main() { testarch := os.Getenv("TESTARCH") // Targets other platform in test compilation. debug := os.Getenv("TESTDEBUG") != "" // Output the relevant assembly language. - cmd := exec.Command("go", "build", "-gcflags", "-S", "fixedbugs/issue18902b.go") + cmd := exec.Command("go", "tool", "compile", "-S", "fixedbugs/issue18902b.go") var buf bytes.Buffer cmd.Stdout = &buf cmd.Stderr = &buf cmd.Env = os.Environ() - updateEnv(&cmd.Env, "GOARCH", testarch) + if testarch != "" { + updateEnv(&cmd.Env, "GOARCH", testarch) + updateEnv(&cmd.Env, "GOOS", "linux") // Simplify multi-arch testing + } err := cmd.Run() if err != nil { @@ -89,8 +92,9 @@ func main() { i = strings.Index(line, beforeLineNumber) if i < 0 { // Done reading lines - if scannedCount < 200 { // When test was written, 251 lines observed on amd64 - fmt.Printf("Scanned only %d lines, was expecting more than 200", scannedCount) + const minLines = 150 + if scannedCount <= minLines { // When test was written, 251 lines observed on amd64; arm64 now obtains 184 + fmt.Printf("Scanned only %d lines, was expecting more than %d\n", int(scannedCount), minLines) return } // Note: when test was written, before changes=92, after=50 (was 62 w/o rematerialization NoXPos in *Value.copyInto()) diff --git a/test/fixedbugs/issue19137.go b/test/fixedbugs/issue19137.go index 946f029b..0539a850 100644 --- a/test/fixedbugs/issue19137.go +++ b/test/fixedbugs/issue19137.go @@ -33,3 +33,19 @@ func zero() ([20]byte, [20]byte) { _ = x return [20]byte{}, [20]byte{} // the second return value is not 8-byte aligned to SP } + +// Issue 21992: unaligned offset between 256 and 504 and handled +// incorrectly. +type T2 struct { + a [257]byte + // fields below are not 8-, 4-, 2-byte aligned + b [8]byte + c [4]byte + d [2]byte +} + +func f2(x *T2) { + x.b = [8]byte{} + x.c = [4]byte{} + x.d = [2]byte{} +} diff --git a/test/fixedbugs/issue19261.dir/p.go b/test/fixedbugs/issue19261.dir/p.go new file mode 100644 index 00000000..1c44d8a3 --- /dev/null +++ b/test/fixedbugs/issue19261.dir/p.go @@ -0,0 +1,24 @@ +// Copyright 2017 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. + +package p + +func F() { // ERROR "can inline F" + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +} + +func G() { + F() // ERROR "inlining call to F" + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +} diff --git a/test/fixedbugs/issue19261.dir/q.go b/test/fixedbugs/issue19261.dir/q.go new file mode 100644 index 00000000..9f3550ab --- /dev/null +++ b/test/fixedbugs/issue19261.dir/q.go @@ -0,0 +1,17 @@ +// Copyright 2017 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. + +package q + +import "./p" + +func H() { + p.F() // ERROR "inlining call to p.F" + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) +} diff --git a/test/fixedbugs/issue19261.go b/test/fixedbugs/issue19261.go new file mode 100644 index 00000000..61cff6e1 --- /dev/null +++ b/test/fixedbugs/issue19261.go @@ -0,0 +1,7 @@ +// errorcheckdir -0 -m + +// Copyright 2017 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. + +package ignored diff --git a/test/fixedbugs/issue20250.go b/test/fixedbugs/issue20250.go index f24710a0..525192a4 100644 --- a/test/fixedbugs/issue20250.go +++ b/test/fixedbugs/issue20250.go @@ -1,4 +1,4 @@ -// errorcheck -0 -live -d=compilelater +// errorcheck -0 -live -l -d=compilelater,eagerwb // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -8,6 +8,10 @@ // due to propagation of addrtaken to outer variables for // closure variables. +// TODO(austin): This expects function calls to the write barrier, so +// we enable the legacy eager write barrier. Fix this once the +// buffered write barrier works on all arches. + package p type T struct { @@ -16,8 +20,8 @@ type T struct { func f(a T) { // ERROR "live at entry to f: a" var e interface{} - func() { // ERROR "live at entry to f.func1: &e a" - e = a.s // ERROR "live at call to convT2Estring: &e a" "live at call to writebarrierptr: a" + func() { // ERROR "live at entry to f.func1: a &e" + e = a.s // ERROR "live at call to convT2Estring: a &e" "live at call to writebarrierptr: a" }() // ERROR "live at call to f.func1: e$" // Before the fix, both a and e were live at the previous line. _ = e diff --git a/test/fixedbugs/issue20739.go b/test/fixedbugs/issue20739.go new file mode 100644 index 00000000..b71a25dc --- /dev/null +++ b/test/fixedbugs/issue20739.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2017 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. + +package p + +func F() { + var x struct { + x *int + w [1e9][1e9][1e9][0]*int + y *int + } + println(&x) +} diff --git a/test/fixedbugs/issue20812.go b/test/fixedbugs/issue20812.go new file mode 100644 index 00000000..0175eede --- /dev/null +++ b/test/fixedbugs/issue20812.go @@ -0,0 +1,15 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +func f() { + _ = int("1") // ERROR "cannot convert" + _ = bool(0) // ERROR "cannot convert" + _ = bool("false") // ERROR "cannot convert" + _ = int(false) // ERROR "cannot convert" + _ = string(true) // ERROR "cannot convert" +} diff --git a/test/fixedbugs/issue21253.go b/test/fixedbugs/issue21253.go new file mode 100644 index 00000000..3531b2b8 --- /dev/null +++ b/test/fixedbugs/issue21253.go @@ -0,0 +1,27 @@ +// compile + +// Copyright 2017 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. + +// Gccgo crashed compiling this code due to failing to finalize +// interfaces in the right order. + +package p + +type s1 struct { + f m + I +} + +type m interface { + Mm(*s2) +} + +type s2 struct { + *s1 +} + +type I interface { + MI() +} diff --git a/test/fixedbugs/issue21256.go b/test/fixedbugs/issue21256.go new file mode 100644 index 00000000..3d361247 --- /dev/null +++ b/test/fixedbugs/issue21256.go @@ -0,0 +1,9 @@ +// errorcheck + +// Copyright 2017 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. + +package main + +var main = func() {} // ERROR "must be func" diff --git a/test/fixedbugs/issue21273.go b/test/fixedbugs/issue21273.go new file mode 100644 index 00000000..7a790d14 --- /dev/null +++ b/test/fixedbugs/issue21273.go @@ -0,0 +1,28 @@ +// errorcheck + +// Copyright 2017 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. + +package main + +type T0 T0 // ERROR "invalid recursive type" +type _ map[T0]int + +type T1 struct{ T1 } // ERROR "invalid recursive type" +type _ map[T1]int + +func f() { + type T2 T2 // ERROR "invalid recursive type" + type _ map[T2]int +} + +func g() { + type T3 struct{ T3 } // ERROR "invalid recursive type" + type _ map[T3]int +} + +func h() { + type T4 struct{ m map[T4]int } // ERROR "invalid map key" + type _ map[T4]int // ERROR "invalid map key" +} diff --git a/test/fixedbugs/issue21317.go b/test/fixedbugs/issue21317.go new file mode 100644 index 00000000..ae0e0b55 --- /dev/null +++ b/test/fixedbugs/issue21317.go @@ -0,0 +1,60 @@ +// run + +// Copyright 2017 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. + +// As of "Mon 6 Nov 2017", run.go doesn't yet have proper +// column matching so instead match the output manually +// by exec-ing + +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "runtime" + "strings" +) + +func main() { + if runtime.Compiler != "gc" || runtime.GOOS == "nacl" { + return + } + + f, err := ioutil.TempFile("", "issue21317.go") + if err != nil { + log.Fatal(err) + } + fmt.Fprintf(f, ` +package main + +import "fmt" + +func main() { + n, err := fmt.Println(1) +} +`) + f.Close() + defer os.RemoveAll(f.Name()) + + // compile and test output + cmd := exec.Command("go", "tool", "compile", f.Name()) + out, err := cmd.CombinedOutput() + if err == nil { + log.Fatalf("expected cmd/compile to fail") + } + wantErrs := []string{ + "7:9: n declared and not used", + "7:12: err declared and not used", + } + outStr := string(out) + for _, want := range wantErrs { + if !strings.Contains(outStr, want) { + log.Fatalf("failed to match %q\noutput: %q", want, outStr) + } + } +} diff --git a/test/fixedbugs/issue21655.go b/test/fixedbugs/issue21655.go new file mode 100644 index 00000000..66d4e3a7 --- /dev/null +++ b/test/fixedbugs/issue21655.go @@ -0,0 +1,62 @@ +// compile + +// Copyright 2017 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. + +// Make sure assembly offsets don't get too large. + +// To trigger issue21655, the index offset needs to be small +// enough to fit into an int32 (to get rewritten to an ADDQconst) +// but large enough to overflow an int32 after multiplying by the stride. + +package main + +func f1(a []int64, i int64) int64 { + return a[i+1<<30] +} +func f2(a []int32, i int64) int32 { + return a[i+1<<30] +} +func f3(a []int16, i int64) int16 { + return a[i+1<<30] +} +func f4(a []int8, i int64) int8 { + return a[i+1<<31] +} +func f5(a []float64, i int64) float64 { + return a[i+1<<30] +} +func f6(a []float32, i int64) float32 { + return a[i+1<<30] +} + +// Note: Before the fix for issue 21655, f{1,2,5,6} made +// the compiler crash. f3 silently generated the wrong +// code, using an offset of -1<<31 instead of 1<<31. +// (This is due to the assembler accepting offsets +// like 0x80000000 and silently using them as +// signed 32 bit offsets.) +// f4 was ok, but testing it can't hurt. + +func f7(ss []*string, i int) string { + const offset = 3 << 29 // 3<<29 * 4 = 3<<31 = 1<<31 mod 1<<32. + if i > offset { + return *ss[i-offset] + } + return "" +} +func f8(ss []*string, i int) string { + const offset = 3<<29 + 10 + if i > offset { + return *ss[i-offset] + } + return "" +} +func f9(ss []*string, i int) string { + const offset = 3<<29 - 10 + if i > offset { + return *ss[i-offset] + } + return "" +} diff --git a/test/fixedbugs/issue21687.go b/test/fixedbugs/issue21687.go new file mode 100644 index 00000000..9b4c03fe --- /dev/null +++ b/test/fixedbugs/issue21687.go @@ -0,0 +1,68 @@ +// run + +// Copyright 2017 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. + +// Issue 21687: cmd/compile evaluates x twice in "x op= y", which was +// detectable if evaluating y affects x. + +package main + +func ptrs() (int, int) { + one := 1 + two := 2 + + x := &one + *x += func() int { + x = &two + return 0 + }() + + return one, two +} + +func slices() (int, int) { + one := []int{1} + two := []int{2} + + x := one + x[0] += func() int { + x = two + return 0 + }() + + return one[0], two[0] +} + +func maps() (int, int) { + one := map[int]int{0: 1} + two := map[int]int{0: 2} + + x := one + x[0] += func() int { + x = two + return 0 + }() + + return one[0], two[0] +} + +var tests = [...]func() (int, int){ + ptrs, + slices, + maps, +} + +func main() { + bad := 0 + for i, f := range tests { + if a, b := f(); a+b != 3 { + println(i, a, b) + bad++ + } + } + if bad != 0 { + panic(bad) + } +} diff --git a/test/fixedbugs/issue21709.go b/test/fixedbugs/issue21709.go new file mode 100644 index 00000000..bf5d9d23 --- /dev/null +++ b/test/fixedbugs/issue21709.go @@ -0,0 +1,37 @@ +// errorcheck -0 -l -m + +// Copyright 2017 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. + +// Issue 21709: range expression overly escapes. + +package p + +type S struct{} + +func (s *S) Inc() {} // ERROR "\(\*S\).Inc s does not escape" +var N int + +func F1() { + var s S // ERROR "moved to heap: s" + for i := 0; i < N; i++ { + fs := []func(){ // ERROR "F1 \[\]func\(\) literal does not escape" + s.Inc, // ERROR "F1 s.Inc does not escape" "s escapes to heap" + } + for _, f := range fs { + f() + } + } +} + +func F2() { + var s S // ERROR "moved to heap: s" + for i := 0; i < N; i++ { + for _, f := range []func(){ // ERROR "F2 \[\]func\(\) literal does not escape" + s.Inc, // ERROR "F2 s.Inc does not escape" "s escapes to heap" + } { + f() + } + } +} diff --git a/test/fixedbugs/issue21770.go b/test/fixedbugs/issue21770.go new file mode 100644 index 00000000..2f07d640 --- /dev/null +++ b/test/fixedbugs/issue21770.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 21770: gccgo incorrectly accepts "p.f = 0" where p is **struct + +package p + +type PP **struct{ f int } + +func f() { + // anonymous type + var p **struct{ f int } + p.f = 0 // ERROR "field" + // named type + var p2 PP + p2.f = 0 // ERROR "field" +} diff --git a/test/fixedbugs/issue21808.go b/test/fixedbugs/issue21808.go new file mode 100644 index 00000000..d146200e --- /dev/null +++ b/test/fixedbugs/issue21808.go @@ -0,0 +1,17 @@ +// run + +// Copyright 2017 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. + +// Make sure println() prints a blank line. + +package main + +import "fmt" + +func main() { + fmt.Println("A") + println() + fmt.Println("B") +} diff --git a/test/fixedbugs/issue21808.out b/test/fixedbugs/issue21808.out new file mode 100644 index 00000000..655da036 --- /dev/null +++ b/test/fixedbugs/issue21808.out @@ -0,0 +1,3 @@ +A + +B diff --git a/test/fixedbugs/issue21879.go b/test/fixedbugs/issue21879.go new file mode 100644 index 00000000..1029ca04 --- /dev/null +++ b/test/fixedbugs/issue21879.go @@ -0,0 +1,37 @@ +// run + +// Copyright 2017 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. + +package main + +import ( + "runtime" +) + +func main() { + println(caller().frame.Function) + + // Used to erroneously print "main.call.name" instead of + // "main.main". + println(caller().name()) +} + +func caller() call { + var pcs [3]uintptr + n := runtime.Callers(1, pcs[:]) + frames := runtime.CallersFrames(pcs[:n]) + frame, _ := frames.Next() + frame, _ = frames.Next() + + return call{frame: frame} +} + +type call struct { + frame runtime.Frame +} + +func (c call) name() string { + return c.frame.Function +} diff --git a/test/fixedbugs/issue21879.out b/test/fixedbugs/issue21879.out new file mode 100644 index 00000000..066f1a83 --- /dev/null +++ b/test/fixedbugs/issue21879.out @@ -0,0 +1,2 @@ +main.main +main.main diff --git a/test/fixedbugs/issue21882.go b/test/fixedbugs/issue21882.go new file mode 100644 index 00000000..f77e0469 --- /dev/null +++ b/test/fixedbugs/issue21882.go @@ -0,0 +1,9 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +type T [2]T // ERROR "invalid recursive type" diff --git a/test/fixedbugs/issue21887.go b/test/fixedbugs/issue21887.go new file mode 100644 index 00000000..9e3e91fc --- /dev/null +++ b/test/fixedbugs/issue21887.go @@ -0,0 +1,25 @@ +// cmpout + +// Copyright 2017 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. + +// Issue 21887: println(^uint(0)) fails to compile + +package main + +import "strconv" + +func main() { + if strconv.IntSize == 32 { + println(^uint(0)) + } else { + println(^uint32(0)) + } + + if strconv.IntSize == 64 { + println(^uint(0)) + } else { + println(^uint64(0)) + } +} diff --git a/test/fixedbugs/issue21887.out b/test/fixedbugs/issue21887.out new file mode 100644 index 00000000..664b67d7 --- /dev/null +++ b/test/fixedbugs/issue21887.out @@ -0,0 +1,2 @@ +4294967295 +18446744073709551615 diff --git a/test/fixedbugs/issue21963.go b/test/fixedbugs/issue21963.go new file mode 100644 index 00000000..996bd63d --- /dev/null +++ b/test/fixedbugs/issue21963.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2017 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. + +package main + +import ( + "fmt" + "runtime" +) + +//go:noinline +func f(x []int32, y *int8) int32 { + c := int32(int16(*y)) + runtime.GC() + return x[0] * c +} + +func main() { + var x = [1]int32{5} + var y int8 = -1 + if got, want := f(x[:], &y), int32(-5); got != want { + panic(fmt.Sprintf("wanted %d, got %d", want, got)) + } +} diff --git a/test/fixedbugs/issue21988.go b/test/fixedbugs/issue21988.go new file mode 100644 index 00000000..850e0398 --- /dev/null +++ b/test/fixedbugs/issue21988.go @@ -0,0 +1,17 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 21988: panic on switch case with invalid value + +package p + +const X = Wrong(0) // ERROR "undefined: Wrong" + +func _() { + switch 0 { + case X: + } +} diff --git a/test/fixedbugs/issue22063.go b/test/fixedbugs/issue22063.go new file mode 100644 index 00000000..bfdb2e00 --- /dev/null +++ b/test/fixedbugs/issue22063.go @@ -0,0 +1,17 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 22063: panic on interface switch case with invalid name + +package p + +const X = Wrong(0) // ERROR "undefined: Wrong" + +func _() { + switch interface{}(nil) { + case X: + } +} diff --git a/test/fixedbugs/issue22076.go b/test/fixedbugs/issue22076.go new file mode 100644 index 00000000..5d628b96 --- /dev/null +++ b/test/fixedbugs/issue22076.go @@ -0,0 +1,25 @@ +// compile + +// Copyright 2017 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. + +// Issue 22076: Couldn't use ":=" to declare names that refer to +// dot-imported symbols. + +package p + +import . "bytes" + +var _ Reader // use "bytes" import + +func _() { + Buffer := 0 + _ = Buffer +} + +func _() { + for Buffer := range []int{} { + _ = Buffer + } +} diff --git a/test/fixedbugs/issue22083.go b/test/fixedbugs/issue22083.go new file mode 100644 index 00000000..a385102d --- /dev/null +++ b/test/fixedbugs/issue22083.go @@ -0,0 +1,41 @@ +// run + +// Copyright 2017 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. + +// The compiler was panicking on the wrong line number, where +// the panic was occurring in an inlined call. + +package main + +import ( + "runtime/debug" + "strings" +) + +type Wrapper struct { + a []int +} + +func (w Wrapper) Get(i int) int { + return w.a[i] +} + +func main() { + defer func() { + e := recover() + if e == nil { + panic("bounds check didn't fail") + } + stk := string(debug.Stack()) + if !strings.Contains(stk, "issue22083.go:40") { + panic("wrong stack trace: " + stk) + } + }() + foo := Wrapper{a: []int{0, 1, 2}} + _ = foo.Get(0) + _ = foo.Get(1) + _ = foo.Get(2) + _ = foo.Get(3) // stack trace should mention this line +} diff --git a/test/fixedbugs/issue22164.go b/test/fixedbugs/issue22164.go new file mode 100644 index 00000000..fad78e23 --- /dev/null +++ b/test/fixedbugs/issue22164.go @@ -0,0 +1,26 @@ +// errorcheck + +// Copyright 2017 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 error recovery after missing closing parentheses in lists. + +package p + +func f() { + x := f(g() // ERROR "unexpected newline" + y := 1 +} + +func g() { +} + +func h() { + x := f(g() // ERROR "unexpected newline" +} + +func i() { + x := []int{1, 2, 3 // ERROR "unexpected newline" + y := 0 +}
\ No newline at end of file diff --git a/test/fixedbugs/issue22198.go b/test/fixedbugs/issue22198.go new file mode 100644 index 00000000..c874c1ca --- /dev/null +++ b/test/fixedbugs/issue22198.go @@ -0,0 +1,18 @@ +// compile + +// Copyright 2017 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. + +package issue22198 + +func f(a *bool, b bool) { + if b { + return + } + c := '\n' + if b { + c = ' ' + } + *a = c == '\n' +} diff --git a/test/fixedbugs/issue22200.go b/test/fixedbugs/issue22200.go new file mode 100644 index 00000000..66b9538e --- /dev/null +++ b/test/fixedbugs/issue22200.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +func f1(x *[1<<30 - 1e6]byte) byte { + for _, b := range *x { + return b + } + return 0 +} +func f2(x *[1<<30 + 1e6]byte) byte { // ERROR "stack frame too large" + for _, b := range *x { + return b + } + return 0 +} diff --git a/test/fixedbugs/issue22200b.go b/test/fixedbugs/issue22200b.go new file mode 100644 index 00000000..8d4515eb --- /dev/null +++ b/test/fixedbugs/issue22200b.go @@ -0,0 +1,28 @@ +// errorcheck + +// Copyright 2017 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. + +// +build !386,!amd64p32,!arm,!mips,!mipsle + +package p + +func f3(x *[1 << 31]byte) byte { // ERROR "stack frame too large" + for _, b := range *x { + return b + } + return 0 +} +func f4(x *[1 << 32]byte) byte { // ERROR "stack frame too large" + for _, b := range *x { + return b + } + return 0 +} +func f5(x *[1 << 33]byte) byte { // ERROR "stack frame too large" + for _, b := range *x { + return b + } + return 0 +} diff --git a/test/fixedbugs/issue22351.go b/test/fixedbugs/issue22351.go new file mode 100644 index 00000000..e46a0fb2 --- /dev/null +++ b/test/fixedbugs/issue22351.go @@ -0,0 +1,11 @@ +// errorcheck + +// Copyright 2017 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. + +package main + +import "unsafe" + +const _ = uint64(unsafe.Offsetof(T{}.F)) // ERROR "undefined" diff --git a/test/fixedbugs/issue22389.go b/test/fixedbugs/issue22389.go new file mode 100644 index 00000000..706b4494 --- /dev/null +++ b/test/fixedbugs/issue22389.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +type Foo struct{} + +func (f *Foo) Call(cb func(*Foo)) { + cb(f) +} + +func main() { + f := &Foo{} + f.Call(func(f) {}) // ERROR "f is not a type" +} diff --git a/test/fixedbugs/issue22429.go b/test/fixedbugs/issue22429.go new file mode 100644 index 00000000..289b434a --- /dev/null +++ b/test/fixedbugs/issue22429.go @@ -0,0 +1,18 @@ +// compile + +// Copyright 2017 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. + +// Make sure SSA->assembly pass can handle SP as an index register. + +package p + +type T struct { + a,b,c,d float32 +} + +func f(a *[8]T, i,j,k int) float32 { + b := *a + return b[i].a + b[j].b + b[k].c +} diff --git a/test/fixedbugs/issue22458.go b/test/fixedbugs/issue22458.go new file mode 100644 index 00000000..5c899295 --- /dev/null +++ b/test/fixedbugs/issue22458.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2017 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. + +// Make sure KeepAlive introduces a use of the spilled variable. + +package main + +import "runtime" + +type node struct { + next *node +} + +var x bool + +func main() { + var head *node + for x { + head = &node{head} + } + + runtime.KeepAlive(head) +} diff --git a/test/fixedbugs/issue22581.go b/test/fixedbugs/issue22581.go new file mode 100644 index 00000000..2b637f2e --- /dev/null +++ b/test/fixedbugs/issue22581.go @@ -0,0 +1,27 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +func f() { + if i := g()); i == j { // ERROR "unexpected \)" + } + + if i == g()] { // ERROR "unexpected \]" + } + + switch i := g()); i { // ERROR "unexpected \)" + } + + switch g()] { // ERROR "unexpected \]" + } + + for i := g()); i < y; { // ERROR "unexpected \)" + } + + for g()] { // ERROR "unexpected \]" + } +} diff --git a/test/fixedbugs/issue22605.go b/test/fixedbugs/issue22605.go new file mode 100644 index 00000000..9e726f35 --- /dev/null +++ b/test/fixedbugs/issue22605.go @@ -0,0 +1,26 @@ +// run + +// Copyright 2017 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. + +// We were picking up a special noalg type from typelinks. + +package main + +import "reflect" + +func f(m map[string]int) int { + return m["a"] +} + +func g(m map[[8]string]int) int { + t := reflect.ArrayOf(8, reflect.TypeOf("")) + a := reflect.New(t).Elem() + return m[a.Interface().([8]string)] +} + +func main() { + m := map[[8]string]int{} + g(m) +} diff --git a/test/fixedbugs/issue22660.go b/test/fixedbugs/issue22660.go new file mode 100644 index 00000000..48686fef --- /dev/null +++ b/test/fixedbugs/issue22660.go @@ -0,0 +1,50 @@ +// run + +// Copyright 2017 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. + +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +func main() { + if runtime.GOOS == "nacl" { + return // no file system available on builders + } + + f, err := ioutil.TempFile("", "issue22660.go") + if err != nil { + log.Fatal(err) + } + f.Close() + defer os.Remove(f.Name()) + + // path must appear in error messages even if we strip them with -trimpath + path := filepath.Join("users", "xxx", "go") + var src bytes.Buffer + fmt.Fprintf(&src, "//line %s:1\n", filepath.Join(path, "foo.go")) + + if err := ioutil.WriteFile(f.Name(), src.Bytes(), 0660); err != nil { + log.Fatal(err) + } + + out, err := exec.Command("go", "tool", "compile", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput() + if err == nil { + log.Fatalf("expected compiling %s to fail", f.Name()) + } + + if !strings.HasPrefix(string(out), path) { + log.Fatalf("expected full path (%s) in error message, got:\n%s", path, out) + } +} diff --git a/test/fixedbugs/issue22683.go b/test/fixedbugs/issue22683.go new file mode 100644 index 00000000..a59a0eda --- /dev/null +++ b/test/fixedbugs/issue22683.go @@ -0,0 +1,30 @@ +// cmpout + +// Copyright 2017 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. + +package main + +import ( + "fmt" +) + +type foo struct { + bar [1]*int +} + +func main() { + ch := make(chan foo, 2) + var a int + var b [1]*int + b[0] = &a + ch <- foo{bar: b} + close(ch) + + for v := range ch { + for i := 0; i < 1; i++ { + fmt.Println(v.bar[0] != nil) + } + } +} diff --git a/test/fixedbugs/issue22683.out b/test/fixedbugs/issue22683.out new file mode 100644 index 00000000..27ba77dd --- /dev/null +++ b/test/fixedbugs/issue22683.out @@ -0,0 +1 @@ +true diff --git a/test/fixedbugs/issue22781.go b/test/fixedbugs/issue22781.go new file mode 100644 index 00000000..5ad82398 --- /dev/null +++ b/test/fixedbugs/issue22781.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2017 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. + +package main + +import "runtime/debug" + +type T struct { + // >= 16 bytes to avoid tiny alloc. + a, b int +} + +func main() { + debug.SetGCPercent(1) + for i := 0; i < 100000; i++ { + m := make(map[*T]struct{}, 0) + for j := 0; j < 20; j++ { + // During the call to mapassign_fast64, the key argument + // was incorrectly treated as a uint64. If the stack was + // scanned during that call, the only pointer to k was + // missed, leading to *k being collected prematurely. + k := new(T) + m[k] = struct{}{} + } + } +} diff --git a/test/fixedbugs/issue22794.go b/test/fixedbugs/issue22794.go new file mode 100644 index 00000000..c7e9eb12 --- /dev/null +++ b/test/fixedbugs/issue22794.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2017 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. + +package main + +type it struct { + Floats bool + inner string +} + +func main() { + i1 := it{Floats: true} + if i1.floats { // ERROR "(type it .* field or method floats, but does have Floats)" + } + i2 := &it{floats: false} // ERROR "(but does have Floats)" + _ = &it{InneR: "foo"} // ERROR "(but does have inner)" +} diff --git a/test/fixedbugs/issue22877.dir/p.go b/test/fixedbugs/issue22877.dir/p.go new file mode 100644 index 00000000..fc86cb9e --- /dev/null +++ b/test/fixedbugs/issue22877.dir/p.go @@ -0,0 +1,14 @@ +// Copyright 2017 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. + +package main + +type S struct{ i int } +type SS = S + +func sub() + +func main() { + sub() +} diff --git a/test/fixedbugs/issue22877.dir/p.s b/test/fixedbugs/issue22877.dir/p.s new file mode 100644 index 00000000..8b14358c --- /dev/null +++ b/test/fixedbugs/issue22877.dir/p.s @@ -0,0 +1,8 @@ +// Copyright 2017 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. + +#include "go_asm.h" + +TEXT ·sub(SB), 0, $0 + RET diff --git a/test/fixedbugs/issue22877.go b/test/fixedbugs/issue22877.go new file mode 100644 index 00000000..284b6807 --- /dev/null +++ b/test/fixedbugs/issue22877.go @@ -0,0 +1,7 @@ +// builddir + +// Copyright 2017 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. + +package ignored diff --git a/test/fixedbugs/issue22881.go b/test/fixedbugs/issue22881.go new file mode 100644 index 00000000..61e99a28 --- /dev/null +++ b/test/fixedbugs/issue22881.go @@ -0,0 +1,72 @@ +// run + +// Copyright 2017 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 to make sure RHS is evaluated before map insert is started. +// The RHS panics in all of these cases. + +package main + +import "fmt" + +func main() { + for i, f := range []func(map[int]int){ + f0, f1, f2, f3, f4, f5, f6, f7, + } { + m := map[int]int{} + func() { // wrapper to scope the defer. + defer func() { + recover() + }() + f(m) // Will panic. Shouldn't modify m. + fmt.Printf("RHS didn't panic, case f%d\n", i) + }() + if len(m) != 0 { + fmt.Printf("map insert happened, case f%d\n", i) + } + } +} + +func f0(m map[int]int) { + var p *int + m[0] = *p +} + +func f1(m map[int]int) { + var p *int + m[0] += *p +} + +func f2(m map[int]int) { + var p *int + sink, m[0] = sink, *p +} + +func f3(m map[int]int) { + var p *chan int + m[0], sink = <-(*p) +} + +func f4(m map[int]int) { + var p *interface{} + m[0], sink = (*p).(int) +} + +func f5(m map[int]int) { + var p *map[int]int + m[0], sink = (*p)[0] +} + +func f6(m map[int]int) { + var z int + m[0] /= z +} + +func f7(m map[int]int) { + var a []int + m[0] = a[0] +} + +var sink bool diff --git a/test/fixedbugs/issue22904.go b/test/fixedbugs/issue22904.go new file mode 100644 index 00000000..46cb7c04 --- /dev/null +++ b/test/fixedbugs/issue22904.go @@ -0,0 +1,19 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 22904: Make sure the compiler emits a proper error message about +// invalid recursive types rather than crashing. + +package p + +type a struct{ b } +type b struct{ a } // ERROR "invalid recursive type" + +var x interface{} + +func f() { + x = a{} +} diff --git a/test/fixedbugs/issue22941.dir/a.go b/test/fixedbugs/issue22941.dir/a.go new file mode 100644 index 00000000..7a4ede43 --- /dev/null +++ b/test/fixedbugs/issue22941.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2017 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. + +package q + +type P int diff --git a/test/fixedbugs/issue22941.dir/b.go b/test/fixedbugs/issue22941.dir/b.go new file mode 100644 index 00000000..87d59a67 --- /dev/null +++ b/test/fixedbugs/issue22941.dir/b.go @@ -0,0 +1,30 @@ +// Copyright 2017 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. + +package p + +import q "./a" + +type T struct { + X *q.P +} + +func F(in, out *T) { + *out = *in + if in.X != nil { + in, out := &in.X, &out.X + if *in == nil { + *out = nil + } else { + *out = new(q.P) + **out = **in + } + } + return +} + +//go:noinline +func G(x, y *T) { + F(x, y) +} diff --git a/test/fixedbugs/issue22941.dir/main.go b/test/fixedbugs/issue22941.dir/main.go new file mode 100644 index 00000000..84666adf --- /dev/null +++ b/test/fixedbugs/issue22941.dir/main.go @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +package main + +import p "./b" + +var G int + +func main() { + if G == 101 { + p.G(nil, nil) + } +} diff --git a/test/fixedbugs/issue22941.go b/test/fixedbugs/issue22941.go new file mode 100644 index 00000000..c3732c31 --- /dev/null +++ b/test/fixedbugs/issue22941.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2017 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. + +package ignored diff --git a/test/fixedbugs/issue22962.dir/a.go b/test/fixedbugs/issue22962.dir/a.go new file mode 100644 index 00000000..7257d7df --- /dev/null +++ b/test/fixedbugs/issue22962.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +package a + +func F() { + if x := 0; false { + _ = x + } +} diff --git a/test/fixedbugs/issue22962.dir/b.go b/test/fixedbugs/issue22962.dir/b.go new file mode 100644 index 00000000..e1568c8f --- /dev/null +++ b/test/fixedbugs/issue22962.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2017 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. + +package b + +import "a" + +var V = func() { a.F() } diff --git a/test/fixedbugs/issue22962.go b/test/fixedbugs/issue22962.go new file mode 100644 index 00000000..8000a522 --- /dev/null +++ b/test/fixedbugs/issue22962.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2017 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. + +package ignored diff --git a/test/fixedbugs/issue23093.go b/test/fixedbugs/issue23093.go new file mode 100644 index 00000000..2fd7d5ff --- /dev/null +++ b/test/fixedbugs/issue23093.go @@ -0,0 +1,9 @@ +// errorcheck + +// Copyright 2017 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. + +package p + +var f = func() { f() } // ERROR "initialization loop" diff --git a/test/fixedbugs/issue23179.dir/a.go b/test/fixedbugs/issue23179.dir/a.go new file mode 100644 index 00000000..3d2816fc --- /dev/null +++ b/test/fixedbugs/issue23179.dir/a.go @@ -0,0 +1,13 @@ +// Copyright 2017 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. + +package a + +type Large struct { + x [256]int +} + +func F(x int, _ int, _ bool, _ Large) int { + return x +} diff --git a/test/fixedbugs/issue23179.dir/b.go b/test/fixedbugs/issue23179.dir/b.go new file mode 100644 index 00000000..bec3d15e --- /dev/null +++ b/test/fixedbugs/issue23179.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2017 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. + +package b + +import "a" + +func G(x int) int { + return a.F(x, 1, false, a.Large{}) +} diff --git a/test/fixedbugs/issue23179.go b/test/fixedbugs/issue23179.go new file mode 100644 index 00000000..8000a522 --- /dev/null +++ b/test/fixedbugs/issue23179.go @@ -0,0 +1,7 @@ +// compiledir + +// Copyright 2017 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. + +package ignored diff --git a/test/fixedbugs/issue23305.go b/test/fixedbugs/issue23305.go new file mode 100644 index 00000000..28f400c5 --- /dev/null +++ b/test/fixedbugs/issue23305.go @@ -0,0 +1,28 @@ +// run + +// Copyright 2018 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. + +package main + +func mask1(a, b uint64) uint64 { + op1 := int32(a) + op2 := int32(b) + return uint64(uint32(op1 / op2)) +} + +var mask2 = mask1 + +func main() { + res1 := mask1(0x1, 0xfffffffeffffffff) + res2 := mask2(0x1, 0xfffffffeffffffff) + if res1 != 0xffffffff { + println("got", res1, "want", 0xffffffff) + panic("FAIL") + } + if res2 != 0xffffffff { + println("got", res2, "want", 0xffffffff) + panic("FAIL") + } +} diff --git a/test/fixedbugs/issue23522.go b/test/fixedbugs/issue23522.go new file mode 100644 index 00000000..cace86c8 --- /dev/null +++ b/test/fixedbugs/issue23522.go @@ -0,0 +1,46 @@ +// run + +// Copyright 2018 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. + +package main + +import ( + "math" +) + +type S struct { + u int64 + n int32 +} + +func F1(f float64) *S { + s := f + pf := math.Copysign(f, 1) + u := math.Floor(pf) + return &S{ + u: int64(math.Copysign(u, s)), + n: int32(math.Copysign((pf-u)*1e9, s)), + } +} + +func F2(f float64) *S { + s := f + f = math.Copysign(f, 1) + u := math.Floor(f) + return &S{ + u: int64(math.Copysign(u, s)), + n: int32(math.Copysign((f-u)*1e9, s)), + } +} + +func main() { + s1 := F1(-1) + s2 := F2(-1) + if *s1 != *s2 { + println("F1:", s1.u, s1.n) + println("F2:", s2.u, s2.n) + panic("different") + } +} diff --git a/test/fixedbugs/issue23545.go b/test/fixedbugs/issue23545.go new file mode 100644 index 00000000..24485c11 --- /dev/null +++ b/test/fixedbugs/issue23545.go @@ -0,0 +1,35 @@ +// run + +// Copyright 2018 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. + +// +build gccgo + +// Issue 23545: gccgo didn't lower array comparison to +// proper equality function in some case. +// TODO: build only on gccgo for now, as it hits issue +// #23546. + +package main + +func main() { + if a := Get(); a != dummyID(1234) { + panic("FAIL") + } +} + +func dummyID(x int) [Size]interface{} { + var out [Size]interface{} + out[0] = x + return out +} + +const Size = 32 + +type OutputID [Size]interface{} + +//go:noinline +func Get() OutputID { + return dummyID(1234) +} diff --git a/test/fixedbugs/issue23719.go b/test/fixedbugs/issue23719.go new file mode 100644 index 00000000..c97e6363 --- /dev/null +++ b/test/fixedbugs/issue23719.go @@ -0,0 +1,42 @@ +// run + +// Copyright 2018 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. + +package main + +func main() { + v1 := [2]int32{-1, 88} + v2 := [2]int32{-1, 99} + if v1 == v2 { + panic("bad comparison") + } + + w1 := [2]int16{-1, 88} + w2 := [2]int16{-1, 99} + if w1 == w2 { + panic("bad comparison") + } + x1 := [4]int16{-1, 88, 88, 88} + x2 := [4]int16{-1, 99, 99, 99} + if x1 == x2 { + panic("bad comparison") + } + + a1 := [2]int8{-1, 88} + a2 := [2]int8{-1, 99} + if a1 == a2 { + panic("bad comparison") + } + b1 := [4]int8{-1, 88, 88, 88} + b2 := [4]int8{-1, 99, 99, 99} + if b1 == b2 { + panic("bad comparison") + } + c1 := [8]int8{-1, 88, 88, 88, 88, 88, 88, 88} + c2 := [8]int8{-1, 99, 99, 99, 99, 99, 99, 99} + if c1 == c2 { + panic("bad comparison") + } +} diff --git a/test/fixedbugs/issue23812.go b/test/fixedbugs/issue23812.go new file mode 100644 index 00000000..0a40deb2 --- /dev/null +++ b/test/fixedbugs/issue23812.go @@ -0,0 +1,34 @@ +// run + +// Copyright 2018 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. + +package main + +import "fmt" + +func main() { + want := int32(0x3edae8) + got := foo(1) + if want != got { + panic(fmt.Sprintf("want %x, got %x", want, got)) + } +} + +func foo(a int32) int32 { + return shr1(int32(shr2(int64(0x14ff6e2207db5d1f), int(a))), 4) +} + +func shr1(n int32, m int) int32 { return n >> uint(m) } + +func shr2(n int64, m int) int64 { + if m < 0 { + m = -m + } + if m >= 64 { + return n + } + + return n >> uint(m) +} diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go deleted file mode 100644 index 5bb05eb4..00000000 --- a/test/fixedbugs/issue4388.go +++ /dev/null @@ -1,56 +0,0 @@ -// run - -// Copyright 2014 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. - -package main - -import ( - "fmt" - "io" - "runtime" -) - -type T struct { - io.Closer -} - -func f1() { - // The 5 here and below depends on the number of internal runtime frames - // that sit between a deferred function called during panic and - // the original frame. If that changes, this test will start failing and - // the number here will need to be updated. - defer checkLine(5) - var t *T - var c io.Closer = t - c.Close() -} - -func f2() { - defer checkLine(5) - var t T - var c io.Closer = t - c.Close() -} - -func main() { - f1() - f2() -} - -func checkLine(n int) { - if err := recover(); err == nil { - panic("did not panic") - } - var file string - var line int - for i := 1; i <= n; i++ { - _, file, line, _ = runtime.Caller(i) - if file != "<autogenerated>" || line != 1 { - continue - } - return - } - panic(fmt.Sprintf("expected <autogenerated>:1 have %s:%d", file, line)) -} diff --git a/test/fixedbugs/issue7525.go b/test/fixedbugs/issue7525.go index 6e695931..fcfab723 100644 --- a/test/fixedbugs/issue7525.go +++ b/test/fixedbugs/issue7525.go @@ -11,7 +11,5 @@ package main import "unsafe" var x struct { - a [unsafe.Sizeof(x.a)]int // ERROR "array bound|typechecking loop|invalid expression" - b [unsafe.Offsetof(x.b)]int // ERROR "array bound" - c [unsafe.Alignof(x.c)]int // ERROR "array bound|invalid expression" + a [unsafe.Sizeof(x.a)]int // ERROR "array bound|typechecking loop|invalid expression" } diff --git a/test/fixedbugs/issue7525d.go b/test/fixedbugs/issue7525d.go new file mode 100644 index 00000000..141d6752 --- /dev/null +++ b/test/fixedbugs/issue7525d.go @@ -0,0 +1,15 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 7525: self-referential array types. + +package main + +import "unsafe" + +var x struct { + b [unsafe.Offsetof(x.b)]int // ERROR "array bound|typechecking loop|invalid array" +} diff --git a/test/fixedbugs/issue7525e.go b/test/fixedbugs/issue7525e.go new file mode 100644 index 00000000..c13194ca --- /dev/null +++ b/test/fixedbugs/issue7525e.go @@ -0,0 +1,15 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 7525: self-referential array types. + +package main + +import "unsafe" + +var x struct { + c [unsafe.Alignof(x.c)]int // ERROR "array bound|typechecking loop|invalid array" +} diff --git a/test/inline.go b/test/inline.go index 773b047c..25532304 100644 --- a/test/inline.go +++ b/test/inline.go @@ -9,7 +9,10 @@ package foo -import "unsafe" +import ( + "errors" + "unsafe" +) func add2(p *byte, n uintptr) *byte { // ERROR "can inline add2" "leaking param: p to result" return (*byte)(add1(unsafe.Pointer(p), n)) // ERROR "inlining call to add1" @@ -46,6 +49,83 @@ func j(x int) int { // ERROR "can inline j" } } +var somethingWrong error = errors.New("something went wrong") + +// local closures can be inlined +func l(x, y int) (int, int, error) { + e := func(err error) (int, int, error) { // ERROR "can inline l.func1" "func literal does not escape" "leaking param: err to result" + return 0, 0, err + } + if x == y { + e(somethingWrong) // ERROR "inlining call to l.func1" + } + return y, x, nil +} + +// any re-assignment prevents closure inlining +func m() int { + foo := func() int { return 1 } // ERROR "can inline m.func1" "func literal does not escape" + x := foo() + foo = func() int { return 2 } // ERROR "can inline m.func2" "func literal does not escape" + return x + foo() +} + +// address taking prevents closure inlining +func n() int { + foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape" + bar := &foo // ERROR "&foo does not escape" + x := (*bar)() + foo() + return x +} + +// make sure assignment inside closure is detected +func o() int { + foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape" + func(x int) { // ERROR "func literal does not escape" + if x > 10 { + foo = func() int { return 2 } // ERROR "can inline o.func2" "func literal escapes" + } + }(11) + return foo() +} + +func p() int { + return func() int { return 42 }() // ERROR "can inline p.func1" "inlining call to p.func1" +} + +func q(x int) int { + foo := func() int { return x * 2 } // ERROR "can inline q.func1" "q func literal does not escape" + return foo() // ERROR "inlining call to q.func1" +} + +func r(z int) int { + foo := func(x int) int { // ERROR "can inline r.func1" "r func literal does not escape" + return x + z + } + bar := func(x int) int { // ERROR "r func literal does not escape" + return x + func(y int) int { // ERROR "can inline r.func2.1" + return 2*y + x*z + }(x) // ERROR "inlining call to r.func2.1" + } + return foo(42) + bar(42) // ERROR "inlining call to r.func1" +} + +func s0(x int) int { + foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape" + x = x + 1 + } + foo() // ERROR "inlining call to s0.func1" "&x does not escape" + return x +} + +func s1(x int) int { + foo := func() int { // ERROR "can inline s1.func1" "s1 func literal does not escape" + return x + } + x = x + 1 + return foo() // ERROR "inlining call to s1.func1" "&x does not escape" +} + // can't currently inline functions with a break statement func switchBreak(x, y int) int { var n int @@ -72,3 +152,13 @@ func switchType(x interface{}) int { // ERROR "switchType x does not escape" return 0 } } + +type T struct{} + +func (T) meth(int, int) {} // ERROR "can inline T.meth" + +func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k" + +func _() { // ERROR "can inline _" + T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth" +} diff --git a/test/inline_callers.go b/test/inline_callers.go index fb6ff6c7..6df68619 100644 --- a/test/inline_callers.go +++ b/test/inline_callers.go @@ -1,4 +1,4 @@ -// run -gcflags -l=4 +// run -gcflags=-l=4 // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -7,7 +7,7 @@ package main import ( - "log" + "fmt" "runtime" ) @@ -83,13 +83,13 @@ func main() { frames := testCallers(i) expected := expectedFrames[i] if !same(frames, expected) { - log.Fatalf("testCallers(%d):\n got %v\n want %v", i, frames, expected) + fmt.Printf("testCallers(%d):\n got %v\n want %v\n", i, frames, expected) } frames = testCallersFrames(i) expected = allFrames[i:] if !same(frames, expected) { - log.Fatalf("testCallersFrames(%d):\n got %v\n want %v", i, frames, expected) + fmt.Printf("testCallersFrames(%d):\n got %v\n want %v\n", i, frames, expected) } } } diff --git a/test/intrinsic_atomic.go b/test/intrinsic_atomic.go index dd765a0f..a90056e1 100644 --- a/test/intrinsic_atomic.go +++ b/test/intrinsic_atomic.go @@ -1,5 +1,5 @@ // errorcheck -0 -d=ssa/intrinsics/debug -// +build amd64 arm64 +// +build amd64 arm64 mips mipsle mips64 mips64le ppc64 ppc64le s390x // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/live.go b/test/live.go index ef988a05..e54336ea 100644 --- a/test/live.go +++ b/test/live.go @@ -239,15 +239,6 @@ func f14() { func g14() string -func f15() { - var x string - _ = &x - x = g15() // ERROR "live at call to g15: x$" - printstring(x) // ERROR "live at call to printstring: x$" -} - -func g15() string - // Checking that various temporaries do not persist or cause // ambiguously live values that must be zeroed. // The exact temporary names are inconsequential but we are @@ -384,10 +375,9 @@ func f25(b bool) { return } var x string - _ = &x - x = g15() // ERROR "live at call to g15: x$" - printstring(x) // ERROR "live at call to printstring: x$" -} // ERROR "live at call to deferreturn: x$" + x = g14() + printstring(x) +} func g25() @@ -473,22 +463,30 @@ func f29(b bool) { } // copy of array of pointers should die at end of range loop +var pstructarr [10]pstruct -var ptrarr [10]*int +// Struct size choosen to make pointer to element in pstructarr +// not computable by strength reduction. +type pstruct struct { + intp *int + _ [8]byte +} func f30(b bool) { - // two live temps during print(p): - // the copy of ptrarr and the internal iterator pointer. + // two live temps during printintpointer(p): + // in the copy of p.intp and + // the internal iterator pointer if a pointer to pstruct in pstructarr + // can not be easily computed by strength reduction. if b { - for _, p := range ptrarr { - printintpointer(p) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" + for _, p := range pstructarr { + printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" } } - for _, p := range ptrarr { - printintpointer(p) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" + for _, p := range pstructarr { + printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" } - for _, p := range ptrarr { - printintpointer(p) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" + for _, p := range pstructarr { + printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+ .autotmp_[0-9]+$" } } @@ -641,9 +639,12 @@ type T40 struct { m map[int]int } +//go:noescape +func useT40(*T40) + func newT40() *T40 { ret := T40{} - ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret$" + ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$" return &ret } @@ -655,10 +656,10 @@ func bad40() { func good40() { ret := T40{} - ret.m = make(map[int]int) // ERROR "live at call to makemap: .autotmp_[0-9]+ ret$" + ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+ ret$" t := &ret printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ ret$" - _ = t + useT40(t) // ERROR "live at call to useT40: .autotmp_[0-9]+ ret$" } func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$" diff --git a/test/live2.go b/test/live2.go index 6138d369..cc1b0b7a 100644 --- a/test/live2.go +++ b/test/live2.go @@ -14,26 +14,29 @@ package main func printnl() +//go:noescape +func useT40(*T40) + type T40 struct { m map[int]int } func newT40() *T40 { ret := T40{} - ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret$" + ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$" return &ret } func bad40() { t := newT40() // ERROR "live at call to makemap: .autotmp_[0-9]+ ret$" printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ ret$" - _ = t + useT40(t) // ERROR "live at call to useT40: .autotmp_[0-9]+ ret$" } func good40() { ret := T40{} - ret.m = make(map[int]int) // ERROR "live at call to makemap: .autotmp_[0-9]+ ret$" + ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: .autotmp_[0-9]+ ret$" t := &ret printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ ret$" - _ = t + useT40(t) // ERROR "live at call to useT40: .autotmp_[0-9]+ ret$" } diff --git a/test/live_syscall.go b/test/live_syscall.go index f693e935..6d954653 100644 --- a/test/live_syscall.go +++ b/test/live_syscall.go @@ -26,3 +26,15 @@ func h() { var v int syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "h &v does not escape" } + +func i() { + var t int + p := unsafe.Pointer(&t) // ERROR "i &t does not escape" + f(uintptr(p)) // ERROR "live at call to f: .?autotmp" +} + +func j() { + var v int + p := unsafe.Pointer(&v) // ERROR "j &v does not escape" + syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" +} diff --git a/test/makechan.go b/test/makechan.go new file mode 100644 index 00000000..0ac38c4b --- /dev/null +++ b/test/makechan.go @@ -0,0 +1,34 @@ +// errorcheck + +// Copyright 2017 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. + +// Ensure that typed non-integer, negative and to large +// values are not accepted as size argument in make for +// channels. + +package main + +type T chan byte + +var sink T + +func main() { + sink = make(T, -1) // ERROR "negative buffer argument in make.*" + sink = make(T, uint64(1<<63)) // ERROR "buffer argument too large in make.*" + + sink = make(T, 0.5) // ERROR "constant 0.5 truncated to integer" + sink = make(T, 1.0) + sink = make(T, float32(1.0)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, float64(1.0)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, 1.0) + sink = make(T, float32(1.0)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, float64(1.0)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, 1+0i) + sink = make(T, complex64(1+0i)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, complex128(1+0i)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, 1+0i) + sink = make(T, complex64(1+0i)) // ERROR "non-integer buffer argument in make.*" + sink = make(T, complex128(1+0i)) // ERROR "non-integer buffer argument in make.*" +} diff --git a/test/makemap.go b/test/makemap.go new file mode 100644 index 00000000..60983c0d --- /dev/null +++ b/test/makemap.go @@ -0,0 +1,34 @@ +// errorcheck + +// Copyright 2017 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. + +// Ensure that typed non-integer, negative and too large +// values are not accepted as size argument in make for +// maps. + +package main + +type T map[int]int + +var sink T + +func main() { + sink = make(T, -1) // ERROR "negative size argument in make.*" + sink = make(T, uint64(1<<63)) // ERROR "size argument too large in make.*" + + sink = make(T, 0.5) // ERROR "constant 0.5 truncated to integer" + sink = make(T, 1.0) + sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*" + sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*" + sink = make(T, 1.0) + sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*" + sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*" + sink = make(T, 1+0i) + sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*" + sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*" + sink = make(T, 1+0i) + sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*" + sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*" +} diff --git a/test/mergemul.go b/test/mergemul.go new file mode 100644 index 00000000..a23115b6 --- /dev/null +++ b/test/mergemul.go @@ -0,0 +1,117 @@ +// runoutput + +// Copyright 2017 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. + +package main + +import "fmt" + +// Check that expressions like (c*n + d*(n+k)) get correctly merged by +// the compiler into (c+d)*n + d*k (with c+d and d*k computed at +// compile time). +// +// The merging is performed by a combination of the multiplication +// merge rules +// (c*n + d*n) -> (c+d)*n +// and the distributive multiplication rules +// c * (d+x) -> c*d + c*x + +// Generate a MergeTest that looks like this: +// +// a8, b8 = m1*n8 + m2*(n8+k), (m1+m2)*n8 + m2*k +// if a8 != b8 { +// // print error msg and panic +// } +func makeMergeAddTest(m1, m2, k int, size string) string { + + model := " a" + size + ", b" + size + model += fmt.Sprintf(" = %%d*n%s + %%d*(n%s+%%d), (%%d+%%d)*n%s + (%%d*%%d)", size, size, size) + + test := fmt.Sprintf(model, m1, m2, k, m1, m2, m2, k) + test += fmt.Sprintf(` + if a%s != b%s { + fmt.Printf("MergeAddTest(%d, %d, %d, %s) failed\n") + fmt.Printf("%%d != %%d\n", a%s, b%s) + panic("FAIL") + } +`, size, size, m1, m2, k, size, size, size) + return test + "\n" +} + +// Check that expressions like (c*n - d*(n+k)) get correctly merged by +// the compiler into (c-d)*n - d*k (with c-d and d*k computed at +// compile time). +// +// The merging is performed by a combination of the multiplication +// merge rules +// (c*n - d*n) -> (c-d)*n +// and the distributive multiplication rules +// c * (d-x) -> c*d - c*x + +// Generate a MergeTest that looks like this: +// +// a8, b8 = m1*n8 - m2*(n8+k), (m1-m2)*n8 - m2*k +// if a8 != b8 { +// // print error msg and panic +// } +func makeMergeSubTest(m1, m2, k int, size string) string { + + model := " a" + size + ", b" + size + model += fmt.Sprintf(" = %%d*n%s - %%d*(n%s+%%d), (%%d-%%d)*n%s - (%%d*%%d)", size, size, size) + + test := fmt.Sprintf(model, m1, m2, k, m1, m2, m2, k) + test += fmt.Sprintf(` + if a%s != b%s { + fmt.Printf("MergeSubTest(%d, %d, %d, %s) failed\n") + fmt.Printf("%%d != %%d\n", a%s, b%s) + panic("FAIL") + } +`, size, size, m1, m2, k, size, size, size) + return test + "\n" +} + +func makeAllSizes(m1, m2, k int) string { + var tests string + tests += makeMergeAddTest(m1, m2, k, "8") + tests += makeMergeAddTest(m1, m2, k, "16") + tests += makeMergeAddTest(m1, m2, k, "32") + tests += makeMergeAddTest(m1, m2, k, "64") + tests += makeMergeSubTest(m1, m2, k, "8") + tests += makeMergeSubTest(m1, m2, k, "16") + tests += makeMergeSubTest(m1, m2, k, "32") + tests += makeMergeSubTest(m1, m2, k, "64") + tests += "\n" + return tests +} + +func main() { + fmt.Println(`package main + +import "fmt" + +var n8 int8 = 42 +var n16 int16 = 42 +var n32 int32 = 42 +var n64 int64 = 42 + +func main() { + var a8, b8 int8 + var a16, b16 int16 + var a32, b32 int32 + var a64, b64 int64 +`) + + fmt.Println(makeAllSizes(03, 05, 0)) // 3*n + 5*n + fmt.Println(makeAllSizes(17, 33, 0)) + fmt.Println(makeAllSizes(80, 45, 0)) + fmt.Println(makeAllSizes(32, 64, 0)) + + fmt.Println(makeAllSizes(7, 11, +1)) // 7*n + 11*(n+1) + fmt.Println(makeAllSizes(9, 13, +2)) + fmt.Println(makeAllSizes(11, 16, -1)) + fmt.Println(makeAllSizes(17, 9, -2)) + + fmt.Println("}") +} diff --git a/test/method2.go b/test/method2.go index e55aee42..a45a9431 100644 --- a/test/method2.go +++ b/test/method2.go @@ -35,3 +35,7 @@ var pv = &v var _ = pv.val() // ERROR "pv.val undefined" var _ = pv.val // ERROR "pv.val undefined" + +func (t *T) g() int { return t.a } + +var _ = (T).g() // ERROR "needs pointer receiver|undefined" diff --git a/test/method6.go b/test/method6.go new file mode 100644 index 00000000..20eccce4 --- /dev/null +++ b/test/method6.go @@ -0,0 +1,22 @@ +// errorcheck + +// Copyright 2017 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. + +// Verify that pointer method calls are caught during typechecking. +// Reproducer extracted and adapted from method.go + +package foo + +type A struct { + B +} +type B int + +func (*B) g() {} + +var _ = func() { + var a A + A(a).g() // ERROR "cannot call pointer method on|cannot take the address of" +} diff --git a/test/method7.go b/test/method7.go new file mode 100644 index 00000000..72c88b37 --- /dev/null +++ b/test/method7.go @@ -0,0 +1,56 @@ +// run + +// Copyright 2017 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 forms of method expressions T.m where T is +// a literal type. + +package main + +var got, want string + +type I interface { + m() +} + +type S struct { +} + +func (S) m() { got += " m()" } +func (S) m1(s string) { got += " m1(" + s + ")" } + +type T int + +func (T) m2() { got += " m2()" } + +func main() { + // method expressions with named receiver types + I.m(S{}) + want += " m()" + + S.m1(S{}, "a") + want += " m1(a)" + + // method expressions with literal receiver types + f := interface{ m1(string) }.m1 + f(S{}, "b") + want += " m1(b)" + + interface{ m1(string) }.m1(S{}, "c") + want += " m1(c)" + + x := S{} + interface{ m1(string) }.m1(x, "d") + want += " m1(d)" + + // cannot link the call below - see #22444 + // g := struct{ T }.m2 + // g(struct{T}{}) + // want += " m2()" + + if got != want { + panic("got" + got + ", want" + want) + } +} diff --git a/test/nilptr3.go b/test/nilptr3.go index 195c8ca0..9a96bb53 100644 --- a/test/nilptr3.go +++ b/test/nilptr3.go @@ -259,3 +259,10 @@ func f7() (*Struct, float64) { func f8(t *[8]int) [8]int { return *t // ERROR "removed nil check" } + +func f9() []int { + x := new([1]int) + x[0] = 1 // ERROR "removed nil check" + y := x[:] // ERROR "removed nil check" + return y +} diff --git a/test/nosplit.go b/test/nosplit.go index 989d8ccb..e6cecebd 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -115,15 +115,15 @@ main 132 main 136 # A nosplit leaf can use the whole 128-CallSize bytes available on entry. -# (CallSize is 32 on ppc64) +# (CallSize is 32 on ppc64, 8 on amd64 for frame pointer.) main 96 nosplit main 100 nosplit; REJECT ppc64 ppc64le main 104 nosplit; REJECT ppc64 ppc64le main 108 nosplit; REJECT ppc64 ppc64le main 112 nosplit; REJECT ppc64 ppc64le main 116 nosplit; REJECT ppc64 ppc64le -main 120 nosplit; REJECT ppc64 ppc64le -main 124 nosplit; REJECT ppc64 ppc64le +main 120 nosplit; REJECT ppc64 ppc64le amd64 +main 124 nosplit; REJECT ppc64 ppc64le amd64 main 128 nosplit; REJECT main 132 nosplit; REJECT main 136 nosplit; REJECT @@ -132,13 +132,14 @@ main 136 nosplit; REJECT # having room for the saved caller PC and the called frame. # Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes. # Because arm64 doesn't save LR in the leaf, it gets an extra 8 bytes. -# ppc64 doesn't save LR in the leaf, but CallSize is 32, so it gets 24 fewer bytes than amd64. +# ppc64 doesn't save LR in the leaf, but CallSize is 32, so it gets 24 bytes. +# Because AMD64 uses frame pointer, it has 8 fewer bytes. main 96 nosplit call f; f 0 nosplit main 100 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le main 104 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le main 108 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le -main 112 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le -main 116 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le +main 112 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 +main 116 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 main 120 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 main 124 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 386 main 128 nosplit call f; f 0 nosplit; REJECT @@ -148,11 +149,11 @@ main 136 nosplit call f; f 0 nosplit; REJECT # Calling a splitting function from a nosplit function requires # having room for the saved caller PC of the call but also the # saved caller PC for the call to morestack. -# RISC architectures differ in the same way as before. +# Architectures differ in the same way as before. main 96 nosplit call f; f 0 call f main 100 nosplit call f; f 0 call f; REJECT ppc64 ppc64le -main 104 nosplit call f; f 0 call f; REJECT ppc64 ppc64le -main 108 nosplit call f; f 0 call f; REJECT ppc64 ppc64le +main 104 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 +main 108 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 main 112 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 main 116 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 main 120 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 386 @@ -164,8 +165,8 @@ main 136 nosplit call f; f 0 call f; REJECT # Indirect calls are assumed to be splitting functions. main 96 nosplit callind main 100 nosplit callind; REJECT ppc64 ppc64le -main 104 nosplit callind; REJECT ppc64 ppc64le -main 108 nosplit callind; REJECT ppc64 ppc64le +main 104 nosplit callind; REJECT ppc64 ppc64le amd64 +main 108 nosplit callind; REJECT ppc64 ppc64le amd64 main 112 nosplit callind; REJECT ppc64 ppc64le amd64 main 116 nosplit callind; REJECT ppc64 ppc64le amd64 main 120 nosplit callind; REJECT ppc64 ppc64le amd64 386 @@ -198,18 +199,14 @@ func main() { goarch = runtime.GOARCH } - // Frame pointer is on by default now. - // golang.org/issue/18317. - return - version, err := exec.Command("go", "tool", "compile", "-V").Output() if err != nil { bug() fmt.Printf("running go tool compile -V: %v\n", err) return } - if strings.Contains(string(version), "framepointer") { - // Skip this test if GOEXPERIMENT=framepointer + if s := string(version); goarch == "amd64" && strings.Contains(s, "X:") && !strings.Contains(s, "framepointer") { + // Skip this test if framepointer is NOT enabled on AMD64 return } @@ -266,18 +263,18 @@ TestCases: ptrSize := 4 switch goarch { case "mips", "mipsle": - fmt.Fprintf(&buf, "#define CALL JAL\n#define REGISTER (R0)\n") + fmt.Fprintf(&buf, "#define REGISTER (R0)\n") case "mips64", "mips64le": ptrSize = 8 - fmt.Fprintf(&buf, "#define CALL JAL\n#define REGISTER (R0)\n") + fmt.Fprintf(&buf, "#define REGISTER (R0)\n") case "ppc64", "ppc64le": ptrSize = 8 - fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n") + fmt.Fprintf(&buf, "#define REGISTER (CTR)\n") case "arm": - fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") + fmt.Fprintf(&buf, "#define REGISTER (R0)\n") case "arm64": ptrSize = 8 - fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") + fmt.Fprintf(&buf, "#define REGISTER (R0)\n") case "amd64": ptrSize = 8 fmt.Fprintf(&buf, "#define REGISTER AX\n") @@ -307,7 +304,7 @@ TestCases: name := m[1] size, _ := strconv.Atoi(m[2]) - // The limit was originally 128 but is now 592. + // The limit was originally 128 but is now 752 (880-128). // Instead of rewriting the test cases above, adjust // the first stack frame to use up the extra bytes. if i == 0 { diff --git a/test/notinheap3.go b/test/notinheap3.go new file mode 100644 index 00000000..d48c2a0c --- /dev/null +++ b/test/notinheap3.go @@ -0,0 +1,60 @@ +// errorcheck -+ -0 -l -d=wb + +// Copyright 2016 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 write barrier elimination for notinheap. + +package p + +type t1 struct { + x *nih + s []nih + y [1024]byte // Prevent write decomposition +} + +type t2 struct { + x *ih + s []ih + y [1024]byte +} + +//go:notinheap +type nih struct { + x uintptr +} + +type ih struct { // In-heap type + x uintptr +} + +var ( + v1 t1 + v2 t2 + + v1s []t1 + v2s []t2 +) + +func f() { + // Test direct writes + v1.x = nil // no barrier + v2.x = nil // ERROR "write barrier" + v1.s = []nih(nil) // no barrier + v2.s = []ih(nil) // ERROR "write barrier" +} + +func g() { + // Test aggregate writes + v1 = t1{x: nil} // no barrier + v2 = t2{x: nil} // ERROR "write barrier" +} + +func h() { + // Test copies and appends. + copy(v1s, v1s[1:]) // no barrier + copy(v2s, v2s[1:]) // ERROR "write barrier" + _ = append(v1s, v1s...) // no barrier + _ = append(v2s, v2s...) // ERROR "write barrier" +} diff --git a/test/nowritebarrier.go b/test/nowritebarrier.go index 23dce753..64666fa5 100644 --- a/test/nowritebarrier.go +++ b/test/nowritebarrier.go @@ -76,3 +76,18 @@ func d3() { func d4() { d2() } + +//go:noinline +func systemstack(func()) {} + +//go:nowritebarrierrec +func e1() { + systemstack(e2) + systemstack(func() { + x.f = y // ERROR "write barrier prohibited by caller" + }) +} + +func e2() { + x.f = y // ERROR "write barrier prohibited by caller" +} diff --git a/test/print.go b/test/print.go index 466e19f1..b7f3db0a 100644 --- a/test/print.go +++ b/test/print.go @@ -19,6 +19,11 @@ func main() { println(([]int)(nil)) // printslice println(int64(-7)) // printint println(uint64(7)) // printuint + println(uint32(7)) // printuint + println(uint16(7)) // printuint + println(uint8(7)) // printuint + println(uint(7)) // printuint + println(uintptr(7)) // printuint println(8.0) // printfloat println(complex(9.0, 10.0)) // printcomplex println(true) // printbool @@ -28,11 +33,18 @@ func main() { // test goprintf defer println((interface{})(nil)) - defer println((interface{f()})(nil)) + defer println((interface { + f() + })(nil)) defer println((map[int]int)(nil)) defer println(([]int)(nil)) defer println(int64(-11)) defer println(uint64(12)) + defer println(uint32(12)) + defer println(uint16(12)) + defer println(uint8(12)) + defer println(uint(12)) + defer println(uintptr(12)) defer println(13.0) defer println(complex(14.0, 15.0)) defer println(true) diff --git a/test/print.out b/test/print.out index 266fe5d6..85376af0 100644 --- a/test/print.out +++ b/test/print.out @@ -4,6 +4,11 @@ [0/0]0x0 -7 7 +7 +7 +7 +7 +7 +8.000000e+000 (+9.000000e+000+1.000000e+001i) true @@ -17,6 +22,11 @@ true (+1.400000e+001+1.500000e+001i) +1.300000e+001 12 +12 +12 +12 +12 +12 -11 [0/0]0x0 0x0 diff --git a/test/range.go b/test/range.go index afdac57f..3da7d170 100644 --- a/test/range.go +++ b/test/range.go @@ -23,12 +23,57 @@ func seq(lo, hi int) chan int { return c } +const alphabet = "abcdefghijklmnopqrstuvwxyz" + +func testblankvars() { + n := 0 + for range alphabet { + n++ + } + if n != 26 { + println("for range: wrong count", n, "want 26") + panic("fail") + } + n = 0 + for _ = range alphabet { + n++ + } + if n != 26 { + println("for _ = range: wrong count", n, "want 26") + panic("fail") + } + n = 0 + for _, _ = range alphabet { + n++ + } + if n != 26 { + println("for _, _ = range: wrong count", n, "want 26") + panic("fail") + } + s := 0 + for i, _ := range alphabet { + s += i + } + if s != 325 { + println("for i, _ := range: wrong sum", s, "want 325") + panic("fail") + } + r := rune(0) + for _, v := range alphabet { + r += v + } + if r != 2847 { + println("for _, v := range: wrong sum", r, "want 2847") + panic("fail") + } +} + func testchan() { s := "" for i := range seq('a', 'z') { s += string(i) } - if s != "abcdefghijklmnopqrstuvwxyz" { + if s != alphabet { println("Wanted lowercase alphabet; got", s) panic("fail") } @@ -38,6 +83,7 @@ func testchan() { } if n != 26 { println("testchan wrong count", n, "want 26") + panic("fail") } } @@ -426,6 +472,7 @@ func testcalls() { } func main() { + testblankvars() testchan() testarray() testarray1() diff --git a/test/recover4.go b/test/recover4.go index da5117cc..67ed970e 100644 --- a/test/recover4.go +++ b/test/recover4.go @@ -68,6 +68,6 @@ func main() { log.Fatal("no error from memcopy across memory hole") } if n != 8*size-5 { - log.Fatal("memcopy returned %d, want %d", n, 8*size-5) + log.Fatalf("memcopy returned %d, want %d", n, 8*size-5) } } diff --git a/test/rename1.go b/test/rename1.go index a71e5b2e..568aa13d 100644 --- a/test/rename1.go +++ b/test/rename1.go @@ -10,10 +10,10 @@ package main func main() { - var n byte // ERROR "not a type|expected type" + var n byte // ERROR "not a type|expected type" var y = float32(0) // ERROR "cannot call|expected function" const ( - a = 1 + iota // ERROR "string|incompatible types" "convert iota" + a = 1 + iota // ERROR "invalid operation|incompatible types" "cannot convert iota" ) } diff --git a/test/run.go b/test/run.go index 2fa20674..22ec7576 100644 --- a/test/run.go +++ b/test/run.go @@ -417,6 +417,14 @@ func (ctxt *context) match(name string) bool { func init() { checkShouldTest() } +// goGcflags returns the -gcflags argument to use with go build / go run. +// This must match the flags used for building the standard libary, +// or else the commands will rebuild any needed packages (like runtime) +// over and over. +func goGcflags() string { + return "-gcflags=" + os.Getenv("GO_GCFLAGS") +} + // run runs a test. func (t *test) run() { start := time.Now() @@ -701,7 +709,7 @@ func (t *test) run() { } case "build": - _, err := runcmd("go", "build", "-o", "a.exe", long) + _, err := runcmd("go", "build", goGcflags(), "-o", "a.exe", long) if err != nil { t.err = err } @@ -728,6 +736,9 @@ func (t *test) run() { } var objs []string cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"} + if len(asms) > 0 { + cmd = append(cmd, "-asmhdr", "go_asm.h") + } for _, file := range gos { cmd = append(cmd, filepath.Join(longdir, file.Name())) } @@ -766,7 +777,7 @@ func (t *test) run() { case "buildrun": // build binary, then run binary, instead of go run. Useful for timeout tests where failure mode is infinite loop. // TODO: not supported on NaCl useTmp = true - cmd := []string{"go", "build", "-o", "a.exe"} + cmd := []string{"go", "build", goGcflags(), "-o", "a.exe"} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -791,13 +802,38 @@ func (t *test) run() { case "run": useTmp = false - cmd := []string{"go", "run"} - if *linkshared { - cmd = append(cmd, "-linkshared") + var out []byte + var err error + if len(flags)+len(args) == 0 && goGcflags() == "" && !*linkshared { + // If we're not using special go command flags, + // skip all the go command machinery. + // This avoids any time the go command would + // spend checking whether, for example, the installed + // package runtime is up to date. + // Because we run lots of trivial test programs, + // the time adds up. + pkg := filepath.Join(t.tempDir, "pkg.a") + if _, err := runcmd("go", "tool", "compile", "-o", pkg, t.goFileName()); err != nil { + t.err = err + return + } + exe := filepath.Join(t.tempDir, "test.exe") + cmd := []string{"go", "tool", "link", "-s", "-w"} + cmd = append(cmd, "-o", exe, pkg) + if _, err := runcmd(cmd...); err != nil { + t.err = err + return + } + out, err = runcmd(append([]string{exe}, args...)...) + } else { + cmd := []string{"go", "run", goGcflags()} + if *linkshared { + cmd = append(cmd, "-linkshared") + } + cmd = append(cmd, flags...) + cmd = append(cmd, t.goFileName()) + out, err = runcmd(append(cmd, args...)...) } - cmd = append(cmd, flags...) - cmd = append(cmd, t.goFileName()) - out, err := runcmd(append(cmd, args...)...) if err != nil { t.err = err return @@ -812,7 +848,7 @@ func (t *test) run() { <-rungatec }() useTmp = false - cmd := []string{"go", "run"} + cmd := []string{"go", "run", goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -827,7 +863,7 @@ func (t *test) run() { t.err = fmt.Errorf("write tempfile:%s", err) return } - cmd = []string{"go", "run"} + cmd = []string{"go", "run", goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } @@ -843,7 +879,7 @@ func (t *test) run() { case "errorcheckoutput": useTmp = false - cmd := []string{"go", "run"} + cmd := []string{"go", "run", goGcflags()} if *linkshared { cmd = append(cmd, "-linkshared") } diff --git a/test/shift1.go b/test/shift1.go index c81ee515..01ecbed5 100644 --- a/test/shift1.go +++ b/test/shift1.go @@ -152,8 +152,7 @@ func _() { var a []int _ = a[1<<s] _ = a[1.] - // For now, the spec disallows these. We may revisit past Go 1.1. - _ = a[1.<<s] // ERROR "integer|shift of type float64" + _ = a[1.<<s] _ = a[1.1<<s] // ERROR "integer|shift of type float64" _ = make([]int, 1) |