mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
717de79976
commit
74e2e087e2
|
|
@ -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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
||||||
338
src/cmd/gc/dcl.c
338
src/cmd/gc/dcl.c
|
|
@ -20,38 +20,14 @@ 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(exportadj)
|
dowidth(t);
|
||||||
exportsym(n->sym);
|
|
||||||
addvar(n, t, dclcontext);
|
addvar(n, t, dclcontext);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dodcltype(Type *n, Type *t)
|
|
||||||
{
|
|
||||||
Type *nt;
|
|
||||||
|
|
||||||
if(n == T)
|
|
||||||
return;
|
|
||||||
if(t->sym != S) {
|
|
||||||
// botch -- should be a complete deep copy
|
|
||||||
nt = typ(Txxx);
|
|
||||||
*nt = *t;
|
|
||||||
t = nt;
|
|
||||||
t->sym = S;
|
|
||||||
}
|
|
||||||
n->sym->local = 1;
|
|
||||||
addtyp(n, t, dclcontext);
|
|
||||||
if(exportadj)
|
if(exportadj)
|
||||||
exportsym(n->sym);
|
exportsym(n->sym);
|
||||||
}
|
}
|
||||||
|
|
@ -59,49 +35,93 @@ dodcltype(Type *n, Type *t)
|
||||||
void
|
void
|
||||||
dodclconst(Node *n, Node *e)
|
dodclconst(Node *n, Node *e)
|
||||||
{
|
{
|
||||||
Sym *s;
|
|
||||||
Dcl *r, *d;
|
|
||||||
|
|
||||||
loop:
|
|
||||||
if(n == N)
|
if(n == N)
|
||||||
return;
|
return;
|
||||||
if(n->op == OLIST) {
|
|
||||||
dodclconst(n->left, e);
|
|
||||||
n = n->right;
|
|
||||||
goto loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(n->op != ONAME)
|
for(; n->op == OLIST; n=n->right)
|
||||||
fatal("dodclconst: not a name");
|
dodclconst(n, e);
|
||||||
|
|
||||||
if(e->op != OLITERAL) {
|
|
||||||
yyerror("expression must be a constant");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
s = n->sym;
|
|
||||||
|
|
||||||
s->oconst = e;
|
|
||||||
s->lexical = LACONST;
|
|
||||||
|
|
||||||
|
addconst(n, e, dclcontext);
|
||||||
if(exportadj)
|
if(exportadj)
|
||||||
exportsym(n->sym);
|
exportsym(n->sym);
|
||||||
|
|
||||||
r = autodcl;
|
|
||||||
if(dclcontext == PEXTERN)
|
|
||||||
r = externdcl;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* introduce a type named n
|
||||||
|
* but it is an unknown type for now
|
||||||
|
*/
|
||||||
|
Type*
|
||||||
|
dodcltype(Type *n)
|
||||||
|
{
|
||||||
|
Sym *s;
|
||||||
|
|
||||||
|
// if n has been forward declared,
|
||||||
|
// use the Type* created then
|
||||||
|
s = n->sym;
|
||||||
|
if(s->tblock == block) {
|
||||||
|
switch(s->otype->etype) {
|
||||||
|
case TFORWSTRUCT:
|
||||||
|
case TFORWINTER:
|
||||||
|
return s->otype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise declare a new type
|
||||||
|
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;
|
||||||
|
|
||||||
|
s = n->sym;
|
||||||
|
if(s == S || s->otype != n)
|
||||||
|
fatal("updatetype %T = %T", n, t);
|
||||||
|
|
||||||
|
switch(n->etype) {
|
||||||
|
case TFORW:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFORWSTRUCT:
|
||||||
|
if(t->etype != TSTRUCT) {
|
||||||
|
yyerror("%T forward declared as struct", n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFORWINTER:
|
||||||
|
if(t->etype != TINTER) {
|
||||||
|
yyerror("%T forward declared as interface", n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fatal("updatetype %T / %T", n, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
*n = *t;
|
||||||
|
n->sym = s;
|
||||||
|
|
||||||
|
// catch declaration of incomplete type
|
||||||
|
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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
|
||||||
// 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
|
||||||
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
|
||||||
TFIELD,
|
TFIELD,
|
||||||
TANY,
|
TANY,
|
||||||
TSTRING,
|
TSTRING,
|
||||||
|
TFORWSTRUCT,
|
||||||
|
TFORWINTER,
|
||||||
|
|
||||||
NTYPE, // 26
|
NTYPE, // 28
|
||||||
};
|
};
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
@ -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);
|
||||||
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 @@
|
||||||
%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:
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
Atypedcl
|
Atypedcl
|
||||||
| Btypedcl
|
| Btypedcl
|
||||||
|
|
||||||
Atypedcl:
|
typedclname:
|
||||||
new_type fullAtype
|
new_type
|
||||||
{
|
{
|
||||||
dodcltype($1, $2);
|
$$ = dodcltype($1);
|
||||||
|
defercheckwidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
Btypedcl:
|
Atypedcl:
|
||||||
new_type fullBtype
|
typedclname fullAtype
|
||||||
{
|
{
|
||||||
dodcltype($1, $2);
|
updatetype($1, $2);
|
||||||
|
resumecheckwidth();
|
||||||
|
}
|
||||||
|
| typedclname LSTRUCT
|
||||||
|
{
|
||||||
|
updatetype($1, typ(TFORWSTRUCT));
|
||||||
|
resumecheckwidth();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
| typedclname LINTERFACE
|
||||||
|
{
|
||||||
|
updatetype($1, typ(TFORWINTER));
|
||||||
|
resumecheckwidth();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Btypedcl:
|
||||||
|
typedclname fullBtype
|
||||||
|
{
|
||||||
|
updatetype($1, $2);
|
||||||
|
resumecheckwidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
else_stmt1:
|
else_stmt1:
|
||||||
|
|
@ -991,7 +1022,6 @@ non_name_Atype:
|
||||||
| interfacetype
|
| interfacetype
|
||||||
| '*' fullAtype
|
| '*' fullAtype
|
||||||
{
|
{
|
||||||
dowidth($2);
|
|
||||||
$$ = ptrto($2);
|
$$ = ptrto($2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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:
|
||||||
}
|
}
|
||||||
| '*' 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:
|
||||||
* 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:
|
||||||
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)
|
||||||
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:
|
||||||
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:
|
||||||
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:
|
||||||
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
|
||||||
=========== 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
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue