mirror of
https://github.com/golang/go
synced 2024-11-22 07:14:40 -07:00
gc: renamed walkdef to typecheckdef and moved from walk to typedef.
also inlined a typechecking function in dcl away. R=rsc CC=golang-dev https://golang.org/cl/4550115
This commit is contained in:
parent
f4f5836840
commit
ab8ed7f8dd
@ -438,20 +438,6 @@ newtype(Sym *s)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* type check top level declarations
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
dclchecks(void)
|
|
||||||
{
|
|
||||||
NodeList *l;
|
|
||||||
|
|
||||||
for(l=externdcl; l; l=l->next) {
|
|
||||||
if(l->n->op != ONAME)
|
|
||||||
continue;
|
|
||||||
typecheck(&l->n, Erv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* := declarations
|
* := declarations
|
||||||
|
@ -862,7 +862,6 @@ NodeList* checkarglist(NodeList *all, int input);
|
|||||||
Node* colas(NodeList *left, NodeList *right);
|
Node* colas(NodeList *left, NodeList *right);
|
||||||
void colasdefn(NodeList *left, Node *defn);
|
void colasdefn(NodeList *left, Node *defn);
|
||||||
NodeList* constiter(NodeList *vl, Node *t, NodeList *cl);
|
NodeList* constiter(NodeList *vl, Node *t, NodeList *cl);
|
||||||
void dclchecks(void);
|
|
||||||
Node* dclname(Sym *s);
|
Node* dclname(Sym *s);
|
||||||
void declare(Node *n, int ctxt);
|
void declare(Node *n, int ctxt);
|
||||||
Type* dostruct(NodeList *l, int et);
|
Type* dostruct(NodeList *l, int et);
|
||||||
@ -1166,6 +1165,11 @@ int exportassignok(Type *t, char *desc);
|
|||||||
int islvalue(Node *n);
|
int islvalue(Node *n);
|
||||||
Node* typecheck(Node **np, int top);
|
Node* typecheck(Node **np, int top);
|
||||||
void typechecklist(NodeList *l, int top);
|
void typechecklist(NodeList *l, int top);
|
||||||
|
Node* typecheckdef(Node *n);
|
||||||
|
void resumetypecopy(void);
|
||||||
|
void copytype(Node *n, Type *t);
|
||||||
|
void defertypecopy(Node *n, Type *t);
|
||||||
|
void queuemethod(Node *n);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* unsafe.c
|
* unsafe.c
|
||||||
@ -1177,15 +1181,10 @@ Node* unsafenmagic(Node *n);
|
|||||||
*/
|
*/
|
||||||
Node* callnew(Type *t);
|
Node* callnew(Type *t);
|
||||||
Node* chanfn(char *name, int n, Type *t);
|
Node* chanfn(char *name, int n, Type *t);
|
||||||
void copytype(Node *n, Type *t);
|
|
||||||
void defertypecopy(Node *n, Type *t);
|
|
||||||
Node* mkcall(char *name, Type *t, NodeList **init, ...);
|
Node* mkcall(char *name, Type *t, NodeList **init, ...);
|
||||||
Node* mkcall1(Node *fn, Type *t, NodeList **init, ...);
|
Node* mkcall1(Node *fn, Type *t, NodeList **init, ...);
|
||||||
void queuemethod(Node *n);
|
|
||||||
void resumetypecopy(void);
|
|
||||||
int vmatch1(Node *l, Node *r);
|
int vmatch1(Node *l, Node *r);
|
||||||
void walk(Node *fn);
|
void walk(Node *fn);
|
||||||
Node* walkdef(Node *n);
|
|
||||||
void walkexpr(Node **np, NodeList **init);
|
void walkexpr(Node **np, NodeList **init);
|
||||||
void walkexprlist(NodeList *l, NodeList **init);
|
void walkexprlist(NodeList *l, NodeList **init);
|
||||||
void walkexprlistsafe(NodeList *l, NodeList **init);
|
void walkexprlistsafe(NodeList *l, NodeList **init);
|
||||||
|
@ -274,7 +274,9 @@ main(int argc, char *argv[])
|
|||||||
funccompile(l->n, 1);
|
funccompile(l->n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dclchecks();
|
for(l=externdcl; l; l=l->next)
|
||||||
|
if(l->n->op == ONAME)
|
||||||
|
typecheck(&l->n, Erv);
|
||||||
|
|
||||||
if(nerrors)
|
if(nerrors)
|
||||||
errorexit();
|
errorexit();
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
* evaluates compile time constants.
|
* evaluates compile time constants.
|
||||||
* marks variables that escape the local frame.
|
* marks variables that escape the local frame.
|
||||||
* rewrites n->op to be more specific in some cases.
|
* rewrites n->op to be more specific in some cases.
|
||||||
* sets n->walk to walking function.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "go.h"
|
#include "go.h"
|
||||||
@ -33,6 +32,8 @@ static void stringtoarraylit(Node**);
|
|||||||
static Node* resolve(Node*);
|
static Node* resolve(Node*);
|
||||||
static Type* getforwtype(Node*);
|
static Type* getforwtype(Node*);
|
||||||
|
|
||||||
|
static NodeList* typecheckdefstack;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* resolve ONONAME to definition, if any.
|
* resolve ONONAME to definition, if any.
|
||||||
*/
|
*/
|
||||||
@ -159,7 +160,7 @@ typecheck(Node **np, int top)
|
|||||||
if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
|
if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
|
||||||
defertypecopy(n, ft);
|
defertypecopy(n, ft);
|
||||||
|
|
||||||
walkdef(n);
|
typecheckdef(n);
|
||||||
n->realtype = n->type;
|
n->realtype = n->type;
|
||||||
if(n->op == ONONAME)
|
if(n->op == ONONAME)
|
||||||
goto error;
|
goto error;
|
||||||
@ -2523,3 +2524,294 @@ getforwtype(Node *n)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ntypecheckdeftype;
|
||||||
|
static NodeList *methodqueue;
|
||||||
|
|
||||||
|
static void
|
||||||
|
domethod(Node *n)
|
||||||
|
{
|
||||||
|
Node *nt;
|
||||||
|
|
||||||
|
nt = n->type->nname;
|
||||||
|
typecheck(&nt, Etype);
|
||||||
|
if(nt->type == T) {
|
||||||
|
// type check failed; leave empty func
|
||||||
|
n->type->etype = TFUNC;
|
||||||
|
n->type->nod = N;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*n->type = *nt->type;
|
||||||
|
n->type->nod = N;
|
||||||
|
checkwidth(n->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct NodeTypeList NodeTypeList;
|
||||||
|
struct NodeTypeList {
|
||||||
|
Node *n;
|
||||||
|
Type *t;
|
||||||
|
NodeTypeList *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static NodeTypeList *dntq;
|
||||||
|
static NodeTypeList *dntend;
|
||||||
|
|
||||||
|
void
|
||||||
|
defertypecopy(Node *n, Type *t)
|
||||||
|
{
|
||||||
|
NodeTypeList *ntl;
|
||||||
|
|
||||||
|
if(n == N || t == T)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ntl = mal(sizeof *ntl);
|
||||||
|
ntl->n = n;
|
||||||
|
ntl->t = t;
|
||||||
|
ntl->next = nil;
|
||||||
|
|
||||||
|
if(dntq == nil)
|
||||||
|
dntq = ntl;
|
||||||
|
else
|
||||||
|
dntend->next = ntl;
|
||||||
|
|
||||||
|
dntend = ntl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
resumetypecopy(void)
|
||||||
|
{
|
||||||
|
NodeTypeList *l;
|
||||||
|
|
||||||
|
for(l=dntq; l; l=l->next)
|
||||||
|
copytype(l->n, l->t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
copytype(Node *n, Type *t)
|
||||||
|
{
|
||||||
|
*n->type = *t;
|
||||||
|
|
||||||
|
t = n->type;
|
||||||
|
t->sym = n->sym;
|
||||||
|
t->local = n->local;
|
||||||
|
t->vargen = n->vargen;
|
||||||
|
t->siggen = 0;
|
||||||
|
t->method = nil;
|
||||||
|
t->nod = N;
|
||||||
|
t->printed = 0;
|
||||||
|
t->deferwidth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
typecheckdeftype(Node *n)
|
||||||
|
{
|
||||||
|
int maplineno, embedlineno, lno;
|
||||||
|
Type *t;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
|
ntypecheckdeftype++;
|
||||||
|
lno = lineno;
|
||||||
|
setlineno(n);
|
||||||
|
n->type->sym = n->sym;
|
||||||
|
n->typecheck = 1;
|
||||||
|
typecheck(&n->ntype, Etype);
|
||||||
|
if((t = n->ntype->type) == T) {
|
||||||
|
n->diag = 1;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
if(n->type == T) {
|
||||||
|
n->diag = 1;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
maplineno = n->type->maplineno;
|
||||||
|
embedlineno = n->type->embedlineno;
|
||||||
|
|
||||||
|
// copy new type and clear fields
|
||||||
|
// that don't come along.
|
||||||
|
// anything zeroed here must be zeroed in
|
||||||
|
// typedcl2 too.
|
||||||
|
copytype(n, t);
|
||||||
|
|
||||||
|
// double-check use of type as map key.
|
||||||
|
if(maplineno) {
|
||||||
|
lineno = maplineno;
|
||||||
|
maptype(n->type, types[TBOOL]);
|
||||||
|
}
|
||||||
|
if(embedlineno) {
|
||||||
|
lineno = embedlineno;
|
||||||
|
if(isptr[t->etype])
|
||||||
|
yyerror("embedded type cannot be a pointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret:
|
||||||
|
lineno = lno;
|
||||||
|
|
||||||
|
// if there are no type definitions going on, it's safe to
|
||||||
|
// try to resolve the method types for the interfaces
|
||||||
|
// we just read.
|
||||||
|
if(ntypecheckdeftype == 1) {
|
||||||
|
while((l = methodqueue) != nil) {
|
||||||
|
methodqueue = nil;
|
||||||
|
for(; l; l=l->next)
|
||||||
|
domethod(l->n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ntypecheckdeftype--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
queuemethod(Node *n)
|
||||||
|
{
|
||||||
|
if(ntypecheckdeftype == 0) {
|
||||||
|
domethod(n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
methodqueue = list(methodqueue, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
typecheckdef(Node *n)
|
||||||
|
{
|
||||||
|
int lno;
|
||||||
|
Node *e;
|
||||||
|
Type *t;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
|
lno = lineno;
|
||||||
|
setlineno(n);
|
||||||
|
|
||||||
|
if(n->op == ONONAME) {
|
||||||
|
if(!n->diag) {
|
||||||
|
n->diag = 1;
|
||||||
|
if(n->lineno != 0)
|
||||||
|
lineno = n->lineno;
|
||||||
|
yyerror("undefined: %S", n->sym);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(n->walkdef == 1)
|
||||||
|
return n;
|
||||||
|
|
||||||
|
l = mal(sizeof *l);
|
||||||
|
l->n = n;
|
||||||
|
l->next = typecheckdefstack;
|
||||||
|
typecheckdefstack = l;
|
||||||
|
|
||||||
|
if(n->walkdef == 2) {
|
||||||
|
flusherrors();
|
||||||
|
print("typecheckdef loop:");
|
||||||
|
for(l=typecheckdefstack; l; l=l->next)
|
||||||
|
print(" %S", l->n->sym);
|
||||||
|
print("\n");
|
||||||
|
fatal("typecheckdef loop");
|
||||||
|
}
|
||||||
|
n->walkdef = 2;
|
||||||
|
|
||||||
|
if(n->type != T || n->sym == S) // builtin or no name
|
||||||
|
goto ret;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
fatal("typecheckdef %O", n->op);
|
||||||
|
|
||||||
|
case OLITERAL:
|
||||||
|
if(n->ntype != N) {
|
||||||
|
typecheck(&n->ntype, Etype);
|
||||||
|
n->type = n->ntype->type;
|
||||||
|
n->ntype = N;
|
||||||
|
if(n->type == T) {
|
||||||
|
n->diag = 1;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e = n->defn;
|
||||||
|
n->defn = N;
|
||||||
|
if(e == N) {
|
||||||
|
lineno = n->lineno;
|
||||||
|
dump("typecheckdef nil defn", n);
|
||||||
|
yyerror("xxx");
|
||||||
|
}
|
||||||
|
typecheck(&e, Erv | Eiota);
|
||||||
|
if(e->type != T && e->op != OLITERAL) {
|
||||||
|
yyerror("const initializer must be constant");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
if(isconst(e, CTNIL)) {
|
||||||
|
yyerror("const initializer cannot be nil");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
t = n->type;
|
||||||
|
if(t != T) {
|
||||||
|
if(!okforconst[t->etype]) {
|
||||||
|
yyerror("invalid constant type %T", t);
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
if(!isideal(e->type) && !eqtype(t, e->type)) {
|
||||||
|
yyerror("cannot use %+N as type %T in const initializer", e, t);
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
convlit(&e, t);
|
||||||
|
}
|
||||||
|
n->val = e->val;
|
||||||
|
n->type = e->type;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ONAME:
|
||||||
|
if(n->ntype != N) {
|
||||||
|
typecheck(&n->ntype, Etype);
|
||||||
|
n->type = n->ntype->type;
|
||||||
|
if(n->type == T) {
|
||||||
|
n->diag = 1;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(n->type != T)
|
||||||
|
break;
|
||||||
|
if(n->defn == N) {
|
||||||
|
if(n->etype != 0) // like OPRINTN
|
||||||
|
break;
|
||||||
|
if(nerrors > 0) {
|
||||||
|
// Can have undefined variables in x := foo
|
||||||
|
// that make x have an n->ndefn == nil.
|
||||||
|
// If there are other errors anyway, don't
|
||||||
|
// bother adding to the noise.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fatal("var without type, init: %S", n->sym);
|
||||||
|
}
|
||||||
|
if(n->defn->op == ONAME) {
|
||||||
|
typecheck(&n->defn, Erv);
|
||||||
|
n->type = n->defn->type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
typecheck(&n->defn, Etop); // fills in n->type
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OTYPE:
|
||||||
|
if(curfn)
|
||||||
|
defercheckwidth();
|
||||||
|
n->walkdef = 1;
|
||||||
|
n->type = typ(TFORW);
|
||||||
|
n->type->sym = n->sym;
|
||||||
|
typecheckdeftype(n);
|
||||||
|
if(curfn)
|
||||||
|
resumecheckwidth();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPACK:
|
||||||
|
// nothing to see here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret:
|
||||||
|
if(typecheckdefstack->n != n)
|
||||||
|
fatal("typecheckdefstack mismatch");
|
||||||
|
l = typecheckdefstack;
|
||||||
|
typecheckdefstack = l->next;
|
||||||
|
|
||||||
|
lineno = lno;
|
||||||
|
n->walkdef = 1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
@ -21,8 +21,6 @@ static Node* addstr(Node*, NodeList**);
|
|||||||
static Node* appendslice(Node*, NodeList**);
|
static Node* appendslice(Node*, NodeList**);
|
||||||
static Node* append(Node*, NodeList**);
|
static Node* append(Node*, NodeList**);
|
||||||
|
|
||||||
static NodeList* walkdefstack;
|
|
||||||
|
|
||||||
// can this code branch reach the end
|
// can this code branch reach the end
|
||||||
// without an unconditional RETURN
|
// without an unconditional RETURN
|
||||||
// this is hard, so it is conservative
|
// this is hard, so it is conservative
|
||||||
@ -100,296 +98,6 @@ walk(Node *fn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nwalkdeftype;
|
|
||||||
static NodeList *methodqueue;
|
|
||||||
|
|
||||||
static void
|
|
||||||
domethod(Node *n)
|
|
||||||
{
|
|
||||||
Node *nt;
|
|
||||||
|
|
||||||
nt = n->type->nname;
|
|
||||||
typecheck(&nt, Etype);
|
|
||||||
if(nt->type == T) {
|
|
||||||
// type check failed; leave empty func
|
|
||||||
n->type->etype = TFUNC;
|
|
||||||
n->type->nod = N;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*n->type = *nt->type;
|
|
||||||
n->type->nod = N;
|
|
||||||
checkwidth(n->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct NodeTypeList NodeTypeList;
|
|
||||||
struct NodeTypeList {
|
|
||||||
Node *n;
|
|
||||||
Type *t;
|
|
||||||
NodeTypeList *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static NodeTypeList *dntq;
|
|
||||||
static NodeTypeList *dntend;
|
|
||||||
|
|
||||||
void
|
|
||||||
defertypecopy(Node *n, Type *t)
|
|
||||||
{
|
|
||||||
NodeTypeList *ntl;
|
|
||||||
|
|
||||||
if(n == N || t == T)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ntl = mal(sizeof *ntl);
|
|
||||||
ntl->n = n;
|
|
||||||
ntl->t = t;
|
|
||||||
ntl->next = nil;
|
|
||||||
|
|
||||||
if(dntq == nil)
|
|
||||||
dntq = ntl;
|
|
||||||
else
|
|
||||||
dntend->next = ntl;
|
|
||||||
|
|
||||||
dntend = ntl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
resumetypecopy(void)
|
|
||||||
{
|
|
||||||
NodeTypeList *l;
|
|
||||||
|
|
||||||
for(l=dntq; l; l=l->next)
|
|
||||||
copytype(l->n, l->t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
copytype(Node *n, Type *t)
|
|
||||||
{
|
|
||||||
*n->type = *t;
|
|
||||||
|
|
||||||
t = n->type;
|
|
||||||
t->sym = n->sym;
|
|
||||||
t->local = n->local;
|
|
||||||
t->vargen = n->vargen;
|
|
||||||
t->siggen = 0;
|
|
||||||
t->method = nil;
|
|
||||||
t->nod = N;
|
|
||||||
t->printed = 0;
|
|
||||||
t->deferwidth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
walkdeftype(Node *n)
|
|
||||||
{
|
|
||||||
int maplineno, embedlineno, lno;
|
|
||||||
Type *t;
|
|
||||||
NodeList *l;
|
|
||||||
|
|
||||||
nwalkdeftype++;
|
|
||||||
lno = lineno;
|
|
||||||
setlineno(n);
|
|
||||||
n->type->sym = n->sym;
|
|
||||||
n->typecheck = 1;
|
|
||||||
typecheck(&n->ntype, Etype);
|
|
||||||
if((t = n->ntype->type) == T) {
|
|
||||||
n->diag = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
if(n->type == T) {
|
|
||||||
n->diag = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
maplineno = n->type->maplineno;
|
|
||||||
embedlineno = n->type->embedlineno;
|
|
||||||
|
|
||||||
// copy new type and clear fields
|
|
||||||
// that don't come along.
|
|
||||||
// anything zeroed here must be zeroed in
|
|
||||||
// typedcl2 too.
|
|
||||||
copytype(n, t);
|
|
||||||
|
|
||||||
// double-check use of type as map key.
|
|
||||||
if(maplineno) {
|
|
||||||
lineno = maplineno;
|
|
||||||
maptype(n->type, types[TBOOL]);
|
|
||||||
}
|
|
||||||
if(embedlineno) {
|
|
||||||
lineno = embedlineno;
|
|
||||||
if(isptr[t->etype])
|
|
||||||
yyerror("embedded type cannot be a pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
ret:
|
|
||||||
lineno = lno;
|
|
||||||
|
|
||||||
// if there are no type definitions going on, it's safe to
|
|
||||||
// try to resolve the method types for the interfaces
|
|
||||||
// we just read.
|
|
||||||
if(nwalkdeftype == 1) {
|
|
||||||
while((l = methodqueue) != nil) {
|
|
||||||
methodqueue = nil;
|
|
||||||
for(; l; l=l->next)
|
|
||||||
domethod(l->n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nwalkdeftype--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
queuemethod(Node *n)
|
|
||||||
{
|
|
||||||
if(nwalkdeftype == 0) {
|
|
||||||
domethod(n);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
methodqueue = list(methodqueue, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node*
|
|
||||||
walkdef(Node *n)
|
|
||||||
{
|
|
||||||
int lno;
|
|
||||||
Node *e;
|
|
||||||
Type *t;
|
|
||||||
NodeList *l;
|
|
||||||
|
|
||||||
lno = lineno;
|
|
||||||
setlineno(n);
|
|
||||||
|
|
||||||
if(n->op == ONONAME) {
|
|
||||||
if(!n->diag) {
|
|
||||||
n->diag = 1;
|
|
||||||
if(n->lineno != 0)
|
|
||||||
lineno = n->lineno;
|
|
||||||
yyerror("undefined: %S", n->sym);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(n->walkdef == 1)
|
|
||||||
return n;
|
|
||||||
|
|
||||||
l = mal(sizeof *l);
|
|
||||||
l->n = n;
|
|
||||||
l->next = walkdefstack;
|
|
||||||
walkdefstack = l;
|
|
||||||
|
|
||||||
if(n->walkdef == 2) {
|
|
||||||
flusherrors();
|
|
||||||
print("walkdef loop:");
|
|
||||||
for(l=walkdefstack; l; l=l->next)
|
|
||||||
print(" %S", l->n->sym);
|
|
||||||
print("\n");
|
|
||||||
fatal("walkdef loop");
|
|
||||||
}
|
|
||||||
n->walkdef = 2;
|
|
||||||
|
|
||||||
if(n->type != T || n->sym == S) // builtin or no name
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
switch(n->op) {
|
|
||||||
default:
|
|
||||||
fatal("walkdef %O", n->op);
|
|
||||||
|
|
||||||
case OLITERAL:
|
|
||||||
if(n->ntype != N) {
|
|
||||||
typecheck(&n->ntype, Etype);
|
|
||||||
n->type = n->ntype->type;
|
|
||||||
n->ntype = N;
|
|
||||||
if(n->type == T) {
|
|
||||||
n->diag = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e = n->defn;
|
|
||||||
n->defn = N;
|
|
||||||
if(e == N) {
|
|
||||||
lineno = n->lineno;
|
|
||||||
dump("walkdef nil defn", n);
|
|
||||||
yyerror("xxx");
|
|
||||||
}
|
|
||||||
typecheck(&e, Erv | Eiota);
|
|
||||||
if(e->type != T && e->op != OLITERAL) {
|
|
||||||
yyerror("const initializer must be constant");
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
if(isconst(e, CTNIL)) {
|
|
||||||
yyerror("const initializer cannot be nil");
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
t = n->type;
|
|
||||||
if(t != T) {
|
|
||||||
if(!okforconst[t->etype]) {
|
|
||||||
yyerror("invalid constant type %T", t);
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
if(!isideal(e->type) && !eqtype(t, e->type)) {
|
|
||||||
yyerror("cannot use %+N as type %T in const initializer", e, t);
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
convlit(&e, t);
|
|
||||||
}
|
|
||||||
n->val = e->val;
|
|
||||||
n->type = e->type;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ONAME:
|
|
||||||
if(n->ntype != N) {
|
|
||||||
typecheck(&n->ntype, Etype);
|
|
||||||
n->type = n->ntype->type;
|
|
||||||
if(n->type == T) {
|
|
||||||
n->diag = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(n->type != T)
|
|
||||||
break;
|
|
||||||
if(n->defn == N) {
|
|
||||||
if(n->etype != 0) // like OPRINTN
|
|
||||||
break;
|
|
||||||
if(nerrors > 0) {
|
|
||||||
// Can have undefined variables in x := foo
|
|
||||||
// that make x have an n->ndefn == nil.
|
|
||||||
// If there are other errors anyway, don't
|
|
||||||
// bother adding to the noise.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fatal("var without type, init: %S", n->sym);
|
|
||||||
}
|
|
||||||
if(n->defn->op == ONAME) {
|
|
||||||
typecheck(&n->defn, Erv);
|
|
||||||
n->type = n->defn->type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
typecheck(&n->defn, Etop); // fills in n->type
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OTYPE:
|
|
||||||
if(curfn)
|
|
||||||
defercheckwidth();
|
|
||||||
n->walkdef = 1;
|
|
||||||
n->type = typ(TFORW);
|
|
||||||
n->type->sym = n->sym;
|
|
||||||
walkdeftype(n);
|
|
||||||
if(curfn)
|
|
||||||
resumecheckwidth();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPACK:
|
|
||||||
// nothing to see here
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret:
|
|
||||||
if(walkdefstack->n != n)
|
|
||||||
fatal("walkdefstack mismatch");
|
|
||||||
l = walkdefstack;
|
|
||||||
walkdefstack = l->next;
|
|
||||||
|
|
||||||
lineno = lno;
|
|
||||||
n->walkdef = 1;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
walkstmtlist(NodeList *l)
|
walkstmtlist(NodeList *l)
|
||||||
|
Loading…
Reference in New Issue
Block a user