Iter save;
Strlit *note;
int lno;
+ Node *init;
+ init = N;
lno = lineno;
- n = listfirst(&save, &n);
-
-loop:
- note = nil;
- if(n == N) {
- *t = T;
- lineno = lno;
- return t;
- }
+ for(n = listfirst(&save, &n); n != N; n = listnext(&save)) {
+ note = nil;
- lineno = n->lineno;
- if(n->op == OLIST) {
- // recursive because it can be lists of lists
- t = stotype(n, et, t);
- goto next;
- }
+ lineno = n->lineno;
+ if(n->op == OLIST) {
+ // recursive because it can be lists of lists
+ t = stotype(n, et, t);
+ continue;
+ }
- if(n->op != ODCLFIELD)
- fatal("stotype: oops %N\n", n);
+ if(n->op != ODCLFIELD)
+ fatal("stotype: oops %N\n", n);
+ if(n->right != N) {
+ walkexpr(n->right, Etype, &init);
+ n->type = n->right->type;
+ n->right = N;
+ if(n->embedded && n->type != T) {
+ t1 = n->type;
+ if(t1->sym == S && isptr[t1->etype])
+ t1 = t1->type;
+ if(t1 != T && isptr[t1->etype])
+ yyerror("embedded type cannot be a pointer");
+ }
+ }
- if(n->type == T) {
- // assume error already printed
- goto next;
- }
+ if(n->type == T) {
+ // assume error already printed
+ continue;
+ }
- switch(n->val.ctype) {
- case CTSTR:
- if(et != TSTRUCT)
- yyerror("interface method cannot have annotation");
- note = n->val.u.sval;
- break;
- default:
- if(et != TSTRUCT)
- yyerror("interface method cannot have annotation");
- else
- yyerror("field annotation must be string");
- case CTxxx:
- note = nil;
- break;
- }
+ switch(n->val.ctype) {
+ case CTSTR:
+ if(et != TSTRUCT)
+ yyerror("interface method cannot have annotation");
+ note = n->val.u.sval;
+ break;
+ default:
+ if(et != TSTRUCT)
+ yyerror("interface method cannot have annotation");
+ else
+ yyerror("field annotation must be string");
+ case CTxxx:
+ note = nil;
+ break;
+ }
- if(et == TINTER && n->left == N) {
- // embedded interface - inline the methods
- if(n->type->etype != TINTER) {
- yyerror("interface contains embedded non-interface %T", t);
- goto next;
+ if(et == TINTER && n->left == N) {
+ // embedded interface - inline the methods
+ if(n->type->etype != TINTER) {
+ yyerror("interface contains embedded non-interface %T", t);
+ continue;
+ }
+ for(t1=n->type->type; t1!=T; t1=t1->down) {
+ // TODO(rsc): Is this really an error?
+ if(strcmp(t1->sym->package, package) != 0)
+ yyerror("embedded interface contains unexported method %S", t1->sym);
+ f = typ(TFIELD);
+ f->type = t1->type;
+ f->width = BADWIDTH;
+ f->nname = newname(t1->sym);
+ f->sym = t1->sym;
+ *t = f;
+ t = &f->down;
+ }
+ continue;
}
- for(t1=n->type->type; t1!=T; t1=t1->down) {
- if(strcmp(t1->sym->package, package) != 0)
- yyerror("embedded interface contains unexported method %S", t1->sym);
- f = typ(TFIELD);
- f->type = t1->type;
- f->width = BADWIDTH;
- f->nname = newname(t1->sym);
- f->sym = t1->sym;
- *t = f;
- t = &f->down;
+
+ f = typ(TFIELD);
+ f->type = n->type;
+ f->note = note;
+ f->width = BADWIDTH;
+
+ if(n->left != N && n->left->op == ONAME) {
+ f->nname = n->left;
+ f->embedded = n->embedded;
+ f->sym = f->nname->sym;
+ if(pkgimportname != S && !exportname(f->sym->name))
+ f->sym = pkglookup(f->sym->name, structpkg);
}
- goto next;
- }
- f = typ(TFIELD);
- f->type = n->type;
- f->note = note;
- f->width = BADWIDTH;
-
- if(n->left != N && n->left->op == ONAME) {
- f->nname = n->left;
- f->embedded = n->embedded;
- f->sym = f->nname->sym;
- if(pkgimportname != S && !exportname(f->sym->name))
- f->sym = pkglookup(f->sym->name, structpkg);
+ *t = f;
+ t = &f->down;
}
- *t = f;
- t = &f->down;
-
-next:
- n = listnext(&save);
- goto loop;
+ *t = T;
+ lineno = lno;
+ return t;
}
Type*
if(s == S)
return T;
if(s->def == N || s->def->op != OTYPE) {
- yyerror("%S is not a type", s);
+ if(!s->undef)
+ yyerror("%S is not a type", s);
return T;
}
t = s->def->type;
n->embedded = 1;
if(s == S)
return n;
- n->type = oldtype(s);
- if(n->type != T && isptr[n->type->etype])
- yyerror("embedded type cannot be a pointer");
+ n->right = oldname(s);
return n;
}
// OLITERAL/OREGISTER
Val val;
+ // OTFUNC
+ Node* rcvr;
+
// ONAME func param with PHEAP
Node* heapaddr; // temp holding heap address of param
Node* stackparam; // OPARAM node referring to stack copy of param
ODOTTYPE, OTYPESW,
OBAD,
+ OTCHAN, OTMAP, OTSTRUCT, OTINTER, OTFUNC, OTARRAY,
+
OEXTEND, // 6g internal
OEND,
Etop, // evaluated at statement level
Elv, // evaluated in lvalue context
Erv, // evaluated in rvalue context
+ Etype = 1<<8,
};
#define BITS 5
uint32 stringhash(char*);
Sym* lookup(char*);
Sym* pkglookup(char*, char*);
-Sym* opkglookup(char*, char*);
+Sym* restrictlookup(char*, char*);
void importdot(Sym*);
void yyerror(char*, ...);
void warn(char*, ...);
void walkstmt(Node*);
void walkexpr(Node*, int, Node**);
void walkconv(Node*, Node**);
+void walkdottype(Node*, Node**);
void walkas(Node*);
void walkbool(Node*);
void walkswitch(Node*);
%type <sym> sym packname
%type <val> oliteral
-%type <node> stmt
+%type <node> stmt ntype
%type <node> arg_type arg_type_list
%type <node> arg_type_list_r braced_keyexpr_list case caseblock
%type <node> caseblock_list_r common_dcl
%type <node> switch_body switch_stmt uexpr vardcl vardcl_list_r
%type <node> xdcl xdcl_list_r xfndcl
-%type <type> convtype dotdotdot
-%type <type> fnlitdcl fntype indcl interfacetype
-%type <type> new_type structtype type typedclname
-%type <type> chantype non_chan_type othertype non_fn_type
+%type <type> type
+%type <node> convtype dotdotdot
+%type <node> indcl interfacetype structtype
+%type <type> new_type typedclname fnlitdcl fntype
+%type <node> chantype non_chan_type othertype non_fn_type
%type <sym> hidden_importsym hidden_pkg_importsym
$$ = nod(OXCASE, $$, N);
break;
}
+ e = nerrors;
+ walkexpr($2, Etype | Erv, &top);
if($2->op == OTYPE) {
$$ = old2new(typeswvar->right, $2->type, &top);
$$ = nod(OTYPESW, $$, N);
$$->ninit = top;
break;
}
- e = nerrors;
- gettype($2, nil);
- // maybe gettype found problems that keep
+ // maybe walkexpr found problems that keep
// e from being valid even outside a type switch.
- // only complain if gettype didn't print new errors.
+ // only complain if walkexpr didn't print new errors.
if(nerrors == e)
yyerror("non-type case in type switch");
$$ = nod(OXCASE, N, N);
pexpr
| '*' uexpr
{
- if($2->op == OTYPE) {
- $$ = typenod(ptrto($2->type));
- break;
- }
$$ = nod(OIND, $2, N);
}
| '&' uexpr
$$ = unsafenmagic($1, $3);
if($$)
break;
- if($1->op == OTYPE) {
- // type conversion
- if($3 == N)
- yyerror("conversion to %T missing expr", $1->type);
- else if($3->op == OLIST)
- yyerror("conversion to %T has too many exprs", $1->type);
- $$ = nod(OCONV, $3, N);
- $$->type = $1->type;
- break;
- }
- if($1->op == ONAME && $1->etype != 0) { // builtin OLEN, OCAP, etc
- $$ = nod($1->etype, $3, N);
- break;
- }
$$ = nod(OCALL, $1, $3);
}
{
if($1->op == OPACK) {
Sym *s;
- s = pkglookup($3->name, $1->sym->name);
+ s = restrictlookup($3->name, $1->sym->name);
$$ = oldname(s);
break;
}
}
| pexpr '.' '(' expr_or_type ')'
{
- $$ = nod(ODOTTYPE, $1, N);
- if($4->op != OTYPE)
- yyerror("expected type got %O", $4->op);
- $$->type = $4->type;
+ $$ = nod(ODOTTYPE, $1, $4);
}
| pexpr '.' '(' LTYPE ')'
{
| convtype '(' expr ')'
{
// conversion
- $$ = nod(OCONV, $3, N);
- $$->type = $1;
+ $$ = nod(OCALL, $1, $3);
}
| convtype lbrace braced_keyexpr_list '}'
{
$$ = rev($3);
if($$ == N)
$$ = nod(OEMPTY, N, N);
- $$ = nod(OCOMPOS, $$, N);
- $$->type = $1;
+ $$ = nod(OCOMPOS, $$, $1);
// If the opening brace was an LBODY,
// set up for another one now that we're done.
$$ = rev($3);
if($$ == N)
$$ = nod(OEMPTY, N, N);
- $$ = nod(OCOMPOS, $$, N);
- if($1->op != OTYPE)
- yyerror("expected type in composite literal");
- else
- $$->type = $1->type;
+ $$ = nod(OCOMPOS, $$, $1);
}
| fnliteral
expr_or_type:
expr
-| type %prec PreferToRightParen
- {
- $$ = typenod($1);
- }
+| ntype %prec PreferToRightParen
name_or_type:
dotname
name
convtype:
- '[' oexpr ']' type
+ '[' oexpr ']' ntype
{
// array literal
- $$ = aindex($2, $4);
+ $$ = nod(OTARRAY, $2, $4);
}
-| '[' LDDD ']' type
+| '[' dotdotdot ']' ntype
{
// array literal of nelem
- $$ = aindex(N, $4);
- $$->bound = -100;
+ $$ = nod(OTARRAY, $2, $4);
}
-| LMAP '[' type ']' type
+| LMAP '[' ntype ']' ntype
{
// map literal
- $$ = maptype($3, $5);
+ $$ = nod(OTMAP, $3, $5);
}
| structtype
dotdotdot:
LDDD
{
- $$ = typ(TDDD);
+ $$ = typenod(typ(TDDD));
}
type:
+ ntype
+ {
+ Node *init;
+
+ init = N;
+ walkexpr($1, Etype, &init);
+ // init can only be set if this was not a type; ignore
+
+ $$ = $1->type;
+ }
+
+ntype:
chantype
-| fntype
+| fntype { $$ = typenod($1); }
| othertype
-| '(' type ')'
+| '(' ntype ')'
{
$$ = $2;
}
non_chan_type:
- fntype
+ fntype { $$ = typenod($1); }
| othertype
-| '(' type ')'
+| '(' ntype ')'
{
$$ = $2;
}
{
if($1->op == OPACK) {
Sym *s;
- s = pkglookup($3->name, $1->sym->name);
+ s = restrictlookup($3->name, $1->sym->name);
$$ = oldname(s);
break;
}
othertype:
'[' oexpr ']' type
{
- $$ = aindex($2, $4);
+ $$ = typenod(aindex($2, $4));
}
-| LCOMM LCHAN type
+| LCOMM LCHAN ntype
{
- $$ = typ(TCHAN);
- $$->type = $3;
- $$->chan = Crecv;
+ $$ = nod(OTCHAN, $3, N);
+ $$->etype = Crecv;
}
| LCHAN LCOMM non_chan_type
{
- $$ = typ(TCHAN);
- $$->type = $3;
- $$->chan = Csend;
+ $$ = nod(OTCHAN, $3, N);
+ $$->etype = Csend;
}
-| LMAP '[' type ']' type
+| LMAP '[' ntype ']' ntype
{
- $$ = maptype($3, $5);
+ $$ = nod(OTMAP, $3, $5);
}
-| '*' type
+| '*' ntype
{
- $$ = ptrto($2);
+ $$ = nod(OIND, $2, N);
}
| structtype
| interfacetype
| dotname
- {
- if($1->op == ODOT) {
- yyerror("%S.%S is not a type", $1->left->sym, $1->right->sym);
- $$ = T;
- break;
- }
- $$ = oldtype($1->sym);
- }
chantype:
- LCHAN type
+ LCHAN ntype
{
- $$ = typ(TCHAN);
- $$->type = $2;
- $$->chan = Cboth;
+ $$ = nod(OTCHAN, $2, N);
+ $$->etype = Cboth;
}
structtype:
LSTRUCT '{' structdcl_list_r osemi '}'
{
- $$ = dostruct(rev($3), TSTRUCT);
+ $$ = nod(OTSTRUCT, rev($3), N);
// Distinguish closing brace in struct from
// other closing braces by explicitly marking it.
// Used above (yylast == LSEMIBRACE).
}
| LSTRUCT '{' '}'
{
- $$ = dostruct(N, TSTRUCT);
+ $$ = nod(OTSTRUCT, N, N);
yylast = LSEMIBRACE;
}
interfacetype:
LINTERFACE '{' interfacedcl_list_r osemi '}'
{
- $$ = dostruct(rev($3), TINTER);
- $$ = sortinter($$);
+ $$ = nod(OTINTER, rev($3), N);
yylast = LSEMIBRACE;
}
| LINTERFACE '{' '}'
{
- $$ = dostruct(N, TINTER);
+ $$ = nod(OTINTER, N, N);
yylast = LSEMIBRACE;
}
}
| non_fn_type
{
- $$ = nod(ODCLFIELD, N, N);
- $$->type = $1;
+ $$ = nod(ODCLFIELD, N, $1);
$$ = cleanidlist($$);
}
| '(' oarg_type_list ')'
$$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3);
}
-| new_field type oliteral
+| new_field ntype oliteral
{
- $$ = nod(ODCLFIELD, $1, N);
- $$->type = $2;
+ $$ = nod(ODCLFIELD, $1, $2);
$$->val = $3;
}
| embed oliteral
| '*' embed oliteral
{
$$ = $2;
- $$->type = ptrto($$->type);
+ $$->right = nod(OIND, $$->right, N);
$$->val = $3;
}
pkg = $1->name;
} else
pkg = $1->def->sym->name;
- $$ = pkglookup($3->name, pkg);
+ $$ = restrictlookup($3->name, pkg);
}
embed:
}
| new_name indcl
{
- $$ = nod(ODCLFIELD, $1, N);
- $$->type = $2;
+ $$ = nod(ODCLFIELD, $1, $2);
}
interfacedcl:
interfacedcl1
| packname
{
- $$ = nod(ODCLFIELD, N, N);
- $$->type = oldtype($1);
+ $$ = nod(ODCLFIELD, N, typenod(oldtype($1)));
}
indcl:
'(' oarg_type_list ')' fnres
{
// without func keyword
- $$ = functype(fakethis(), $2, $4);
+ $$ = typenod(functype(fakethis(), $2, $4));
}
/*
$$ = nod(ONONAME, N, N);
$$->sym = $1;
}
- $$ = nod(OKEY, $$, typenod($2));
+ $$ = nod(OKEY, $$, $2);
}
| dotdotdot
- {
- $$ = typenod($1);
- }
arg_type_list_r:
arg_type
hidden_structdcl:
sym hidden_type oliteral
{
- $$ = nod(ODCLFIELD, newname($1), N);
- $$->type = $2;
+ $$ = nod(ODCLFIELD, newname($1), typenod($2));
$$->val = $3;
}
| '?' hidden_type oliteral
{
if(isptr[$2->etype]) {
$$ = embedded($2->type->sym);
- $$->type = ptrto($$->type);
+ $$->right = nod(OIND, $$->right, N);
} else
$$ = embedded($2->sym);
$$->val = $3;
hidden_interfacedcl:
sym '(' ohidden_funarg_list ')' ohidden_funres
{
- $$ = nod(ODCLFIELD, newname($1), N);
- $$->type = functype(fakethis(), $3, $5);
+ $$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
}
ohidden_funres:
}
Sym*
-pkglookup(char *p, char *k)
+pkglookup(char *name, char *pkg)
{
Sym *s;
uint32 h;
int c;
- h = stringhash(p) % NHASH;
- c = p[0];
+ h = stringhash(name) % NHASH;
+ c = name[0];
for(s = hash[h]; s != S; s = s->link) {
if(s->name[0] != c)
continue;
- if(strcmp(s->name, p) == 0)
- if(s->package && strcmp(s->package, k) == 0)
+ if(strcmp(s->name, name) == 0)
+ if(s->package && strcmp(s->package, pkg) == 0)
return s;
}
s = mal(sizeof(*s));
- s->name = mal(strlen(p)+1);
- strcpy(s->name, p);
+ s->name = mal(strlen(name)+1);
+ strcpy(s->name, name);
// botch - should probably try to reuse the pkg string
- s->package = mal(strlen(k)+1);
- strcpy(s->package, k);
+ s->package = mal(strlen(pkg)+1);
+ strcpy(s->package, pkg);
s->link = hash[h];
hash[h] = s;
return s;
}
-// find all the symbols in package opkg
+Sym*
+restrictlookup(char *name, char *pkg)
+{
+ if(!exportname(name) && strcmp(pkg, package) != 0)
+ yyerror("cannot refer to %s.%s", pkg, name);
+ return pkglookup(name, pkg);
+}
+
+
+// find all the exported symbols in package opkg
// and make them available in the current package
void
importdot(Sym *opkg)
for(s = hash[h]; s != S; s = s->link) {
if(s->package[0] != c)
continue;
+ if(!exportname(s->name))
+ continue;
if(strcmp(s->package, opkg->name) != 0)
continue;
s1 = lookup(s->name);
[OSLICE] = "SLICE",
[OSUB] = "SUB",
[OSWITCH] = "SWITCH",
+ [OTCHAN] = "TCHAN",
+ [OTMAP] = "TMAP",
+ [OTSTRUCT] = "TSTRUCT",
+ [OTINTER] = "TINTER",
+ [OTFUNC] = "TFUNC",
+ [OTARRAY] = "TARRAY",
[OTYPEOF] = "TYPEOF",
[OTYPESW] = "TYPESW",
[OTYPE] = "TYPE",
{
Node *last, *n;
- if(na->op != OLIST)
+ if(na->op != OLIST) {
+ if(na->op != ODCLFIELD)
+ fatal("cleanidlist: %O", na->op);
+ if(na->right == N)
+ fatal("cleanidlist: no type");
return na;
+ }
for(last=na; last->op == OLIST; last=last->right)
;
- if(last->op != ODCLFIELD)
- fatal("cleanidlist: %O", last->op);
- if(last->type == T)
- fatal("cleanidlist: no type");
for(n=na; n->op == OLIST; n=n->right) {
- n->left->type = last->type;
+ n->left->right = last->right;
n->left->val = last->val;
}
return na;
// statement of the function
case OGOTO:
- case OPANIC:
- case OPANICN:
case ORETURN:
return 0;
+
+ case OCALL:
+ if(n->left->op == ONAME) {
+ switch(n->left->etype) {
+ case OPANIC:
+ case OPANICN:
+ return 0;
+ }
+ }
+ break;
}
// all other statements
Node *r, *l;
Type *t;
Sym *s;
- int et, cl, cr;
+ int et, cl, cr, typeok;
int32 lno;
if(n == N)
return;
lno = setlineno(n);
+ typeok = top & Etype;
+ top &= ~Etype;
loop:
if(n == N)
if(debug['w'] > 1 && top == Etop && n->op != OLIST)
dump("walk-before", n);
+reswitch:
t = T;
et = Txxx;
goto ret;
case OTYPE:
- if(!n->diag) {
- n->diag = 1;
- yyerror("type %T used as expression", n->type);
+ goto ret;
+
+ case OTARRAY:
+ t = typ(TARRAY);
+ l = n->left;
+ r = n->right;
+ if(l == nil) {
+ t->bound = -1;
+ } else {
+ walkexpr(l, Erv | Etype, init);
+ switch(l->op) {
+ default:
+ yyerror("invalid array bound %O", l->op);
+ break;
+
+ case OLITERAL:
+ if(consttype(l) == CTINT) {
+ t->bound = mpgetfix(l->val.u.xval);
+ if(t->bound < 0) {
+ yyerror("array bound must be non-negative");
+ t->bound = 1;
+ }
+ }
+ break;
+
+ case OTYPE:
+ if(l->type == T)
+ break;
+ if(l->type->etype != TDDD)
+ yyerror("invalid array bound %T", l->type);
+ t->bound = -100;
+ break;
+ }
}
+ walkexpr(r, Etype, init);
+ t->type = r->type;
+ n->op = OTYPE;
+ n->type = t;
+ goto ret;
+
+ case OTMAP:
+ l = n->left;
+ r = n->right;
+ walkexpr(l, Etype, init);
+ walkexpr(r, Etype, init);
+ n->op = OTYPE;
+ n->type = maptype(l->type, r->type);
+ goto ret;
+
+ case OTCHAN:
+ t = typ(TCHAN);
+ l = n->left;
+ walkexpr(l, Etype, init);
+ t->type = l->type;
+ t->chan = n->etype;
+ n->op = OTYPE;
+ n->type = t;
+ goto ret;
+
+ case OTSTRUCT:
+ n->op = OTYPE;
+ n->type = dostruct(n->left, TSTRUCT);
+ goto ret;
+
+ case OTINTER:
+ n->op = OTYPE;
+ n->type = dostruct(n->left, TINTER);
+ n->type = sortinter(n->type);
goto ret;
case OLIST:
case OKEY:
- walkexpr(n->left, top, init);
+ walkexpr(n->left, top | typeok, init);
n = n->right;
goto loop;
s = n->sym;
if(s->undef == 0) {
s->undef = 1;
- yyerror("%S: undefined", s);
+ n->diag = 1;
+ yyerror("undefined: %S", s);
goto ret;
}
if(top == Etop)
if(n->left == N)
goto ret;
- walkexpr(n->left, Erv, init);
+ if(n->left->op == ONAME && n->left->etype != 0) {
+ // builtin OLEN, OCAP, etc.
+ n->op = n->left->etype;
+ n->left = n->right;
+ n->right = N;
+ goto reswitch;
+ }
+
+ walkexpr(n->left, Erv | Etype, init);
defaultlit(n->left, T);
t = n->left->type;
n->op = OCALLMETH;
if(n->left->op == ODOTINTER)
n->op = OCALLINTER;
+ if(n->left->op == OTYPE) {
+ n->op = OCONV;
+ if(top != Erv)
+ goto nottop;
+ // turn CALL(type, arg) into CONV(arg) w/ type.
+ n->type = n->left->type;
+ n->left = n->right;
+ n->right = N;
+ goto reswitch;
+ }
if(t->etype != TFUNC) {
yyerror("call of a non-function: %T", t);
break;
case ODOTTYPE:
+ walkdottype(r, init);
if(cl == 2 && cr == 1) {
// a,b = i.(T)
- walkexpr(r->left, Erv, init);
if(r->left == N)
break;
et = ifaceas1(r->type, r->left->type, 1);
case OEMPTY:
goto ret;
- case OCONV:
case ODOTTYPE:
+ walkdottype(n, init);
+ // fall through
+ case OCONV:
if(top != Erv)
goto nottop;
walkconv(n, init);
goto ret;
case OCOMPOS:
- t = n->type;
+ walkexpr(n->right, Etype, init);
+ t = n->right->type;
+ n->type = t;
if(t == T)
goto ret;
+
l = n->left;
if(l == N)
goto ret;
if(top != Erv)
goto nottop;
defaultlit(n->left, T);
- if(n->left->op == OCOMPOS && n->left->type != T) {
+ if(n->left->op == OCOMPOS) {
+ walkexpr(n->left->right, Etype, init);
+ n->left->type = n->left->right->type;
+ if(n->left->type == T)
+ goto ret;
+
Node *nvar, *nas, *nstar;
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
goto nottop;
if(top == Elv) // even if n is lvalue, n->left is rvalue
top = Erv;
- walkexpr(n->left, top, init);
- defaultlit(n->left, T);
if(n->left == N)
goto ret;
+ walkexpr(n->left, top | Etype, init);
+ defaultlit(n->left, T);
+ if(n->left->op == OTYPE) {
+ n->op = OTYPE;
+ n->type = ptrto(n->left->type);
+ goto ret;
+ }
t = n->left->type;
if(t == T)
goto ret;
if(top != Erv)
goto nottop;
l = n->left;
+ walkexpr(l, Etype, init);
if(l == N)
yyerror("missing argument to new");
else if(n->right != N)
yyerror("too many arguments to new");
- else if(l->op != OTYPE)
- yyerror("argument to new must be type");
else if((t = l->type) == T)
;
else
if(n->diag)
goto ret;
n->diag = 1;
- switch(top) {
+ switch(top | typeok) {
default:
- yyerror("didn't expect %O here", n->op);
+ yyerror("didn't expect %O here [top=%d]", n->op, top);
+ break;
+ case Etype:
+ yyerror("operation %O not allowed in type context", n->op);
break;
case Etop:
yyerror("operation %O not allowed in statement context", n->op);
yyerror("operation %O not allowed in assignment context", n->op);
break;
case Erv:
+ case Erv | Etype:
yyerror("operation %O not allowed in expression context", n->op);
break;
}
if(debug['w'] && top == Etop && n != N)
dump("walk", n);
+ if(typeok && top == 0) { // must be type
+ if(n->op != OTYPE) {
+ if(n->sym) {
+ if(!n->sym->undef)
+ yyerror("%S is not a type", n->sym);
+ } else {
+ yyerror("expr %O is not type", n->op);
+ n->op = OTYPE; // leads to fewer errors later
+ n->type = T;
+ }
+ }
+ }
+ if(!typeok && n->op == OTYPE)
+ yyerror("cannot use type %T as expr", n->type);
+
ullmancalc(n);
lineno = lno;
}
yyerror("IF and FOR require a boolean type");
}
+void
+walkdottype(Node *n, Node **init)
+{
+ walkexpr(n->left, Erv, init);
+ if(n->left == N)
+ return;
+ defaultlit(n->left, T);
+ if(!isinter(n->left->type))
+ yyerror("type assertion requires interface on left, have %T", n->left->type);
+ if(n->right != N) {
+ walkexpr(n->right, Etype, init);
+ n->type = n->right->type;
+ n->right = N;
+ }
+}
+
void
walkconv(Node *n, Node **init)
{
// if using .(T), interface assertion.
if(n->op == ODOTTYPE) {
- defaultlit(l, T);
- if(!isinter(l->type))
- yyerror("type assertion requires interface on left, have %T", l->type);
et = ifaceas1(t, l->type, 1);
if(et == I2Isame || et == E2Esame)
goto nop;
if(!lookdot(n, t)) {
if(!n->diag) {
n->diag = 1;
- yyerror("undefined DOT %S on %T", n->right->sym, n->left->type);
+ yyerror("undefined: %T field %S", n->left->type, n->right->sym);
}
}
}
makecompat(Node *n)
{
Type *t;
- Node *l, *r;
+ Node *l, *r, *init;
l = n->left;
r = N;
r = l->right;
l = l->left;
}
+ init = N;
+ walkexpr(l, Etype, &init);
if(l->op != OTYPE) {
yyerror("cannot make(expr)");
return n;
/* check calls early, to give better message for a := f() */
if(cr == 1) {
switch(nr->op) {
+ case OCALL:
+ if(nr->left->op == ONAME && nr->left->etype != 0)
+ break;
+ walkexpr(nr->left, Erv | Etype, init);
+ if(nr->left->op == OTYPE)
+ break;
+ goto call;
case OCALLMETH:
case OCALLINTER:
- case OCALL:
walkexpr(nr->left, Erv, init);
+ call:
convlit(nr->left, types[TFUNC]);
t = nr->left->type;
if(t == T)
case ODOTTYPE:
// a,b := i.(T)
+ walkdottype(nr, init);
if(cl != 2)
goto badt;
- walkexpr(nr->left, Erv, init);
- if(!isinter(nr->left->type))
- goto badt;
// a,b = iface
a = mixedoldnew(nl->left, nr->type);
n = a;
previous declaration at fixedbugs/bug035.go:5
=========== fixedbugs/bug037.go
-fixedbugs/bug037.go:6: vlong: undefined
-fixedbugs/bug037.go:6: s: undefined
+fixedbugs/bug037.go:6: undefined: vlong
+fixedbugs/bug037.go:6: undefined: s
=========== fixedbugs/bug039.go
fixedbugs/bug039.go:6: variable x redeclared in this block
broke
=========== fixedbugs/bug072.go
-fixedbugs/bug072.go:6: bug: undefined
+fixedbugs/bug072.go:6: undefined: bug
=========== fixedbugs/bug073.go
fixedbugs/bug073.go:8: illegal types for operand: LSH
fixedbugs/bug074.go:6: invalid type for composite literal: string
=========== fixedbugs/bug081.go
-fixedbugs/bug081.go:5: x is not a type
+fixedbugs/bug081.go:5: undefined: x
=========== fixedbugs/bug083.go
-fixedbugs/bug083.dir/bug1.go:9: cannot use type bug0.t0
+fixedbugs/bug083.dir/bug1.go:9: cannot refer to bug0.t0
=========== fixedbugs/bug086.go
fixedbugs/bug086.go:5: function ends without a return statement
=========== fixedbugs/bug091.go
-fixedbugs/bug091.go:15: c: undefined
+fixedbugs/bug091.go:15: undefined: c
fixedbugs/bug091.go:15: illegal types for operand: AS
undefined
=========== fixedbugs/bug103.go
fixedbugs/bug103.go:8: assignment count mismatch: 1 = 0
-fixedbugs/bug103.go:8: x: undefined
+fixedbugs/bug103.go:8: undefined: x
fixedbugs/bug103.go:8: function requires a return type
fixedbugs/bug103.go:8: illegal types for operand: AS
int
uint64
=========== fixedbugs/bug133.go
-fixedbugs/bug133.dir/bug2.go:11: undefined DOT i on bug0.T
+fixedbugs/bug133.dir/bug2.go:11: undefined: bug0.T field i
fixedbugs/bug133.dir/bug2.go:11: illegal types for operand: RETURN
int