mirror of
https://github.com/golang/go
synced 2024-11-26 17:46:57 -07:00
23943a6737
In CL 253457, we did the same fix for direct function calls. But for method calls, the receiver argument also need to be passed through the wrapper function, which we are not doing so the compiler crashes with the code in #44415. It will be nicer if we can rewrite OCALLMETHOD to normal OCALLFUNC, but that will be for future CL. The passing receiver argument to wrapper function is easier for backporting to go1.16 branch. Fixes #44415 Change-Id: I03607a64429042c6066ce673931db9769deb3124 Reviewed-on: https://go-review.googlesource.com/c/go/+/296490 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org>
97 lines
1.9 KiB
Go
97 lines
1.9 KiB
Go
// 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
|
|
}
|