Commit 74e2e087 authored by Russ Cox's avatar Russ Cox

change type names to go live at the name, so that

	type T struct {
		next *T
	}

and

	type T *struct {
		next T
	}

are valid without needing forward declarations.

add "type T struct" syntax for forward struct declarations.

add "type T interface" syntax, but commented out
	(need to fix semicolons first)

R=ken
DELTA=452  (259 added, 115 deleted, 78 changed)
OCL=16580
CL=16584
parent 717de799
...@@ -105,6 +105,14 @@ dowidth(Type *t) ...@@ -105,6 +105,14 @@ dowidth(Type *t)
if(t == T) if(t == T)
return; return;
if(t->width == -2) {
yyerror("invalid recursive type %T", t);
t->width = 0;
return;
}
t->width = -2;
w = 0; w = 0;
switch(t->etype) { switch(t->etype) {
default: default:
...@@ -136,6 +144,7 @@ dowidth(Type *t) ...@@ -136,6 +144,7 @@ dowidth(Type *t)
w = 10; w = 10;
break; break;
case TINTER: // implemented as 2 pointers case TINTER: // implemented as 2 pointers
case TFORWINTER:
offmod(t); offmod(t);
w = 2*wptr; w = 2*wptr;
break; break;
...@@ -148,7 +157,9 @@ dowidth(Type *t) ...@@ -148,7 +157,9 @@ dowidth(Type *t)
dowidth(t->type); dowidth(t->type);
w = wptr; w = wptr;
break; break;
case TFORW: // implemented as pointer case TFORW: // should have been filled in
case TFORWSTRUCT:
yyerror("incomplete type %T", t);
w = wptr; w = wptr;
break; break;
case TANY: // implemented as pointer case TANY: // implemented as pointer
......
...@@ -453,7 +453,7 @@ agen(Node *n, Node *res) ...@@ -453,7 +453,7 @@ agen(Node *n, Node *res)
case OIND: case OIND:
cgen(nl, res); cgen(nl, res);
break; break;
case ODOT: case ODOT:
t = nl->type; t = nl->type;
agen(nl, res); agen(nl, res);
...@@ -632,7 +632,7 @@ bgen(Node *n, int true, Prog *to) ...@@ -632,7 +632,7 @@ bgen(Node *n, int true, Prog *to)
tempname(&tmp, nr->type); tempname(&tmp, nr->type);
gmove(&n1, &tmp); gmove(&n1, &tmp);
regfree(&n1); regfree(&n1);
regalloc(&n1, nl->type, N); regalloc(&n1, nl->type, N);
cgen(nl, &n1); cgen(nl, &n1);
...@@ -711,6 +711,9 @@ sgen(Node *n, Node *ns, int32 w) ...@@ -711,6 +711,9 @@ sgen(Node *n, Node *ns, int32 w)
fatal("sgen UINF"); fatal("sgen UINF");
} }
if(w < 0)
fatal("sgen copy %d", w);
// offset on the stack // offset on the stack
osrc = stkof(n); osrc = stkof(n);
odst = stkof(ns); odst = stkof(ns);
......
...@@ -672,7 +672,7 @@ cgen_proc(Node *n) ...@@ -672,7 +672,7 @@ cgen_proc(Node *n)
cgen_call(n->left, 1); cgen_call(n->left, 1);
break; break;
} }
} }
void void
...@@ -802,7 +802,10 @@ cgen_as(Node *nl, Node *nr, int op) ...@@ -802,7 +802,10 @@ cgen_as(Node *nl, Node *nr, int op)
if(debug['g']) if(debug['g'])
dump("\nclearfat", nl); dump("\nclearfat", nl);
if(nl->type->width < 0)
fatal("clearfat %T %lld", nl->type, nl->type->width);
w = nl->type->width; w = nl->type->width;
if(w > 0) if(w > 0)
gconreg(AMOVQ, 0, D_AX); gconreg(AMOVQ, 0, D_AX);
......
...@@ -20,88 +20,108 @@ dflag(void) ...@@ -20,88 +20,108 @@ dflag(void)
void void
dodclvar(Node *n, Type *t) dodclvar(Node *n, Type *t)
{ {
loop:
if(n == N) if(n == N)
return; return;
if(n->op == OLIST) { for(; n->op == OLIST; n = n->right)
dodclvar(n->left, t); dodclvar(n->left, t);
n = n->right;
goto loop;
}
dowidth(t);
addvar(n, t, dclcontext);
if(exportadj) if(exportadj)
exportsym(n->sym); exportsym(n->sym);
addvar(n, t, dclcontext);
} }
void void
dodcltype(Type *n, Type *t) dodclconst(Node *n, Node *e)
{ {
Type *nt; if(n == N)
if(n == T)
return; return;
if(t->sym != S) {
// botch -- should be a complete deep copy for(; n->op == OLIST; n=n->right)
nt = typ(Txxx); dodclconst(n, e);
*nt = *t;
t = nt; addconst(n, e, dclcontext);
t->sym = S;
}
n->sym->local = 1;
addtyp(n, t, dclcontext);
if(exportadj) if(exportadj)
exportsym(n->sym); exportsym(n->sym);
} }
void /*
dodclconst(Node *n, Node *e) * introduce a type named n
* but it is an unknown type for now
*/
Type*
dodcltype(Type *n)
{ {
Sym *s; Sym *s;
Dcl *r, *d;
loop: // if n has been forward declared,
if(n == N) // use the Type* created then
return; s = n->sym;
if(n->op == OLIST) { if(s->tblock == block) {
dodclconst(n->left, e); switch(s->otype->etype) {
n = n->right; case TFORWSTRUCT:
goto loop; case TFORWINTER:
return s->otype;
}
} }
if(n->op != ONAME) // otherwise declare a new type
fatal("dodclconst: not a name"); addtyp(n, dclcontext);
n->sym->local = 1;
if(exportadj)
exportsym(n->sym);
return n;
}
/*
* now we know what n is: it's t
*/
void
updatetype(Type *n, Type *t)
{
Sym *s;
if(e->op != OLITERAL) {
yyerror("expression must be a constant");
return;
}
s = n->sym; s = n->sym;
if(s == S || s->otype != n)
fatal("updatetype %T = %T", n, t);
s->oconst = e; switch(n->etype) {
s->lexical = LACONST; case TFORW:
break;
if(exportadj) case TFORWSTRUCT:
exportsym(n->sym); if(t->etype != TSTRUCT) {
yyerror("%T forward declared as struct", n);
return;
}
break;
r = autodcl; case TFORWINTER:
if(dclcontext == PEXTERN) if(t->etype != TINTER) {
r = externdcl; yyerror("%T forward declared as interface", n);
return;
}
break;
d = dcl(); default:
d->dsym = s; fatal("updatetype %T / %T", n, t);
d->dnode = e; }
d->op = OCONST;
r->back->forw = d; *n = *t;
r->back = d; n->sym = s;
if(dflag()) // catch declaration of incomplete type
print("const-dcl %S %N\n", n->sym, n->sym->oconst); switch(n->etype) {
case TFORWSTRUCT:
case TFORWINTER:
break;
default:
checkwidth(n);
}
} }
/* /*
* return nelem of list * return nelem of list
*/ */
...@@ -139,7 +159,7 @@ functype(Node *this, Node *in, Node *out) ...@@ -139,7 +159,7 @@ functype(Node *this, Node *in, Node *out)
t->outtuple = listcount(out); t->outtuple = listcount(out);
t->intuple = listcount(in); t->intuple = listcount(in);
dowidth(t); checkwidth(t);
return t; return t;
} }
...@@ -201,6 +221,9 @@ addmethod(Node *n, Type *t, int local) ...@@ -201,6 +221,9 @@ addmethod(Node *n, Type *t, int local)
Type *f, *d, *pa; Type *f, *d, *pa;
Sym *st, *sf; Sym *st, *sf;
pa = nil;
sf = nil;
// get field sym // get field sym
if(n == N) if(n == N)
goto bad; goto bad;
...@@ -465,7 +488,7 @@ dostruct(Node *n, int et) ...@@ -465,7 +488,7 @@ dostruct(Node *n, int et)
t = typ(et); t = typ(et);
stotype(n, &t->type); stotype(n, &t->type);
dowidth(t); checkwidth(t);
return t; return t;
} }
...@@ -484,12 +507,13 @@ dcopy(Sym *a, Sym *b) ...@@ -484,12 +507,13 @@ dcopy(Sym *a, Sym *b)
a->oconst = b->oconst; a->oconst = b->oconst;
a->package = b->package; a->package = b->package;
a->opackage = b->opackage; a->opackage = b->opackage;
a->forwtype = b->forwtype;
a->lexical = b->lexical; a->lexical = b->lexical;
a->undef = b->undef; a->undef = b->undef;
a->vargen = b->vargen; a->vargen = b->vargen;
a->vblock = b->vblock; a->vblock = b->vblock;
a->tblock = b->tblock; a->tblock = b->tblock;
a->local = b->local;
a->offset = b->offset;
} }
Sym* Sym*
...@@ -639,14 +663,6 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -639,14 +663,6 @@ addvar(Node *n, Type *t, int ctxt)
fatal("addvar: n=%N t=%T nil", n, t); fatal("addvar: n=%N t=%T nil", n, t);
s = n->sym; s = n->sym;
vargen++;
gen = vargen;
r = autodcl;
if(ctxt == PEXTERN) {
r = externdcl;
gen = 0;
}
if(s->vblock == block) { if(s->vblock == block) {
if(s->oname != N) { if(s->oname != N) {
...@@ -657,8 +673,16 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -657,8 +673,16 @@ addvar(Node *n, Type *t, int ctxt)
yyerror("var %S redeclared in this block", s); yyerror("var %S redeclared in this block", s);
} }
if(ctxt != PEXTERN) if(ctxt == PEXTERN) {
r = externdcl;
gen = 0;
vargen++; // just for diffing output against old compiler
} else {
r = autodcl;
vargen++;
gen = vargen;
pushdcl(s); pushdcl(s);
}
s->vargen = gen; s->vargen = gen;
s->oname = n; s->oname = n;
...@@ -687,65 +711,34 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -687,65 +711,34 @@ addvar(Node *n, Type *t, int ctxt)
} }
void void
addtyp(Type *n, Type *t, int ctxt) addtyp(Type *n, int ctxt)
{ {
Dcl *r, *d; Dcl *r, *d;
Sym *s; Sym *s;
Type *f, *ot;
if(n==T || n->sym == S || t == T) if(n==T || n->sym == S)
fatal("addtyp: n=%T t=%T nil", n, t); fatal("addtyp: n=%T t=%T nil", n);
s = n->sym; s = n->sym;
r = autodcl; if(ctxt == PEXTERN)
if(ctxt == PEXTERN) {
ot = s->otype;
if(ot != T) {
// allow nil interface to be
// redeclared as an interface
if(ot->etype == TINTER && ot->type == T && t->etype == TINTER) {
if(dflag())
print("forew typ-dcl %S G%ld %T\n", s, s->vargen, t);
s->otype = t;
return;
}
}
r = externdcl; r = externdcl;
else {
r = autodcl;
pushdcl(s);
} }
vargen++; // just for diffing output against old compiler
if(s->tblock == block) if(s->tblock == block)
yyerror("type %S redeclared in this block %d", s, block); yyerror("type %S redeclared in this block %d", s, block);
if(ctxt != PEXTERN) s->otype = n;
pushdcl(s);
if(t->sym != S)
warn("addtyp: renaming type %S/%lT to %S/%lT",
t->sym, t->sym->otype, s, n);
vargen++;
s->vargen = vargen;
s->otype = t;
s->lexical = LATYPE; s->lexical = LATYPE;
s->tblock = block; s->tblock = block;
t->sym = s;
t->vargen = vargen;
if(s->forwtype != T) {
dowidth(t);
for(f=s->forwtype; f!=T; f=f->nforw) {
if(!isptr[f->etype])
fatal("addtyp: forward");
f->type = t;
}
s->forwtype = T;
}
d = dcl(); d = dcl();
d->dsym = s; d->dsym = s;
d->dtype = t; d->dtype = n;
d->op = OTYPE; d->op = OTYPE;
r->back->forw = d; r->back->forw = d;
...@@ -753,12 +746,50 @@ addtyp(Type *n, Type *t, int ctxt) ...@@ -753,12 +746,50 @@ addtyp(Type *n, Type *t, int ctxt)
if(dflag()) { if(dflag()) {
if(ctxt == PEXTERN) if(ctxt == PEXTERN)
print("extern typ-dcl %S G%ld %T\n", s, s->vargen, t); print("extern typ-dcl %S G%ld %T\n", s, s->vargen, n);
else else
print("auto typ-dcl %S G%ld %T\n", s, s->vargen, t); print("auto typ-dcl %S G%ld %T\n", s, s->vargen, n);
} }
} }
void
addconst(Node *n, Node *e, int ctxt)
{
Sym *s;
Dcl *r, *d;
if(n->op != ONAME)
fatal("addconst: not a name");
if(e->op != OLITERAL) {
yyerror("expression must be a constant");
return;
}
s = n->sym;
if(ctxt == PEXTERN)
r = externdcl;
else {
r = autodcl;
pushdcl(s);
}
s->oconst = e;
s->lexical = LACONST;
d = dcl();
d->dsym = s;
d->dnode = e;
d->op = OCONST;
r->back->forw = d;
r->back = d;
if(dflag())
print("const-dcl %S %N\n", n->sym, n->sym->oconst);
}
Node* Node*
fakethis(void) fakethis(void)
{ {
...@@ -850,9 +881,6 @@ forwdcl(Sym *s) ...@@ -850,9 +881,6 @@ forwdcl(Sym *s)
t = typ(TFORW); t = typ(TFORW);
t = ptrto(t); t = ptrto(t);
t->nforw = s->forwtype;
s->forwtype = t;
return t; return t;
} }
...@@ -1038,3 +1066,75 @@ fninit(Node *n) ...@@ -1038,3 +1066,75 @@ fninit(Node *n)
popdcl(); popdcl();
compile(fn); compile(fn);
} }
/*
* when a type's width should be known, we call checkwidth
* to compute it. during a declaration like
*
* type T *struct { next T }
*
* it is necessary to defer the calculation of the struct width
* until after T has been initialized to be a pointer to that struct.
* similarly, during import processing structs may be used
* before their definition. in those situations, calling
* defercheckwidth() stops width calculations until
* resumecheckwidth() is called, at which point all the
* checkwidths that were deferred are executed.
* sometimes it is okay to
*/
typedef struct TypeList TypeList;
struct TypeList {
Type *t;
TypeList *next;
};
static TypeList *tlfree;
static TypeList *tlq;
static int defercalc;
void
checkwidth(Type *t)
{
TypeList *l;
if(!defercalc) {
dowidth(t);
return;
}
l = tlfree;
if(l != nil)
tlfree = l->next;
else
l = mal(sizeof *l);
l->t = t;
l->next = tlq;
tlq = l;
}
void
defercheckwidth(void)
{
if(defercalc)
fatal("defercheckwidth");
defercalc = 1;
}
void
resumecheckwidth(void)
{
TypeList *l, *next;
if(!defercalc)
fatal("restartcheckwidth");
defercalc = 0;
for(l = tlq; l != nil; l = tlq) {
dowidth(l->t);
tlq = l->next;
l->next = tlfree;
tlfree = l;
}
}
...@@ -300,6 +300,7 @@ importvar(int export, Node *ss, Type *t) ...@@ -300,6 +300,7 @@ importvar(int export, Node *ss, Type *t)
warn("redeclare import var %S from %T to %T", warn("redeclare import var %S from %T to %T",
s, s->oname->type, t); s, s->oname->type, t);
} }
checkwidth(t);
addvar(newname(s), t, PEXTERN); addvar(newname(s), t, PEXTERN);
if(debug['e']) if(debug['e'])
...@@ -325,6 +326,7 @@ importtype(int export, Node *ss, Type *t) ...@@ -325,6 +326,7 @@ importtype(int export, Node *ss, Type *t)
s->otype = typ(0); s->otype = typ(0);
*s->otype = *t; *s->otype = *t;
s->otype->sym = s; s->otype->sym = s;
checkwidth(s->otype);
if(debug['e']) if(debug['e'])
print("import type %S %lT\n", s, t); print("import type %S %lT\n", s, t);
...@@ -333,7 +335,7 @@ importtype(int export, Node *ss, Type *t) ...@@ -333,7 +335,7 @@ importtype(int export, Node *ss, Type *t)
void void
importmethod(Sym *s, Type *t) importmethod(Sym *s, Type *t)
{ {
dowidth(t); checkwidth(t);
addmethod(newname(s), t, 0); addmethod(newname(s), t, 0);
} }
......
...@@ -146,9 +146,6 @@ struct Type ...@@ -146,9 +146,6 @@ struct Type
// TFIELD // TFIELD
Type* down; // also used in TMAP Type* down; // also used in TMAP
// TPTR
Type* nforw;
// TARRAY // TARRAY
int32 bound; // negative is dynamic array int32 bound; // negative is dynamic array
}; };
...@@ -215,7 +212,6 @@ struct Sym ...@@ -215,7 +212,6 @@ struct Sym
Node* oname; // ONAME node if a var Node* oname; // ONAME node if a var
Type* otype; // TYPE node if a type Type* otype; // TYPE node if a type
Node* oconst; // OLITERAL node if a const Node* oconst; // OLITERAL node if a const
Type* forwtype; // TPTR iff forward declared
vlong offset; // stack location if automatic vlong offset; // stack location if automatic
int32 lexical; int32 lexical;
int32 vargen; // unique variable number int32 vargen; // unique variable number
...@@ -322,8 +318,10 @@ enum ...@@ -322,8 +318,10 @@ enum
TFIELD, TFIELD,
TANY, TANY,
TSTRING, TSTRING,
TFORWSTRUCT,
TFORWINTER,
NTYPE, // 26 NTYPE, // 28
}; };
enum enum
{ {
...@@ -624,7 +622,8 @@ int Zconv(Fmt*); ...@@ -624,7 +622,8 @@ int Zconv(Fmt*);
* dcl.c * dcl.c
*/ */
void dodclvar(Node*, Type*); void dodclvar(Node*, Type*);
void dodcltype(Type*, Type*); Type* dodcltype(Type*);
void updatetype(Type*, Type*);
void dodclconst(Node*, Node*); void dodclconst(Node*, Node*);
void defaultlit(Node*); void defaultlit(Node*);
int listcount(Node*); int listcount(Node*);
...@@ -648,18 +647,21 @@ void markdclstack(void); ...@@ -648,18 +647,21 @@ void markdclstack(void);
void testdclstack(void); void testdclstack(void);
Sym* pushdcl(Sym*); Sym* pushdcl(Sym*);
void addvar(Node*, Type*, int); void addvar(Node*, Type*, int);
void addtyp(Type*, Type*, int); void addtyp(Type*, int);
void addconst(Node*, Node*, int);
Node* fakethis(void); Node* fakethis(void);
Node* newname(Sym*); Node* newname(Sym*);
Node* oldname(Sym*); Node* oldname(Sym*);
Type* newtype(Sym*); Type* newtype(Sym*);
Type* oldtype(Sym*); Type* oldtype(Sym*);
Type* forwdcl(Sym*);
void fninit(Node*); void fninit(Node*);
Node* nametoanondcl(Node*); Node* nametoanondcl(Node*);
Node* nametodcl(Node*, Type*); Node* nametodcl(Node*, Type*);
Node* anondcl(Type*); Node* anondcl(Type*);
void checkarglist(Node*); void checkarglist(Node*);
void checkwidth(Type*);
void defercheckwidth(void);
void resumecheckwidth(void);
/* /*
* export.c * export.c
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody %type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> keyexpr_list keyval_list_r keyval %type <node> keyexpr_list keyval_list_r keyval
%type <node> typedcl Atypedcl Btypedcl %type <node> typedcl Atypedcl Btypedcl
%type <type> typedclname
%type <type> fntype fnlitdcl Afntype Bfntype fullAtype %type <type> fntype fnlitdcl Afntype Bfntype fullAtype
%type <type> non_name_Atype non_name_type %type <type> non_name_Atype non_name_type
...@@ -137,16 +138,25 @@ import_package: ...@@ -137,16 +138,25 @@ import_package:
} }
import_there: import_there:
hidden_import_list_r '$' '$' hidden_import_list '$' '$'
{ {
checkimports(); checkimports();
unimportfile(); unimportfile();
} }
| LIMPORT '$' '$' hidden_import_list_r '$' '$' | LIMPORT '$' '$' hidden_import_list '$' '$'
{ {
checkimports(); checkimports();
} }
hidden_import_list:
{
defercheckwidth();
}
hidden_import_list_r
{
resumecheckwidth();
}
/* /*
* declarations * declarations
*/ */
...@@ -317,16 +327,37 @@ typedcl: ...@@ -317,16 +327,37 @@ typedcl:
Atypedcl Atypedcl
| Btypedcl | Btypedcl
typedclname:
new_type
{
$$ = dodcltype($1);
defercheckwidth();
}
Atypedcl: Atypedcl:
new_type fullAtype typedclname fullAtype
{
updatetype($1, $2);
resumecheckwidth();
}
| typedclname LSTRUCT
{ {
dodcltype($1, $2); updatetype($1, typ(TFORWSTRUCT));
resumecheckwidth();
} }
/*
| typedclname LINTERFACE
{
updatetype($1, typ(TFORWINTER));
resumecheckwidth();
}
*/
Btypedcl: Btypedcl:
new_type fullBtype typedclname fullBtype
{ {
dodcltype($1, $2); updatetype($1, $2);
resumecheckwidth();
} }
else_stmt1: else_stmt1:
...@@ -991,7 +1022,6 @@ non_name_Atype: ...@@ -991,7 +1022,6 @@ non_name_Atype:
| interfacetype | interfacetype
| '*' fullAtype | '*' fullAtype
{ {
dowidth($2);
$$ = ptrto($2); $$ = ptrto($2);
} }
...@@ -1033,15 +1063,15 @@ Btype: ...@@ -1033,15 +1063,15 @@ Btype:
} }
| '*' fullBtype | '*' fullBtype
{ {
dowidth($2);
$$ = ptrto($2); $$ = ptrto($2);
} }
| '*' lname | '*' lname
{ {
// dont know if this is an error or not Type *t;
if(dclcontext != PEXTERN)
yyerror("forward type in function body %s", $2->name); t = dodcltype(newtype($2));
$$ = forwdcl($2); updatetype(t, typ(TFORWSTRUCT));
$$ = ptrto(t);
} }
Bchantype: Bchantype:
...@@ -1721,7 +1751,7 @@ hidden_type1: ...@@ -1721,7 +1751,7 @@ hidden_type1:
} }
| '*' hidden_type | '*' hidden_type
{ {
dowidth($2); checkwidth($2);
$$ = ptrto($2); $$ = ptrto($2);
} }
| LCOMM LCHAN hidden_type | LCOMM LCHAN hidden_type
...@@ -1823,7 +1853,7 @@ hidden_importsym: ...@@ -1823,7 +1853,7 @@ hidden_importsym:
* to check whether the rest of the grammar is free of * to check whether the rest of the grammar is free of
* reduce/reduce conflicts, comment this section out by * reduce/reduce conflicts, comment this section out by
* removing the slash on the next line. * removing the slash on the next line.
* */
lpack: lpack:
LATYPE LATYPE
{ {
...@@ -1867,6 +1897,5 @@ latype: ...@@ -1867,6 +1897,5 @@ latype:
yyerror("no type %s.%s", context, $3->name); yyerror("no type %s.%s", context, $3->name);
YYERROR; YYERROR;
} }
/**/ /**/
...@@ -1543,7 +1543,7 @@ eqtype(Type *t1, Type *t2, int d) ...@@ -1543,7 +1543,7 @@ eqtype(Type *t1, Type *t2, int d)
t1 = t1->type; t1 = t1->type;
t2 = t2->type; t2 = t2->type;
for(;;) { for(;;) {
if(!eqtype(t1, t2, 0)) if(!eqtype(t1, t2, d+1))
return 0; return 0;
if(t1 == T) if(t1 == T)
return 1; return 1;
......
...@@ -253,7 +253,7 @@ loop: ...@@ -253,7 +253,7 @@ loop:
if(n->type == T) { if(n->type == T) {
s = n->sym; s = n->sym;
if(s->undef == 0) { if(s->undef == 0) {
yyerror("walktype: %N undeclared", n); yyerror("walktype: %S undeclared", s);
s->undef = 1; s->undef = 1;
} }
} }
...@@ -334,7 +334,6 @@ loop: ...@@ -334,7 +334,6 @@ loop:
if(t == T) if(t == T)
goto ret; goto ret;
dowidth(t);
if(n->left->op == ODOTMETH) if(n->left->op == ODOTMETH)
n->op = OCALLMETH; n->op = OCALLMETH;
if(n->left->op == ODOTINTER) if(n->left->op == ODOTINTER)
...@@ -348,6 +347,7 @@ loop: ...@@ -348,6 +347,7 @@ loop:
goto ret; goto ret;
} }
dowidth(t);
n->type = *getoutarg(t); n->type = *getoutarg(t);
switch(t->outtuple) { switch(t->outtuple) {
case 0: case 0:
......
...@@ -97,13 +97,6 @@ BUG: compilation succeeds incorrectly ...@@ -97,13 +97,6 @@ BUG: compilation succeeds incorrectly
=========== bugs/bug093.go =========== bugs/bug093.go
M M
=========== bugs/bug094.go
bugs/bug094.go:11: left side of := must be a name
bad top
. LITERAL-I0 l(81)
bugs/bug094.go:11: fatal error: walktype: top=3 LITERAL
BUG: fails incorrectly
=========== bugs/bug095.go =========== bugs/bug095.go
found 2, expected 1 found 2, expected 1
...@@ -232,7 +225,8 @@ fixedbugs/bug081.go:5: syntax error near x ...@@ -232,7 +225,8 @@ fixedbugs/bug081.go:5: syntax error near x
fixedbugs/bug086.go:5: function ends without a return statement fixedbugs/bug086.go:5: function ends without a return statement
=========== fixedbugs/bug091.go =========== fixedbugs/bug091.go
fixedbugs/bug091.go:14: label exit not defined fixedbugs/bug091.go:15: c: undefined
fixedbugs/bug091.go:15: fatal error: addvar: n=NAME-i G0 a(1) l(85) t=<T> nil
=========== fixedbugs/bug103.go =========== fixedbugs/bug103.go
fixedbugs/bug103.go:8: function requires a return type fixedbugs/bug103.go:8: function requires a return type
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