summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/5g/cgen.c8
-rw-r--r--src/cmd/5g/gsubr.c9
-rw-r--r--src/cmd/6g/cgen.c7
-rw-r--r--src/cmd/6g/gsubr.c9
-rw-r--r--src/cmd/8g/cgen.c7
-rw-r--r--src/cmd/8g/gsubr.c9
-rw-r--r--src/cmd/gc/walk.c3
-rw-r--r--test/live.go26
8 files changed, 77 insertions, 1 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 9faf75461..9011b2022 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1490,6 +1490,7 @@ sgen(Node *n, Node *res, int64 w)
}
if(osrc%align != 0 || odst%align != 0)
fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+
// if we are copying forward on the stack and
// the src and dst overlap, then reverse direction
dir = align;
@@ -1674,6 +1675,13 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
+ // nl and nr are 'cadable' which basically means they are names (variables) now.
+ // If they are the same variable, don't generate any code, because the
+ // VARDEF we generate will mark the old value as dead incorrectly.
+ // (And also the assignments are useless.)
+ if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
+ goto yes;
+
switch(nl->type->etype) {
case TARRAY:
if(nl->op == ONAME)
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 528e8f8cc..f66c87b5a 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -470,6 +470,7 @@ Node*
nodarg(Type *t, int fp)
{
Node *n;
+ NodeList *l;
Type *first;
Iter savet;
@@ -491,6 +492,14 @@ nodarg(Type *t, int fp)
if(t->etype != TFIELD)
fatal("nodarg: not field %T", t);
+ if(fp == 1) {
+ for(l=curfn->dcl; l; l=l->next) {
+ n = l->n;
+ if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
+ return n;
+ }
+ }
+
n = nod(ONAME, N, N);
n->type = t->type;
n->sym = t->sym;
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
index ae1309142..4dd505b08 100644
--- a/src/cmd/6g/cgen.c
+++ b/src/cmd/6g/cgen.c
@@ -1585,6 +1585,13 @@ componentgen(Node *nr, Node *nl)
freer = 1;
}
}
+
+ // nl and nr are 'cadable' which basically means they are names (variables) now.
+ // If they are the same variable, don't generate any code, because the
+ // VARDEF we generate will mark the old value as dead incorrectly.
+ // (And also the assignments are useless.)
+ if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
+ goto yes;
switch(nl->type->etype) {
case TARRAY:
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index bd2f2304b..e4d00bf41 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -462,6 +462,7 @@ Node*
nodarg(Type *t, int fp)
{
Node *n;
+ NodeList *l;
Type *first;
Iter savet;
@@ -482,6 +483,14 @@ nodarg(Type *t, int fp)
if(t->etype != TFIELD)
fatal("nodarg: not field %T", t);
+
+ if(fp == 1) {
+ for(l=curfn->dcl; l; l=l->next) {
+ n = l->n;
+ if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
+ return n;
+ }
+ }
n = nod(ONAME, N, N);
n->type = t->type;
diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c
index 1aae7771c..d626c2eb0 100644
--- a/src/cmd/8g/cgen.c
+++ b/src/cmd/8g/cgen.c
@@ -1397,6 +1397,13 @@ componentgen(Node *nr, Node *nl)
}
}
+ // nl and nr are 'cadable' which basically means they are names (variables) now.
+ // If they are the same variable, don't generate any code, because the
+ // VARDEF we generate will mark the old value as dead incorrectly.
+ // (And also the assignments are useless.)
+ if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr)
+ goto yes;
+
switch(nl->type->etype) {
case TARRAY:
if(nl->op == ONAME)
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index e83ae5d7a..2f3cb28c8 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -1044,6 +1044,7 @@ Node*
nodarg(Type *t, int fp)
{
Node *n;
+ NodeList *l;
Type *first;
Iter savet;
@@ -1068,6 +1069,14 @@ nodarg(Type *t, int fp)
break;
case TFIELD:
+ if(fp == 1 && t->sym != S && !isblanksym(t->sym)) {
+ for(l=curfn->dcl; l; l=l->next) {
+ n = l->n;
+ if((n->class == PPARAM || n->class == PPARAMOUT) && n->sym == t->sym)
+ return n;
+ }
+ }
+
n = nod(ONAME, N, N);
n->type = t->type;
n->sym = t->sym;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 2d402d04f..1cb25512e 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1652,7 +1652,8 @@ ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeL
// optimization - can do block copy
if(eqtypenoname(r->type, *nl)) {
a = nodarg(*nl, fp);
- a->type = r->type;
+ r = nod(OCONVNOP, r, N);
+ r->type = a->type;
nn = list1(convas(nod(OAS, a, r), init));
goto ret;
}
diff --git a/test/live.go b/test/live.go
index 21d3e6a5f..286fcc306 100644
--- a/test/live.go
+++ b/test/live.go
@@ -564,3 +564,29 @@ func f38(b bool) {
}
println()
}
+
+// issue 8097: mishandling of x = x during return.
+
+func f39() (x []int) {
+ x = []int{1}
+ println() // ERROR "live at call to printnl: x"
+ return x
+}
+
+func f39a() (x []int) {
+ x = []int{1}
+ println() // ERROR "live at call to printnl: x"
+ return
+}
+
+func f39b() (x [10]*int) {
+ x = [10]*int{new(int)} // ERROR "live at call to new: x"
+ println() // ERROR "live at call to printnl: x"
+ return x
+}
+
+func f39c() (x [10]*int) {
+ x = [10]*int{new(int)} // ERROR "live at call to new: x"
+ println() // ERROR "live at call to printnl: x"
+ return
+}