Commit b0bb6f8c authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: unbreak exporting of composite literals.

Fixes #4932.

R=golang-dev, dave, rsc
CC=golang-dev
https://golang.org/cl/7437043
parent 69c90985
...@@ -1091,6 +1091,7 @@ static int ...@@ -1091,6 +1091,7 @@ static int
exprfmt(Fmt *f, Node *n, int prec) exprfmt(Fmt *f, Node *n, int prec)
{ {
int nprec; int nprec;
int ptrlit;
NodeList *l; NodeList *l;
while(n && n->implicit && (n->op == OIND || n->op == OADDR)) while(n && n->implicit && (n->op == OIND || n->op == OADDR))
...@@ -1201,12 +1202,23 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1201,12 +1202,23 @@ exprfmt(Fmt *f, Node *n, int prec)
return fmtprint(f, "%T { %H }", n->type, n->closure->nbody); return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
case OCOMPLIT: case OCOMPLIT:
if(fmtmode == FErr) ptrlit = n->right != N && n->right->implicit && n->right->type && isptr[n->right->type->etype];
if(fmtmode == FErr) {
if(n->right != N && n->right->type != T && !n->implicit) {
if(ptrlit)
return fmtprint(f, "&%T literal", n->right->type->type);
else
return fmtprint(f, "%T literal", n->right->type);
}
return fmtstrcpy(f, "composite literal"); return fmtstrcpy(f, "composite literal");
}
if(fmtmode == FExp && ptrlit)
// typecheck has overwritten OIND by OTYPE with pointer type.
return fmtprint(f, "&%T{ %,H }", n->right->type->type, n->list);
return fmtprint(f, "(%N{ %,H })", n->right, n->list); return fmtprint(f, "(%N{ %,H })", n->right, n->list);
case OPTRLIT: case OPTRLIT:
if(fmtmode == FExp) // handle printing of '&' below. if(fmtmode == FExp && n->left->implicit)
return fmtprint(f, "%N", n->left); return fmtprint(f, "%N", n->left);
return fmtprint(f, "&%N", n->left); return fmtprint(f, "&%N", n->left);
...@@ -1214,8 +1226,6 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1214,8 +1226,6 @@ exprfmt(Fmt *f, Node *n, int prec)
if(fmtmode == FExp) { // requires special handling of field names if(fmtmode == FExp) { // requires special handling of field names
if(n->implicit) if(n->implicit)
fmtstrcpy(f, "{"); fmtstrcpy(f, "{");
else if(n->right->implicit)
fmtprint(f, "&%T{", n->type);
else else
fmtprint(f, "(%T{", n->type); fmtprint(f, "(%T{", n->type);
for(l=n->list; l; l=l->next) { for(l=n->list; l; l=l->next) {
...@@ -1226,7 +1236,7 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1226,7 +1236,7 @@ exprfmt(Fmt *f, Node *n, int prec)
else else
fmtstrcpy(f, " "); fmtstrcpy(f, " ");
} }
if(!n->implicit && !n->right->implicit) if(!n->implicit)
return fmtstrcpy(f, "})"); return fmtstrcpy(f, "})");
return fmtstrcpy(f, "}"); return fmtstrcpy(f, "}");
} }
...@@ -1238,13 +1248,16 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1238,13 +1248,16 @@ exprfmt(Fmt *f, Node *n, int prec)
return fmtprint(f, "%T literal", n->type); return fmtprint(f, "%T literal", n->type);
if(fmtmode == FExp && n->implicit) if(fmtmode == FExp && n->implicit)
return fmtprint(f, "{ %,H }", n->list); return fmtprint(f, "{ %,H }", n->list);
if(fmtmode == FExp && n->right->implicit)
return fmtprint(f, "&%T{ %,H }", n->type, n->list);
return fmtprint(f, "(%T{ %,H })", n->type, n->list); return fmtprint(f, "(%T{ %,H })", n->type, n->list);
case OKEY: case OKEY:
if(n->left && n->right) if(n->left && n->right) {
return fmtprint(f, "%N:%N", n->left, n->right); if(fmtmode == FExp && n->left->type && n->left->type->etype == TFIELD) {
// requires special handling of field names
return fmtprint(f, "%hhS:%N", n->left->sym, n->right);
} else
return fmtprint(f, "%N:%N", n->left, n->right);
}
if(!n->left && n->right) if(!n->left && n->right)
return fmtprint(f, ":%N", n->right); return fmtprint(f, ":%N", n->right);
if(n->left && !n->right) if(n->left && !n->right)
......
...@@ -1325,6 +1325,7 @@ Node* safeexpr(Node *n, NodeList **init); ...@@ -1325,6 +1325,7 @@ Node* safeexpr(Node *n, NodeList **init);
void saveerrors(void); void saveerrors(void);
Node* cheapexpr(Node *n, NodeList **init); Node* cheapexpr(Node *n, NodeList **init);
Node* localexpr(Node *n, Type *t, NodeList **init); Node* localexpr(Node *n, Type *t, NodeList **init);
void saveorignode(Node *n);
int32 setlineno(Node *n); int32 setlineno(Node *n);
void setmaxarg(Type *t); void setmaxarg(Type *t);
Type* shallow(Type *t); Type* shallow(Type *t);
......
...@@ -513,6 +513,18 @@ nod(int op, Node *nleft, Node *nright) ...@@ -513,6 +513,18 @@ nod(int op, Node *nleft, Node *nright)
return n; return n;
} }
void
saveorignode(Node *n)
{
Node *norig;
if(n->orig != N)
return;
norig = nod(n->op, N, N);
*norig = *n;
n->orig = norig;
}
// ispaddedfield returns whether the given field // ispaddedfield returns whether the given field
// is followed by padding. For the case where t is // is followed by padding. For the case where t is
// the last field, total gives the size of the enclosing struct. // the last field, total gives the size of the enclosing struct.
...@@ -1416,7 +1428,7 @@ assignconv(Node *n, Type *t, char *context) ...@@ -1416,7 +1428,7 @@ assignconv(Node *n, Type *t, char *context)
r->type = t; r->type = t;
r->typecheck = 1; r->typecheck = 1;
r->implicit = 1; r->implicit = 1;
r->orig = n; r->orig = n->orig;
return r; return r;
} }
......
...@@ -1340,9 +1340,7 @@ reswitch: ...@@ -1340,9 +1340,7 @@ reswitch:
case OCONV: case OCONV:
doconv: doconv:
ok |= Erv; ok |= Erv;
l = nod(OXXX, N, N); saveorignode(n);
n->orig = l;
*l = *n;
typecheck(&n->left, Erv | (top & (Eindir | Eiota))); typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
convlit1(&n->left, n->type, 1); convlit1(&n->left, n->type, 1);
if((t = n->left->type) == T || n->type == T) if((t = n->left->type) == T || n->type == T)
...@@ -2322,7 +2320,7 @@ static void ...@@ -2322,7 +2320,7 @@ static void
typecheckcomplit(Node **np) typecheckcomplit(Node **np)
{ {
int bad, i, len, nerr; int bad, i, len, nerr;
Node *l, *n, *r, **hash; Node *l, *n, *norig, *r, **hash;
NodeList *ll; NodeList *ll;
Type *t, *f; Type *t, *f;
Sym *s, *s1; Sym *s, *s1;
...@@ -2339,14 +2337,18 @@ typecheckcomplit(Node **np) ...@@ -2339,14 +2337,18 @@ typecheckcomplit(Node **np)
yyerror("missing type in composite literal"); yyerror("missing type in composite literal");
goto error; goto error;
} }
// Save original node (including n->right)
norig = nod(n->op, N, N);
*norig = *n;
setlineno(n->right); setlineno(n->right);
l = typecheck(&n->right /* sic */, Etype|Ecomplit); l = typecheck(&n->right /* sic */, Etype|Ecomplit);
if((t = l->type) == T) if((t = l->type) == T)
goto error; goto error;
nerr = nerrors; nerr = nerrors;
n->type = t; n->type = t;
if(isptr[t->etype]) { if(isptr[t->etype]) {
// For better or worse, we don't allow pointers as the composite literal type, // For better or worse, we don't allow pointers as the composite literal type,
// except when using the &T syntax, which sets implicit on the OIND. // except when using the &T syntax, which sets implicit on the OIND.
...@@ -2413,9 +2415,6 @@ typecheckcomplit(Node **np) ...@@ -2413,9 +2415,6 @@ typecheckcomplit(Node **np)
if(t->bound < 0) if(t->bound < 0)
n->right = nodintconst(len); n->right = nodintconst(len);
n->op = OARRAYLIT; n->op = OARRAYLIT;
// restore implicitness.
if(isptr[n->type->etype])
n->right->implicit = 1;
break; break;
case TMAP: case TMAP:
...@@ -2520,6 +2519,7 @@ typecheckcomplit(Node **np) ...@@ -2520,6 +2519,7 @@ typecheckcomplit(Node **np)
if(nerr != nerrors) if(nerr != nerrors)
goto error; goto error;
n->orig = norig;
if(isptr[n->type->etype]) { if(isptr[n->type->etype]) {
n = nod(OPTRLIT, n, N); n = nod(OPTRLIT, n, N);
n->typecheck = 1; n->typecheck = 1;
...@@ -2528,6 +2528,7 @@ typecheckcomplit(Node **np) ...@@ -2528,6 +2528,7 @@ typecheckcomplit(Node **np)
n->left->typecheck = 1; n->left->typecheck = 1;
} }
n->orig = norig;
*np = n; *np = n;
lineno = lno; lineno = lno;
return; return;
......
// Copyright 2013 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.
package foo
type Op struct{}
// Copyright 2013 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.
package state
import "./foo"
func Public() {
var s Settings
s.op()
}
type State struct{}
func (s *State) x(*Settings) {}
type Settings struct{}
func (c *Settings) x() {
run([]foo.Op{{}})
}
func run([]foo.Op) {}
func (s *Settings) op() foo.Op {
return foo.Op{}
}
// Copyright 2013 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.
package state2
import "./state"
type Foo *state.State
// compiledir
// Copyright 2013 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.
// Issue 4932: regression in export of composite literals.
package ignored
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