summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/gc/go.h10
-rw-r--r--src/cmd/gc/go.y18
-rw-r--r--src/cmd/gc/subr.c5
-rw-r--r--src/cmd/gc/walk.c309
4 files changed, 193 insertions, 149 deletions
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 7ec215b0e..0f8d26506 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -326,7 +326,10 @@ enum
OINDEX, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OLITERAL, OREGISTER, OINDREG,
- OCONV, OCOMP, OKEY, OPARAM,
+ OKEY, OPARAM,
+ OCONV,
+ OCONVDOT,
+ OCONVPAREN,
OBAD,
OEXTEND, // 6g internal
@@ -805,6 +808,7 @@ void gettype(Node*, Node*);
void walk(Node*);
void walkstate(Node*);
void walktype(Node*, int);
+void walkconv(Node*);
void walkas(Node*);
void walkbool(Node*);
Type* walkswitch(Node*, Type*(*)(Node*, Type*));
@@ -840,8 +844,8 @@ Node* reorder2(Node*);
Node* reorder3(Node*);
Node* reorder4(Node*);
Node* structlit(Node*, Node*);
-Node* arraylit(Node*);
-Node* maplit(Node*);
+Node* arraylit(Node*, Node*);
+Node* maplit(Node*, Node*);
Node* selectas(Node*, Node*);
Node* old2new(Node*, Type*);
void addrescapes(Node*);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 29a08912d..072db35b6 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -791,7 +791,7 @@ pexpr:
}
| pexpr '.' '(' type ')'
{
- $$ = nod(OCONV, $1, N);
+ $$ = nod(OCONVDOT, $1, N);
$$->type = $4;
}
| pexpr '[' expr ']'
@@ -841,20 +841,24 @@ pexpr:
$$ = nod(OMAKE, $5, N);
$$->type = $3;
}
-| latype '(' expr ')'
+| convtype '(' braced_keyexpr_list ')'
{
- $$ = nod(OCONV, $3, N);
- $$->type = oldtype($1);
+ // typed literal
+ $$ = rev($3);
+ if($$ == N)
+ $$ = nod(OEMPTY, N, N);
+ $$ = nod(OCONVPAREN, $$, N);
+ $$->type = $1;
}
| convtype '{' braced_keyexpr_list '}'
{
+ if(!debug['{'])
+ warn("braces should now be parens");
// composite literal
$$ = rev($3);
if($$ == N)
$$ = nod(OEMPTY, N, N);
- if(!iscomposite($1))
- yyerror("illegal composite literal type %T", $1);
- $$ = nod(OCOMP, $$, N);
+ $$ = nod(OCONVPAREN, $$, N);
$$->type = $1;
}
| fnliteral
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 841f5c361..2ddf6e8ca 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -634,9 +634,10 @@ opnames[] =
[OXCASE] = "XCASE",
[OCMP] = "CMP",
[OFALL] = "FALL",
- [OCONV] = "CONV",
+ [OCONV] = "CONV",
+ [OCONVDOT] = "CONVDOT",
+ [OCONVPAREN] = "CONVPAREN",
[OCOM] = "COM",
- [OCOMP] = "COMP",
[OCONST] = "CONST",
[OCONTINUE] = "CONTINUE",
[ODCLARG] = "DCLARG",
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 440c89779..1d2063348 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -507,7 +507,7 @@ loop:
}
break;
- case OCONV:
+ case OCONVDOT:
if(cl == 2 && cr == 1) {
// a,b = i.(T)
walktype(r->left, Erv);
@@ -590,128 +590,11 @@ loop:
goto ret;
case OCONV:
- if(top == Etop)
- goto nottop;
-
- l = n->left;
- if(l == N)
- goto ret;
-
- walktype(l, Erv);
-
- t = n->type;
- if(t == T)
- goto ret;
-
- convlit1(l, t, 1);
-
- // nil conversion
- if(eqtype(t, l->type, 0)) {
- if(l->op != ONAME) {
- indir(n, l);
- n->type = t;
- }
- goto ret;
- }
-
- // simple fix-float
- if(l->type != T)
- if(isint[l->type->etype] || isfloat[l->type->etype])
- if(isint[t->etype] || isfloat[t->etype]) {
- evconst(n);
- goto ret;
- }
-
- // to string
- if(l->type != T)
- if(istype(t, TSTRING)) {
- et = l->type->etype;
- if(isint[et]) {
- indir(n, stringop(n, top));
- goto ret;
- }
- if(et == TARRAY)
- if(istype(l->type->type, TUINT8)) {
- n->op = OARRAY;
- indir(n, stringop(n, top));
- goto ret;
- }
- }
-
- // convert dynamic to static generated by ONEW/OMAKE
- if(isfixedarray(t) && isslice(l->type))
- goto ret;
-
- // convert static array to dynamic array
- if(isslice(t) && isfixedarray(l->type)) {
- if(eqtype(t->type->type, l->type->type->type, 0)) {
- indir(n, arrayop(n, Erv));
- goto ret;
- }
- }
-
- // interface assignment
- et = ifaceas(n->type, l->type, 1);
- if(et != Inone) {
- indir(n, ifaceop(n->type, l, et));
- goto ret;
- }
-
- // convert to unsafe.pointer
- if(isptrto(n->type, TANY)) {
- if(isptr[l->type->etype])
- goto ret;
- if(l->type->etype == TUINTPTR)
- goto ret;
- }
-
- // convert from unsafe.pointer
- if(isptrto(l->type, TANY)) {
- if(isptr[n->type->etype])
- goto ret;
- if(n->type->etype == TUINTPTR)
- goto ret;
- }
-
- if(l->type != T)
- yyerror("cannot convert %T to %T", l->type, t);
- goto ret;
-
- case OCOMP:
- if(top == Etop)
+ case OCONVDOT:
+ case OCONVPAREN:
+ if(top != Erv)
goto nottop;
-
- l = n->left;
- if(l == N)
- goto ret;
-
- walktype(l, Erv);
-
- t = n->type;
- if(t == T)
- goto ret;
-
- // structure literal
- if(t->etype == TSTRUCT) {
- indir(n, structlit(n, nil));
- goto ret;
- }
-
- // array literal
- if(t->etype == TARRAY) {
- r = arraylit(n);
- indir(n, r);
- goto ret;
- }
-
- // map literal
- if(t->etype == TMAP) {
- r = maplit(n);
- indir(n, r);
- goto ret;
- }
-
- yyerror("bad composite literal %T", t);
+ walkconv(n);
goto ret;
case ORETURN:
@@ -1001,14 +884,18 @@ loop:
case OADDR:
if(top != Erv)
goto nottop;
- if(n->left->op == OCOMP && n->left->type != T)
- if(n->left->type->etype == TSTRUCT) {
- // turn &Point{1, 2} into allocation.
+ if(n->left->op == OCONVPAREN && n->left->type != T)
+ switch(n->left->type->etype) {
+ case TSTRUCT:
+ case TARRAY:
+ case TMAP:
+ // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
// initialize with
// nvar := new(*Point);
- // *nvar = Point{1, 2};
+ // *nvar = Point(1, 2);
// and replace expression with nvar
- Node *nvar, *nas;
+ ; // stupid c syntax - case label must be on stmt, not decl
+ Node *nvar, *nas, *nstar;
nvar = nod(OXXX, N, N);
tempname(nvar, ptrto(n->left->type));
@@ -1016,10 +903,27 @@ loop:
nas = nod(OAS, nvar, callnew(n->left->type));
addtop = list(addtop, nas);
- structlit(n->left, nvar);
+ nstar = nod(OIND, nvar, N);
+ nstar->type = n->left->type;
+
+ switch(n->left->type->etype) {
+ case TSTRUCT:
+ structlit(n->left, nstar);
+ break;
+ case TARRAY:
+ arraylit(n->left, nstar);
+ break;
+ case TMAP:
+ maplit(n->left, nstar);
+ break;
+ default:
+ fatal("addr lit %T", n->left->type);
+ }
+
indir(n, nvar);
goto ret;
}
+
if(istype(n->left->type, TFUNC) && n->left->class == PFUNC) {
if(!n->diag) {
n->diag = 1;
@@ -1223,6 +1127,133 @@ walkbool(Node *n)
yyerror("IF and FOR require a boolean type");
}
+void
+walkconv(Node *n)
+{
+ int et, op;
+ Type *t;
+ Node *l;
+
+ t = n->type;
+ if(t == T)
+ return;
+ l = n->left;
+ if(l == N)
+ return;
+ walktype(l, Erv);
+
+ switch(t->etype) {
+ case TSTRUCT:
+ case TMAP:
+ case TARRAY:
+ break;
+ default:
+ convlit1(l, t, 1);
+ }
+
+ op = n->op;
+ n->op = OCONV; // generic conversion
+
+ // nil conversion
+ if(eqtype(t, l->type, 0)) {
+ if(l->op != ONAME) {
+ indir(n, l);
+ n->type = t;
+ }
+ return;
+ }
+
+ // simple fix-float
+ if(l->type != T)
+ if(isint[l->type->etype] || isfloat[l->type->etype])
+ if(isint[t->etype] || isfloat[t->etype]) {
+ evconst(n);
+ return;
+ }
+
+ // to string
+ if(l->type != T)
+ if(istype(t, TSTRING)) {
+ et = l->type->etype;
+ if(isint[et]) {
+ indir(n, stringop(n, Erv));
+ return;
+ }
+ if(et == TARRAY)
+ if(istype(l->type->type, TUINT8)) {
+ n->op = OARRAY;
+ indir(n, stringop(n, Erv));
+ return;
+ }
+ }
+
+ // convert dynamic to static generated by ONEW/OMAKE
+ if(isfixedarray(t) && isslice(l->type))
+ return;
+
+ // convert static array to dynamic array
+ if(isslice(t) && isfixedarray(l->type)) {
+ if(eqtype(t->type->type, l->type->type->type, 0)) {
+ indir(n, arrayop(n, Erv));
+ return;
+ }
+ }
+
+ // convert to unsafe.pointer
+ if(isptrto(n->type, TANY)) {
+ if(isptr[l->type->etype])
+ return;
+ if(l->type->etype == TUINTPTR)
+ return;
+ }
+
+ // convert from unsafe.pointer
+ if(isptrto(l->type, TANY)) {
+ if(isptr[n->type->etype])
+ return;
+ if(n->type->etype == TUINTPTR)
+ return;
+ }
+
+ // possible interface conversion if using .(T)
+ if(op == OCONVDOT) {
+ // interface conversion
+ et = ifaceas(n->type, l->type, 1);
+ if(et != Inone) {
+ indir(n, ifaceop(n->type, l, et));
+ return;
+ }
+ }
+
+ // possible composite literal if using T()
+ if(op == OCONVPAREN) {
+ // structure literal
+ if(t->etype == TSTRUCT) {
+ indir(n, structlit(n, N));
+ return;
+ }
+
+ // array literal
+ if(t->etype == TARRAY) {
+ indir(n, arraylit(n, N));
+ return;
+ }
+
+ // map literal
+ if(t->etype == TMAP) {
+ indir(n, maplit(n, N));
+ return;
+ }
+ }
+
+ if(l->type != T)
+ yyerror("invalid conversion: %T to %T", l->type, t);
+ else if(n->left->op == OLIST)
+ yyerror("invalid type for composite literal: %T", t);
+}
+
+
+
/*
* return the first type
*/
@@ -3110,7 +3141,7 @@ multi:
n = list(n, a);
break;
- case OCONV:
+ case OCONVDOT:
// a,b := i.(T)
if(cl != 2)
goto badt;
@@ -3538,11 +3569,11 @@ loop:
}
Node*
-arraylit(Node *n)
+arraylit(Node *n, Node *var)
{
Iter saver;
Type *t;
- Node *var, *r, *a, *nnew;
+ Node *r, *a, *nnew;
int idx, ninit, b;
t = n->type;
@@ -3567,8 +3598,10 @@ arraylit(Node *n)
t->bound = b;
}
- var = nod(OXXX, N, N);
- tempname(var, t);
+ if(var == N) {
+ var = nod(OXXX, N, N);
+ tempname(var, t);
+ }
nnew = nil;
if(b < 0) {
@@ -3606,18 +3639,20 @@ arraylit(Node *n)
}
Node*
-maplit(Node *n)
+maplit(Node *n, Node *var)
{
Iter saver;
Type *t;
- Node *var, *r, *a;
+ Node *r, *a;
t = n->type;
if(t->etype != TMAP)
fatal("maplit: not map");
- var = nod(OXXX, N, N);
- tempname(var, t);
+ if(var == N) {
+ var = nod(OXXX, N, N);
+ tempname(var, t);
+ }
a = nod(OMAKE, N, N);
a->type = t;