diff options
Diffstat (limited to 'test/fixedbugs/issue15329.go')
-rw-r--r-- | test/fixedbugs/issue15329.go | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/test/fixedbugs/issue15329.go b/test/fixedbugs/issue15329.go new file mode 100644 index 0000000..30fbf13 --- /dev/null +++ b/test/fixedbugs/issue15329.go @@ -0,0 +1,79 @@ +// run + +// 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. + +// Previously, cmd/compile would rewrite +// +// check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer())) +// +// to +// +// var autotmp_1 uintptr = testMeth(1).Pointer() +// var autotmp_2 uintptr = testMeth(2).Pointer() +// check(unsafe.Pointer(autotmp_1), unsafe.Pointer(autotmp_2)) +// +// However, that means autotmp_1 is the only reference to the int +// variable containing the value "1", but it's not a pointer type, +// so it was at risk of being garbage collected by the evaluation of +// testMeth(2).Pointer(), even though package unsafe's documentation +// says the original code was allowed. +// +// Now cmd/compile rewrites it to +// +// var autotmp_1 unsafe.Pointer = unsafe.Pointer(testMeth(1).Pointer()) +// var autotmp_2 unsafe.Pointer = unsafe.Pointer(testMeth(2).Pointer()) +// check(autotmp_1, autotmp_2) +// +// to ensure the pointed-to variables are visible to the GC. + +package main + +import ( + "fmt" + "reflect" + "runtime" + "unsafe" +) + +func main() { + // Test all the different ways we can invoke reflect.Value.Pointer. + + // Direct method invocation. + check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer())) + + // Invocation via method expression. + check(unsafe.Pointer(reflect.Value.Pointer(testMeth(1))), unsafe.Pointer(reflect.Value.Pointer(testMeth(2)))) + + // Invocation via interface. + check(unsafe.Pointer(testInter(1).Pointer()), unsafe.Pointer(testInter(2).Pointer())) + + // Invocation via method value. + check(unsafe.Pointer(testFunc(1)()), unsafe.Pointer(testFunc(2)())) +} + +func check(p, q unsafe.Pointer) { + a, b := *(*int)(p), *(*int)(q) + if a != 1 || b != 2 { + fmt.Printf("got %v, %v; expected 1, 2\n", a, b) + } +} + +func testMeth(x int) reflect.Value { + // Force GC to run. + runtime.GC() + return reflect.ValueOf(&x) +} + +type Pointerer interface { + Pointer() uintptr +} + +func testInter(x int) Pointerer { + return testMeth(x) +} + +func testFunc(x int) func() uintptr { + return testMeth(x).Pointer +} |