Source file test/fixedbugs/issue15329.go
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 31 package main 32 33 import ( 34 "fmt" 35 "reflect" 36 "runtime" 37 "unsafe" 38 ) 39 40 func 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 56 func 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 63 func testMeth(x int) reflect.Value { 64 // Force GC to run. 65 runtime.GC() 66 return reflect.ValueOf(&x) 67 } 68 69 type Pointerer interface { 70 Pointer() uintptr 71 } 72 73 func testInter(x int) Pointerer { 74 return testMeth(x) 75 } 76 77 func testFunc(x int) func() uintptr { 78 return testMeth(x).Pointer 79 } 80