[dev.garbage] cmd/gc, runtime: add locks around print statements
Now each C printf, Go print, or Go println is guaranteed not to be interleaved with other calls of those functions. This should help when debugging concurrent failures. LGTM=rlh R=rlh CC=golang-codereviews https://golang.org/cl/169120043
This commit is contained in:
parent
91658f934d
commit
75d3f62b3c
@ -24,6 +24,8 @@ char *runtimeimport =
|
|||||||
"func @\"\".printslice (? any)\n"
|
"func @\"\".printslice (? any)\n"
|
||||||
"func @\"\".printnl ()\n"
|
"func @\"\".printnl ()\n"
|
||||||
"func @\"\".printsp ()\n"
|
"func @\"\".printsp ()\n"
|
||||||
|
"func @\"\".printlock ()\n"
|
||||||
|
"func @\"\".printunlock ()\n"
|
||||||
"func @\"\".concatstring2 (? string, ? string) (? string)\n"
|
"func @\"\".concatstring2 (? string, ? string) (? string)\n"
|
||||||
"func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
|
"func @\"\".concatstring3 (? string, ? string, ? string) (? string)\n"
|
||||||
"func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
|
"func @\"\".concatstring4 (? string, ? string, ? string, ? string) (? string)\n"
|
||||||
|
@ -1464,6 +1464,7 @@ void walk(Node *fn);
|
|||||||
void walkexpr(Node **np, NodeList **init);
|
void walkexpr(Node **np, NodeList **init);
|
||||||
void walkexprlist(NodeList *l, NodeList **init);
|
void walkexprlist(NodeList *l, NodeList **init);
|
||||||
void walkexprlistsafe(NodeList *l, NodeList **init);
|
void walkexprlistsafe(NodeList *l, NodeList **init);
|
||||||
|
void walkexprlistcheap(NodeList *l, NodeList **init);
|
||||||
void walkstmt(Node **np);
|
void walkstmt(Node **np);
|
||||||
void walkstmtlist(NodeList *l);
|
void walkstmtlist(NodeList *l);
|
||||||
Node* conv(Node*, Type*);
|
Node* conv(Node*, Type*);
|
||||||
|
@ -36,6 +36,8 @@ func printeface(any)
|
|||||||
func printslice(any)
|
func printslice(any)
|
||||||
func printnl()
|
func printnl()
|
||||||
func printsp()
|
func printsp()
|
||||||
|
func printlock()
|
||||||
|
func printunlock()
|
||||||
|
|
||||||
func concatstring2(string, string) string
|
func concatstring2(string, string) string
|
||||||
func concatstring3(string, string, string) string
|
func concatstring3(string, string, string) string
|
||||||
|
@ -363,6 +363,15 @@ walkexprlistsafe(NodeList *l, NodeList **init)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
walkexprlistcheap(NodeList *l, NodeList **init)
|
||||||
|
{
|
||||||
|
for(; l; l=l->next) {
|
||||||
|
l->n = cheapexpr(l->n, init);
|
||||||
|
walkexpr(&l->n, init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
walkexpr(Node **np, NodeList **init)
|
walkexpr(Node **np, NodeList **init)
|
||||||
{
|
{
|
||||||
@ -1773,6 +1782,11 @@ walkprint(Node *nn, NodeList **init)
|
|||||||
calls = nil;
|
calls = nil;
|
||||||
notfirst = 0;
|
notfirst = 0;
|
||||||
|
|
||||||
|
// Hoist all the argument evaluation up before the lock.
|
||||||
|
walkexprlistcheap(all, init);
|
||||||
|
|
||||||
|
calls = list(calls, mkcall("printlock", T, init));
|
||||||
|
|
||||||
for(l=all; l; l=l->next) {
|
for(l=all; l; l=l->next) {
|
||||||
if(notfirst) {
|
if(notfirst) {
|
||||||
calls = list(calls, mkcall("printsp", T, init));
|
calls = list(calls, mkcall("printsp", T, init));
|
||||||
@ -1853,6 +1867,9 @@ walkprint(Node *nn, NodeList **init)
|
|||||||
|
|
||||||
if(op == OPRINTN)
|
if(op == OPRINTN)
|
||||||
calls = list(calls, mkcall("printnl", T, nil));
|
calls = list(calls, mkcall("printnl", T, nil));
|
||||||
|
|
||||||
|
calls = list(calls, mkcall("printunlock", T, init));
|
||||||
|
|
||||||
typechecklist(calls, Etop);
|
typechecklist(calls, Etop);
|
||||||
walkexprlist(calls, init);
|
walkexprlist(calls, init);
|
||||||
|
|
||||||
|
@ -41,7 +41,31 @@ func snprintf(dst *byte, n int32, s *byte) {
|
|||||||
gp.writebuf = nil
|
gp.writebuf = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//var debuglock mutex
|
var debuglock mutex
|
||||||
|
|
||||||
|
// The compiler emits calls to printlock and printunlock around
|
||||||
|
// the multiple calls that implement a single Go print or println
|
||||||
|
// statement. Some of the print helpers (printsp, for example)
|
||||||
|
// call print recursively. There is also the problem of a crash
|
||||||
|
// happening during the print routines and needing to acquire
|
||||||
|
// the print lock to print information about the crash.
|
||||||
|
// For both these reasons, let a thread acquire the printlock 'recursively'.
|
||||||
|
|
||||||
|
func printlock() {
|
||||||
|
mp := getg().m
|
||||||
|
mp.printlock++
|
||||||
|
if mp.printlock == 1 {
|
||||||
|
lock(&debuglock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printunlock() {
|
||||||
|
mp := getg().m
|
||||||
|
mp.printlock--
|
||||||
|
if mp.printlock == 0 {
|
||||||
|
unlock(&debuglock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// write to goroutine-local buffer if diverting output,
|
// write to goroutine-local buffer if diverting output,
|
||||||
// or else standard error.
|
// or else standard error.
|
||||||
@ -80,7 +104,7 @@ func printnl() {
|
|||||||
// Very simple printf. Only for debugging prints.
|
// Very simple printf. Only for debugging prints.
|
||||||
// Do not add to this without checking with Rob.
|
// Do not add to this without checking with Rob.
|
||||||
func vprintf(str string, arg unsafe.Pointer) {
|
func vprintf(str string, arg unsafe.Pointer) {
|
||||||
//lock(&debuglock);
|
printlock()
|
||||||
|
|
||||||
s := bytes(str)
|
s := bytes(str)
|
||||||
start := 0
|
start := 0
|
||||||
@ -160,7 +184,7 @@ func vprintf(str string, arg unsafe.Pointer) {
|
|||||||
gwrite(s[start:i])
|
gwrite(s[start:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
//unlock(&debuglock);
|
printunlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func printpc(p unsafe.Pointer) {
|
func printpc(p unsafe.Pointer) {
|
||||||
|
@ -345,6 +345,7 @@ struct M
|
|||||||
int32 helpgc;
|
int32 helpgc;
|
||||||
bool spinning; // M is out of work and is actively looking for work
|
bool spinning; // M is out of work and is actively looking for work
|
||||||
bool blocked; // M is blocked on a Note
|
bool blocked; // M is blocked on a Note
|
||||||
|
int8 printlock;
|
||||||
uint32 fastrand;
|
uint32 fastrand;
|
||||||
uint64 ncgocall; // number of cgo calls in total
|
uint64 ncgocall; // number of cgo calls in total
|
||||||
int32 ncgo; // number of cgo calls currently in progress
|
int32 ncgo; // number of cgo calls currently in progress
|
||||||
|
152
test/live.go
152
test/live.go
@ -9,20 +9,39 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
func printnl()
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func printpointer(**int)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func printintpointer(*int)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func printstringpointer(*string)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func printstring(string)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func printbytepointer(*byte)
|
||||||
|
|
||||||
|
func printint(int)
|
||||||
|
|
||||||
func f1() {
|
func f1() {
|
||||||
var x *int
|
var x *int
|
||||||
print(&x) // ERROR "live at call to printpointer: x$"
|
printpointer(&x) // ERROR "live at call to printpointer: x$"
|
||||||
print(&x) // ERROR "live at call to printpointer: x$"
|
printpointer(&x) // ERROR "live at call to printpointer: x$"
|
||||||
}
|
}
|
||||||
|
|
||||||
func f2(b bool) {
|
func f2(b bool) {
|
||||||
if b {
|
if b {
|
||||||
print(0) // nothing live here
|
printint(0) // nothing live here
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var x *int
|
var x *int
|
||||||
print(&x) // ERROR "live at call to printpointer: x$"
|
printpointer(&x) // ERROR "live at call to printpointer: x$"
|
||||||
print(&x) // ERROR "live at call to printpointer: x$"
|
printpointer(&x) // ERROR "live at call to printpointer: x$"
|
||||||
}
|
}
|
||||||
|
|
||||||
func f3(b bool) {
|
func f3(b bool) {
|
||||||
@ -30,22 +49,22 @@ func f3(b bool) {
|
|||||||
// live throughout the function, to avoid being poisoned
|
// live throughout the function, to avoid being poisoned
|
||||||
// in GODEBUG=gcdead=1 mode.
|
// in GODEBUG=gcdead=1 mode.
|
||||||
|
|
||||||
print(0) // ERROR "live at call to printint: x y$"
|
printint(0) // ERROR "live at call to printint: x y$"
|
||||||
if b == false {
|
if b == false {
|
||||||
print(0) // ERROR "live at call to printint: x y$"
|
printint(0) // ERROR "live at call to printint: x y$"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if b {
|
if b {
|
||||||
var x *int
|
var x *int
|
||||||
print(&x) // ERROR "live at call to printpointer: x y$"
|
printpointer(&x) // ERROR "live at call to printpointer: x y$"
|
||||||
print(&x) // ERROR "live at call to printpointer: x y$"
|
printpointer(&x) // ERROR "live at call to printpointer: x y$"
|
||||||
} else {
|
} else {
|
||||||
var y *int
|
var y *int
|
||||||
print(&y) // ERROR "live at call to printpointer: x y$"
|
printpointer(&y) // ERROR "live at call to printpointer: x y$"
|
||||||
print(&y) // ERROR "live at call to printpointer: x y$"
|
printpointer(&y) // ERROR "live at call to printpointer: x y$"
|
||||||
}
|
}
|
||||||
print(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
|
printint(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
|
||||||
}
|
}
|
||||||
|
|
||||||
// The old algorithm treated x as live on all code that
|
// The old algorithm treated x as live on all code that
|
||||||
@ -56,20 +75,20 @@ func f3(b bool) {
|
|||||||
|
|
||||||
func f4(b1, b2 bool) { // x not live here
|
func f4(b1, b2 bool) { // x not live here
|
||||||
if b2 {
|
if b2 {
|
||||||
print(0) // x not live here
|
printint(0) // x not live here
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var z **int
|
var z **int
|
||||||
x := new(int)
|
x := new(int)
|
||||||
*x = 42
|
*x = 42
|
||||||
z = &x
|
z = &x
|
||||||
print(**z) // ERROR "live at call to printint: x z$"
|
printint(**z) // ERROR "live at call to printint: x z$"
|
||||||
if b2 {
|
if b2 {
|
||||||
print(1) // ERROR "live at call to printint: x$"
|
printint(1) // ERROR "live at call to printint: x$"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
print(**z) // ERROR "live at call to printint: x z$"
|
printint(**z) // ERROR "live at call to printint: x z$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +103,7 @@ func f5(b1 bool) {
|
|||||||
*y = 54
|
*y = 54
|
||||||
z = &y
|
z = &y
|
||||||
}
|
}
|
||||||
print(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
|
printint(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live"
|
||||||
}
|
}
|
||||||
|
|
||||||
// confusion about the _ result used to cause spurious "live at entry to f6: _".
|
// confusion about the _ result used to cause spurious "live at entry to f6: _".
|
||||||
@ -155,8 +174,8 @@ func f11b() *int {
|
|||||||
// At this point p is dead: the code here cannot
|
// At this point p is dead: the code here cannot
|
||||||
// get to the bottom of the function.
|
// get to the bottom of the function.
|
||||||
// This used to have a spurious "live at call to printint: p".
|
// This used to have a spurious "live at call to printint: p".
|
||||||
print(1) // nothing live here!
|
printint(1) // nothing live here!
|
||||||
select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
|
select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp"
|
||||||
case <-c: // ERROR "live at call to selectrecv: autotmp"
|
case <-c: // ERROR "live at call to selectrecv: autotmp"
|
||||||
return nil
|
return nil
|
||||||
case <-c: // ERROR "live at call to selectrecv: autotmp"
|
case <-c: // ERROR "live at call to selectrecv: autotmp"
|
||||||
@ -172,8 +191,8 @@ func f11c() *int {
|
|||||||
if b {
|
if b {
|
||||||
// Unlike previous, the cases in this select fall through,
|
// Unlike previous, the cases in this select fall through,
|
||||||
// so we can get to the println, so p is not dead.
|
// so we can get to the println, so p is not dead.
|
||||||
print(1) // ERROR "live at call to printint: p"
|
printint(1) // ERROR "live at call to printint: p"
|
||||||
select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
|
select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p"
|
||||||
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
|
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
|
||||||
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
|
case <-c: // ERROR "live at call to selectrecv: autotmp.* p"
|
||||||
}
|
}
|
||||||
@ -209,7 +228,7 @@ func h13(string, string) string
|
|||||||
|
|
||||||
func f14() {
|
func f14() {
|
||||||
x := g14()
|
x := g14()
|
||||||
print(&x) // ERROR "live at call to printpointer: x"
|
printstringpointer(&x) // ERROR "live at call to printstringpointer: x"
|
||||||
}
|
}
|
||||||
|
|
||||||
func g14() string
|
func g14() string
|
||||||
@ -217,8 +236,8 @@ func g14() string
|
|||||||
func f15() {
|
func f15() {
|
||||||
var x string
|
var x string
|
||||||
_ = &x
|
_ = &x
|
||||||
x = g15() // ERROR "live at call to g15: x"
|
x = g15() // ERROR "live at call to g15: x"
|
||||||
print(x) // ERROR "live at call to printstring: x"
|
printstring(x) // ERROR "live at call to printstring: x"
|
||||||
}
|
}
|
||||||
|
|
||||||
func g15() string
|
func g15() string
|
||||||
@ -282,7 +301,7 @@ func f18() {
|
|||||||
}
|
}
|
||||||
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
print(z)
|
printbytepointer(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ch chan *byte
|
var ch chan *byte
|
||||||
@ -296,7 +315,7 @@ func f19() {
|
|||||||
}
|
}
|
||||||
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
|
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
|
||||||
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
|
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
|
||||||
print(z)
|
printbytepointer(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
func f20() {
|
func f20() {
|
||||||
@ -316,7 +335,7 @@ func f21() {
|
|||||||
}
|
}
|
||||||
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
print(z)
|
printbytepointer(z)
|
||||||
}
|
}
|
||||||
|
|
||||||
func f23() {
|
func f23() {
|
||||||
@ -328,7 +347,8 @@ func f23() {
|
|||||||
}
|
}
|
||||||
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
|
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
|
||||||
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
|
z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
|
||||||
print(z, ok)
|
printbytepointer(z)
|
||||||
|
print(ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
func f24() {
|
func f24() {
|
||||||
@ -350,8 +370,8 @@ func f25(b bool) {
|
|||||||
}
|
}
|
||||||
var x string
|
var x string
|
||||||
_ = &x
|
_ = &x
|
||||||
x = g15() // ERROR "live at call to g15: x"
|
x = g15() // ERROR "live at call to g15: x"
|
||||||
print(x) // ERROR "live at call to printstring: x"
|
printstring(x) // ERROR "live at call to printstring: x"
|
||||||
} // ERROR "live at call to deferreturn: x"
|
} // ERROR "live at call to deferreturn: x"
|
||||||
|
|
||||||
func g25()
|
func g25()
|
||||||
@ -366,7 +386,7 @@ func f26(b bool) {
|
|||||||
}
|
}
|
||||||
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
|
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
|
||||||
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
|
print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -381,7 +401,7 @@ func f27(b bool) {
|
|||||||
}
|
}
|
||||||
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
|
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
|
||||||
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
|
call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
// but defer does escape to later execution in the function
|
// but defer does escape to later execution in the function
|
||||||
@ -392,7 +412,7 @@ func f27defer(b bool) {
|
|||||||
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
|
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
|
defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
|
||||||
println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
|
printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
|
||||||
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
|
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
|
||||||
|
|
||||||
// and newproc (go) escapes to the heap
|
// and newproc (go) escapes to the heap
|
||||||
@ -403,7 +423,7 @@ func f27go(b bool) {
|
|||||||
go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
|
go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
|
||||||
}
|
}
|
||||||
go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
|
go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
@ -415,10 +435,10 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
|
|||||||
|
|
||||||
func f28(b bool) {
|
func f28(b bool) {
|
||||||
if b {
|
if b {
|
||||||
print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
||||||
print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
|
|
||||||
// map iterator should die on end of range loop
|
// map iterator should die on end of range loop
|
||||||
@ -426,14 +446,14 @@ func f28(b bool) {
|
|||||||
func f29(b bool) {
|
func f29(b bool) {
|
||||||
if b {
|
if b {
|
||||||
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
||||||
print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
||||||
print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
|
||||||
print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,14 +466,14 @@ func f30(b bool) {
|
|||||||
// the copy of ptrarr and the internal iterator pointer.
|
// the copy of ptrarr and the internal iterator pointer.
|
||||||
if b {
|
if b {
|
||||||
for _, p := range ptrarr {
|
for _, p := range ptrarr {
|
||||||
print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range ptrarr {
|
for _, p := range ptrarr {
|
||||||
print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
for _, p := range ptrarr {
|
for _, p := range ptrarr {
|
||||||
print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,44 +523,44 @@ var m33 map[interface{}]int
|
|||||||
|
|
||||||
func f33() {
|
func f33() {
|
||||||
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func f34() {
|
func f34() {
|
||||||
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func f35() {
|
func f35() {
|
||||||
if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func f36() {
|
func f36() {
|
||||||
if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
func f37() {
|
func f37() {
|
||||||
if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
|
||||||
println()
|
printnl()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
// select temps should disappear in the case bodies
|
// select temps should disappear in the case bodies
|
||||||
@ -558,44 +578,44 @@ func f38(b bool) {
|
|||||||
if b {
|
if b {
|
||||||
select { // ERROR "live at call"
|
select { // ERROR "live at call"
|
||||||
case <-fc38(): // ERROR "live at call"
|
case <-fc38(): // ERROR "live at call"
|
||||||
println()
|
printnl()
|
||||||
case fc38() <- *fi38(1): // ERROR "live at call"
|
case fc38() <- *fi38(1): // ERROR "live at call"
|
||||||
println()
|
printnl()
|
||||||
case *fi38(2) = <-fc38(): // ERROR "live at call"
|
case *fi38(2) = <-fc38(): // ERROR "live at call"
|
||||||
println()
|
printnl()
|
||||||
case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call"
|
case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call"
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
println()
|
printnl()
|
||||||
}
|
}
|
||||||
|
|
||||||
// issue 8097: mishandling of x = x during return.
|
// issue 8097: mishandling of x = x during return.
|
||||||
|
|
||||||
func f39() (x []int) {
|
func f39() (x []int) {
|
||||||
x = []int{1}
|
x = []int{1}
|
||||||
println() // ERROR "live at call to printnl: x"
|
printnl() // ERROR "live at call to printnl: x"
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func f39a() (x []int) {
|
func f39a() (x []int) {
|
||||||
x = []int{1}
|
x = []int{1}
|
||||||
println() // ERROR "live at call to printnl: x"
|
printnl() // ERROR "live at call to printnl: x"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func f39b() (x [10]*int) {
|
func f39b() (x [10]*int) {
|
||||||
x = [10]*int{}
|
x = [10]*int{}
|
||||||
x[0] = new(int) // ERROR "live at call to newobject: x"
|
x[0] = new(int) // ERROR "live at call to newobject: x"
|
||||||
println() // ERROR "live at call to printnl: x"
|
printnl() // ERROR "live at call to printnl: x"
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func f39c() (x [10]*int) {
|
func f39c() (x [10]*int) {
|
||||||
x = [10]*int{}
|
x = [10]*int{}
|
||||||
x[0] = new(int) // ERROR "live at call to newobject: x"
|
x[0] = new(int) // ERROR "live at call to newobject: x"
|
||||||
println() // ERROR "live at call to printnl: x"
|
printnl() // ERROR "live at call to printnl: x"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,7 +634,7 @@ func newT40() *T40 {
|
|||||||
|
|
||||||
func bad40() {
|
func bad40() {
|
||||||
t := newT40()
|
t := newT40()
|
||||||
println()
|
printnl()
|
||||||
_ = t
|
_ = t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -622,6 +642,6 @@ func good40() {
|
|||||||
ret := T40{}
|
ret := T40{}
|
||||||
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
|
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
|
||||||
t := &ret
|
t := &ret
|
||||||
println() // ERROR "live at call to printnl: ret"
|
printnl() // ERROR "live at call to printnl: ret"
|
||||||
_ = t
|
_ = t
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ package main
|
|||||||
// issue 8142: lost 'addrtaken' bit on inlined variables.
|
// issue 8142: lost 'addrtaken' bit on inlined variables.
|
||||||
// no inlining in this test, so just checking that non-inlined works.
|
// no inlining in this test, so just checking that non-inlined works.
|
||||||
|
|
||||||
|
func printnl()
|
||||||
|
|
||||||
type T40 struct {
|
type T40 struct {
|
||||||
m map[int]int
|
m map[int]int
|
||||||
}
|
}
|
||||||
@ -24,7 +26,7 @@ func newT40() *T40 {
|
|||||||
|
|
||||||
func bad40() {
|
func bad40() {
|
||||||
t := newT40() // ERROR "live at call to makemap: ret"
|
t := newT40() // ERROR "live at call to makemap: ret"
|
||||||
println() // ERROR "live at call to printnl: ret"
|
printnl() // ERROR "live at call to printnl: ret"
|
||||||
_ = t
|
_ = t
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +34,6 @@ func good40() {
|
|||||||
ret := T40{}
|
ret := T40{}
|
||||||
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
|
ret.m = make(map[int]int) // ERROR "live at call to makemap: ret"
|
||||||
t := &ret
|
t := &ret
|
||||||
println() // ERROR "live at call to printnl: ret"
|
printnl() // ERROR "live at call to printnl: ret"
|
||||||
_ = t
|
_ = t
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user