mirror of
https://github.com/golang/go
synced 2024-11-23 09:10:08 -07:00
7e2e648a2d
Normalizing go/defer statements to always use functions with zero parameters and zero results was added to escape analysis, because that was the earliest point at which all three frontends converged. Now that we only have the unified frontend, we can do it during typecheck, which is where we perform all other desugaring and normalization rewrites. Change-Id: Iebf7679b117fd78b1dffee2974bbf85ebc923b23 Reviewed-on: https://go-review.googlesource.com/c/go/+/520260 Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> TryBot-Result: Gopher Robot <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
|
|
}
|