mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
cmd/gc: unbreak exporting of composite literals.
Fixes #4932. R=golang-dev, dave, rsc CC=golang-dev https://golang.org/cl/7437043
This commit is contained in:
parent
69c90985b3
commit
b0bb6f8cee
|
@ -1091,6 +1091,7 @@ static int
|
|||
exprfmt(Fmt *f, Node *n, int prec)
|
||||
{
|
||||
int nprec;
|
||||
int ptrlit;
|
||||
NodeList *l;
|
||||
|
||||
while(n && n->implicit && (n->op == OIND || n->op == OADDR))
|
||||
|
@ -1201,12 +1202,23 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||
return fmtprint(f, "%T { %H }", n->type, n->closure->nbody);
|
||||
|
||||
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");
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1214,8 +1226,6 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||
if(fmtmode == FExp) { // requires special handling of field names
|
||||
if(n->implicit)
|
||||
fmtstrcpy(f, "{");
|
||||
else if(n->right->implicit)
|
||||
fmtprint(f, "&%T{", n->type);
|
||||
else
|
||||
fmtprint(f, "(%T{", n->type);
|
||||
for(l=n->list; l; l=l->next) {
|
||||
|
@ -1226,7 +1236,7 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||
else
|
||||
fmtstrcpy(f, " ");
|
||||
}
|
||||
if(!n->implicit && !n->right->implicit)
|
||||
if(!n->implicit)
|
||||
return fmtstrcpy(f, "})");
|
||||
return fmtstrcpy(f, "}");
|
||||
}
|
||||
|
@ -1238,13 +1248,16 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||
return fmtprint(f, "%T literal", n->type);
|
||||
if(fmtmode == FExp && n->implicit)
|
||||
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);
|
||||
|
||||
case OKEY:
|
||||
if(n->left && n->right)
|
||||
return fmtprint(f, "%N:%N", n->left, n->right);
|
||||
if(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)
|
||||
return fmtprint(f, ":%N", n->right);
|
||||
if(n->left && !n->right)
|
||||
|
|
|
@ -1325,6 +1325,7 @@ Node* safeexpr(Node *n, NodeList **init);
|
|||
void saveerrors(void);
|
||||
Node* cheapexpr(Node *n, NodeList **init);
|
||||
Node* localexpr(Node *n, Type *t, NodeList **init);
|
||||
void saveorignode(Node *n);
|
||||
int32 setlineno(Node *n);
|
||||
void setmaxarg(Type *t);
|
||||
Type* shallow(Type *t);
|
||||
|
|
|
@ -513,6 +513,18 @@ nod(int op, Node *nleft, Node *nright)
|
|||
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
|
||||
// is followed by padding. For the case where t is
|
||||
// the last field, total gives the size of the enclosing struct.
|
||||
|
@ -1416,7 +1428,7 @@ assignconv(Node *n, Type *t, char *context)
|
|||
r->type = t;
|
||||
r->typecheck = 1;
|
||||
r->implicit = 1;
|
||||
r->orig = n;
|
||||
r->orig = n->orig;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -1340,9 +1340,7 @@ reswitch:
|
|||
case OCONV:
|
||||
doconv:
|
||||
ok |= Erv;
|
||||
l = nod(OXXX, N, N);
|
||||
n->orig = l;
|
||||
*l = *n;
|
||||
saveorignode(n);
|
||||
typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
|
||||
convlit1(&n->left, n->type, 1);
|
||||
if((t = n->left->type) == T || n->type == T)
|
||||
|
@ -2322,7 +2320,7 @@ static void
|
|||
typecheckcomplit(Node **np)
|
||||
{
|
||||
int bad, i, len, nerr;
|
||||
Node *l, *n, *r, **hash;
|
||||
Node *l, *n, *norig, *r, **hash;
|
||||
NodeList *ll;
|
||||
Type *t, *f;
|
||||
Sym *s, *s1;
|
||||
|
@ -2339,14 +2337,18 @@ typecheckcomplit(Node **np)
|
|||
yyerror("missing type in composite literal");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
// Save original node (including n->right)
|
||||
norig = nod(n->op, N, N);
|
||||
*norig = *n;
|
||||
|
||||
setlineno(n->right);
|
||||
l = typecheck(&n->right /* sic */, Etype|Ecomplit);
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
nerr = nerrors;
|
||||
n->type = t;
|
||||
|
||||
|
||||
if(isptr[t->etype]) {
|
||||
// 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.
|
||||
|
@ -2413,9 +2415,6 @@ typecheckcomplit(Node **np)
|
|||
if(t->bound < 0)
|
||||
n->right = nodintconst(len);
|
||||
n->op = OARRAYLIT;
|
||||
// restore implicitness.
|
||||
if(isptr[n->type->etype])
|
||||
n->right->implicit = 1;
|
||||
break;
|
||||
|
||||
case TMAP:
|
||||
|
@ -2520,6 +2519,7 @@ typecheckcomplit(Node **np)
|
|||
if(nerr != nerrors)
|
||||
goto error;
|
||||
|
||||
n->orig = norig;
|
||||
if(isptr[n->type->etype]) {
|
||||
n = nod(OPTRLIT, n, N);
|
||||
n->typecheck = 1;
|
||||
|
@ -2528,6 +2528,7 @@ typecheckcomplit(Node **np)
|
|||
n->left->typecheck = 1;
|
||||
}
|
||||
|
||||
n->orig = norig;
|
||||
*np = n;
|
||||
lineno = lno;
|
||||
return;
|
||||
|
|
7
test/fixedbugs/issue4932.dir/foo.go
Normal file
7
test/fixedbugs/issue4932.dir/foo.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
// 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{}
|
28
test/fixedbugs/issue4932.dir/state.go
Normal file
28
test/fixedbugs/issue4932.dir/state.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
// 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{}
|
||||
}
|
9
test/fixedbugs/issue4932.dir/state2.go
Normal file
9
test/fixedbugs/issue4932.dir/state2.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
// 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
|
9
test/fixedbugs/issue4932.go
Normal file
9
test/fixedbugs/issue4932.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
// 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
|
Loading…
Reference in a new issue