mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
![Robert Griesemer](/assets/img/avatar_default.png)
Until now, the parser set the position for each Node to the position of the first token belonging to that node. For compatibility with the now defunct gc parser, in many places that position information was modified when the gcCompat flag was set (which it was, by default). Furthermore, in some places, position information was not set at all. This change removes the gcCompat flag and all associated code, and sets position information for all nodes in a more principled way, as proposed by mdempsky (see #16943 for details). Specifically, the position of a node may not be at the very beginning of the respective production. For instance for an Operation `a + b`, the position associated with the node is the position of the `+`. Thus, for `a + b + c` we now get different positions for the two additions. This change does not pass toolstash -cmp because position information recorded in export data and pcline tables is different. There are no other functional changes. Added test suite testing the position of all nodes. Fixes #16943. Change-Id: I3fc02bf096bc3b3d7d2fa655dfd4714a1a0eb90c Reviewed-on: https://go-review.googlesource.com/37017 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
174 lines
5.3 KiB
Go
174 lines
5.3 KiB
Go
// errorcheck -0 -m -l
|
|
|
|
// Copyright 2015 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.
|
|
|
|
// Test escape analysis for closure arguments.
|
|
|
|
package escape
|
|
|
|
var sink interface{}
|
|
|
|
func ClosureCallArgs0() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
|
|
*p = 1
|
|
// BAD: x should not escape to heap here
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs1() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
for {
|
|
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
|
|
*p = 1
|
|
// BAD: x should not escape to heap here
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
}
|
|
|
|
func ClosureCallArgs2() {
|
|
for {
|
|
// BAD: x should not escape here
|
|
x := 0 // ERROR "moved to heap: x"
|
|
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
|
|
*p = 1
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
}
|
|
|
|
func ClosureCallArgs3() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
|
|
sink = p // ERROR "p escapes to heap"
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs4() {
|
|
// BAD: x should not leak here
|
|
x := 0 // ERROR "moved to heap: x"
|
|
_ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
|
|
return p
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs5() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
sink = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" "\(func literal\)\(&x\) escapes to heap"
|
|
return p
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs6() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
|
|
sink = &p // ERROR "&p escapes to heap"
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs7() {
|
|
var pp *int
|
|
for {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
|
|
pp = p
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
_ = pp
|
|
}
|
|
|
|
func ClosureCallArgs8() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
|
|
*p = 1
|
|
// BAD: x should not escape to heap here
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs9() {
|
|
// BAD: x should not leak
|
|
x := 0 // ERROR "moved to heap: x"
|
|
for {
|
|
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
|
|
*p = 1
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
}
|
|
|
|
func ClosureCallArgs10() {
|
|
for {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
|
|
*p = 1
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
}
|
|
|
|
func ClosureCallArgs11() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
|
|
sink = p // ERROR "p escapes to heap"
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs12() {
|
|
// BAD: x should not leak
|
|
x := 0 // ERROR "moved to heap: x"
|
|
defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
|
|
return p
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs13() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
|
|
sink = &p // ERROR "&p escapes to heap"
|
|
}(&x) // ERROR "&x escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs14() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
// BAD: &x should not escape here
|
|
p := &x // ERROR "moved to heap: p" "&x escapes to heap"
|
|
_ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape"
|
|
return *p
|
|
// BAD: p should not escape here
|
|
}(&p) // ERROR "&p escapes to heap"
|
|
}
|
|
|
|
func ClosureCallArgs15() {
|
|
x := 0 // ERROR "moved to heap: x"
|
|
p := &x // ERROR "moved to heap: p" "&x escapes to heap"
|
|
sink = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap"
|
|
return *p
|
|
// BAD: p should not escape here
|
|
}(&p) // ERROR "&p escapes to heap"
|
|
}
|
|
|
|
func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
|
|
t := s + "YYYY" // ERROR "escapes to heap"
|
|
return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape"
|
|
}
|
|
|
|
// See #14409 -- returning part of captured var leaks it.
|
|
func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
|
|
return func() string { // ERROR "ClosureLeak1a func literal does not escape"
|
|
return a[0]
|
|
}()
|
|
}
|
|
|
|
func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
|
|
t := s + "YYYY" // ERROR "escapes to heap"
|
|
c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
|
|
return c
|
|
}
|
|
func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
|
|
return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
|
|
return a[0]
|
|
})
|
|
}
|
|
func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1"
|
|
return f()
|
|
}
|