diff options
Diffstat (limited to 'test/fixedbugs/issue24491a.go')
-rw-r--r-- | test/fixedbugs/issue24491a.go | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/test/fixedbugs/issue24491a.go b/test/fixedbugs/issue24491a.go new file mode 100644 index 0000000..d30b65b --- /dev/null +++ b/test/fixedbugs/issue24491a.go @@ -0,0 +1,96 @@ +// run + +// Copyright 2020 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. + +// This test makes sure unsafe-uintptr arguments are handled correctly. + +package main + +import ( + "runtime" + "unsafe" +) + +var done = make(chan bool, 1) + +func setup() unsafe.Pointer { + s := "ok" + runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" }) + return unsafe.Pointer(&s) +} + +//go:noinline +//go:uintptrescapes +func test(s string, p, q uintptr, rest ...uintptr) int { + runtime.GC() + runtime.GC() + + if *(*string)(unsafe.Pointer(p)) != "ok" { + panic(s + ": p failed") + } + if *(*string)(unsafe.Pointer(q)) != "ok" { + panic(s + ": q failed") + } + for _, r := range rest { + if *(*string)(unsafe.Pointer(r)) != "ok" { + panic(s + ": r[i] failed") + } + } + + done <- true + return 0 +} + +//go:noinline +func f() int { + return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) +} + +type S struct{} + +//go:noinline +//go:uintptrescapes +func (S) test(s string, p, q uintptr, rest ...uintptr) int { + return test(s, p, q, rest...) +} + +func main() { + test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + <-done + + go test("go", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + <-done + + func() { + defer test("defer", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + }() + <-done + + func() { + for { + defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + break + } + }() + + <-done + func() { + s := &S{} + defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + }() + <-done + + func() { + s := &S{} + for { + defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) + break + } + }() + <-done + + f() + <-done +} |