Commit 75d3f62b authored by Russ Cox's avatar Russ Cox

[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
parent 91658f93
...@@ -24,6 +24,8 @@ char *runtimeimport = ...@@ -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); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) { ...@@ -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() { ...@@ -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) { ...@@ -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 ...@@ -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
......
...@@ -9,20 +9,39 @@ ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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() { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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 { ...@@ -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() { ...@@ -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 ...@@ -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 { ...@@ -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() { ...@@ -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
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment