1// run 2 3// Copyright 2016 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// Previously, cmd/compile would rewrite 8// 9// check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer())) 10// 11// to 12// 13// var autotmp_1 uintptr = testMeth(1).Pointer() 14// var autotmp_2 uintptr = testMeth(2).Pointer() 15// check(unsafe.Pointer(autotmp_1), unsafe.Pointer(autotmp_2)) 16// 17// However, that means autotmp_1 is the only reference to the int 18// variable containing the value "1", but it's not a pointer type, 19// so it was at risk of being garbage collected by the evaluation of 20// testMeth(2).Pointer(), even though package unsafe's documentation 21// says the original code was allowed. 22// 23// Now cmd/compile rewrites it to 24// 25// var autotmp_1 unsafe.Pointer = unsafe.Pointer(testMeth(1).Pointer()) 26// var autotmp_2 unsafe.Pointer = unsafe.Pointer(testMeth(2).Pointer()) 27// check(autotmp_1, autotmp_2) 28// 29// to ensure the pointed-to variables are visible to the GC. 30 31package main 32 33import ( 34 "fmt" 35 "reflect" 36 "runtime" 37 "unsafe" 38) 39 40func main() { 41 // Test all the different ways we can invoke reflect.Value.Pointer. 42 43 // Direct method invocation. 44 check(unsafe.Pointer(testMeth(1).Pointer()), unsafe.Pointer(testMeth(2).Pointer())) 45 46 // Invocation via method expression. 47 check(unsafe.Pointer(reflect.Value.Pointer(testMeth(1))), unsafe.Pointer(reflect.Value.Pointer(testMeth(2)))) 48 49 // Invocation via interface. 50 check(unsafe.Pointer(testInter(1).Pointer()), unsafe.Pointer(testInter(2).Pointer())) 51 52 // Invocation via method value. 53 check(unsafe.Pointer(testFunc(1)()), unsafe.Pointer(testFunc(2)())) 54} 55 56func check(p, q unsafe.Pointer) { 57 a, b := *(*int)(p), *(*int)(q) 58 if a != 1 || b != 2 { 59 fmt.Printf("got %v, %v; expected 1, 2\n", a, b) 60 } 61} 62 63func testMeth(x int) reflect.Value { 64 // Force GC to run. 65 runtime.GC() 66 return reflect.ValueOf(&x) 67} 68 69type Pointerer interface { 70 Pointer() uintptr 71} 72 73func testInter(x int) Pointerer { 74 return testMeth(x) 75} 76 77func testFunc(x int) func() uintptr { 78 return testMeth(x).Pointer 79} 80