1
0
mirror of https://github.com/golang/go synced 2024-11-25 21:57:57 -07:00

introduce typecheck pass before walkexpr.

not complete but compiler still works.

R=ken
OCL=32424
CL=32426
This commit is contained in:
Russ Cox 2009-07-29 12:47:51 -07:00
parent 056940d84b
commit 9271c6402e
6 changed files with 421 additions and 136 deletions

View File

@ -257,8 +257,10 @@ typeinit(void)
* initialize okfor * initialize okfor
*/ */
for(i=0; i<NTYPE; i++) { for(i=0; i<NTYPE; i++) {
if(isint[i]) { if(isint[i] || i == TIDEAL) {
okforeq[i] = 1; okforeq[i] = 1;
okforcmp[i] = 1;
okforarith[i] = 1;
okforadd[i] = 1; okforadd[i] = 1;
okforand[i] = 1; okforand[i] = 1;
issimple[i] = 1; issimple[i] = 1;
@ -267,25 +269,75 @@ typeinit(void)
} }
if(isfloat[i]) { if(isfloat[i]) {
okforeq[i] = 1; okforeq[i] = 1;
okforcmp[i] = 1;
okforadd[i] = 1; okforadd[i] = 1;
okforarith[i] = 1;
issimple[i] = 1; issimple[i] = 1;
minfltval[i] = mal(sizeof(*minfltval[i])); minfltval[i] = mal(sizeof(*minfltval[i]));
maxfltval[i] = mal(sizeof(*maxfltval[i])); maxfltval[i] = mal(sizeof(*maxfltval[i]));
} }
switch(i) { }
case TBOOL:
issimple[i] = 1;
case TPTR32: issimple[TBOOL] = 1;
case TPTR64:
case TINTER: okforadd[TSTRING] = 1;
case TMAP:
case TCHAN: okforbool[TBOOL] = 1;
case TFUNC:
okforeq[i] = 1; okforcap[TARRAY] = 1;
break; //okforcap[TCHAN] = 1;
} //okforcap[TMAP] = 1;
}
okforlen[TARRAY] = 1;
//okforlen[TCHAN] = 1;
okforlen[TMAP] = 1;
okforlen[TSTRING] = 1;
okforeq[TPTR32] = 1;
okforeq[TPTR64] = 1;
okforeq[TINTER] = 1;
okforeq[TMAP] = 1;
okforeq[TCHAN] = 1;
okforeq[TFUNC] = 1;
okforeq[TSTRING] = 1;
okforeq[TBOOL] = 1;
okforeq[TARRAY] = 1; // refined in typecheck
okforcmp[TSTRING] = 1;
for(i=0; i<nelem(okfor); i++)
okfor[i] = okfornone;
// binary
okfor[OADD] = okforadd;
okfor[OAND] = okforand;
okfor[OANDAND] = okforbool;
okfor[OANDNOT] = okforand;
okfor[ODIV] = okforarith;
okfor[OEQ] = okforeq;
okfor[OGE] = okforcmp;
okfor[OGT] = okforcmp;
okfor[OLE] = okforcmp;
okfor[OLT] = okforcmp;
okfor[OMOD] = okforarith;
okfor[OMUL] = okforarith;
okfor[ONE] = okforeq;
okfor[OOR] = okforand;
okfor[OOROR] = okforbool;
okfor[OSUB] = okforarith;
okfor[OXOR] = okforand;
okfor[OLSH] = okforand;
okfor[ORSH] = okforand;
// unary
okfor[OCOM] = okforand;
okfor[OMINUS] = okforarith;
okfor[ONOT] = okforbool;
okfor[OPLUS] = okforadd;
// special
okfor[OCAP] = okforcap;
okfor[OLEN] = okforlen;
mpatofix(maxintval[TINT8], "0x7f"); mpatofix(maxintval[TINT8], "0x7f");
mpatofix(minintval[TINT8], "-0x80"); mpatofix(minintval[TINT8], "-0x80");

View File

@ -587,6 +587,12 @@ unary:
} }
return; return;
case TUP(OCONV, CTINT):
case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR):
convlit1(&nl, n->type, 1);
break;
case TUP(OPLUS, CTINT): case TUP(OPLUS, CTINT):
break; break;
case TUP(OMINUS, CTINT): case TUP(OMINUS, CTINT):
@ -711,7 +717,7 @@ defaultlit(Node **np, Type *t)
lineno = n->lineno; lineno = n->lineno;
switch(n->val.ctype) { switch(n->val.ctype) {
default: default:
yyerror("defaultlit: unknown literal: %N", n); yyerror("defaultlit: unknown literal: %#N", n);
break; break;
case CTINT: case CTINT:
n->type = types[TINT]; n->type = types[TINT];

View File

@ -195,6 +195,7 @@ struct Node
uchar funcdepth; uchar funcdepth;
uchar builtin; // built-in name, like len or close uchar builtin; // built-in name, like len or close
uchar walkdef; uchar walkdef;
uchar typecheck;
// most nodes // most nodes
Node* left; Node* left;
@ -435,12 +436,11 @@ enum
enum enum
{ {
Exxx, Etop = 1<<1, // evaluated at statement level
Eyyy, Elv = 1<<2, // evaluated in lvalue context
Etop, // evaluated at statement level Erv = 1<<3, // evaluated in rvalue context
Elv, // evaluated in lvalue context Etype = 1<<4,
Erv, // evaluated in rvalue context Eideal = 1<<5,
Etype = 1<<8,
}; };
#define BITS 5 #define BITS 5
@ -574,6 +574,7 @@ EXTERN char* filename; // name to uniqify names
EXTERN Idir* idirs; EXTERN Idir* idirs;
EXTERN Type* types[NTYPE]; EXTERN Type* types[NTYPE];
EXTERN Type* idealstring;
EXTERN uchar simtype[NTYPE]; EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE]; EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE]; EXTERN uchar isforw[NTYPE];
@ -581,10 +582,17 @@ EXTERN uchar isint[NTYPE];
EXTERN uchar isfloat[NTYPE]; EXTERN uchar isfloat[NTYPE];
EXTERN uchar issigned[NTYPE]; EXTERN uchar issigned[NTYPE];
EXTERN uchar issimple[NTYPE]; EXTERN uchar issimple[NTYPE];
EXTERN uchar okforeq[NTYPE]; EXTERN uchar okforeq[NTYPE];
EXTERN uchar okforadd[NTYPE]; EXTERN uchar okforadd[NTYPE];
EXTERN uchar okforand[NTYPE]; EXTERN uchar okforand[NTYPE];
EXTERN Type* idealstring; EXTERN uchar okfornone[NTYPE];
EXTERN uchar okforcmp[NTYPE];
EXTERN uchar okforbool[NTYPE];
EXTERN uchar okforcap[NTYPE];
EXTERN uchar okforlen[NTYPE];
EXTERN uchar okforarith[NTYPE];
EXTERN uchar* okfor[OEND];
EXTERN Mpint* minintval[NTYPE]; EXTERN Mpint* minintval[NTYPE];
EXTERN Mpint* maxintval[NTYPE]; EXTERN Mpint* maxintval[NTYPE];
@ -977,6 +985,8 @@ void addrescapes(Node*);
void heapmoves(void); void heapmoves(void);
void walkdeflist(NodeList*); void walkdeflist(NodeList*);
void walkdef(Node*); void walkdef(Node*);
void typechecklist(NodeList*, int);
Node* typecheck(Node**, int);
/* /*
* const.c * const.c

View File

@ -2123,7 +2123,6 @@ out:
void void
badtype(int o, Type *tl, Type *tr) badtype(int o, Type *tl, Type *tr)
{ {
yyerror("illegal types for operand: %O", o); yyerror("illegal types for operand: %O", o);
if(tl != T) if(tl != T)
print(" %T\n", tl); print(" %T\n", tl);
@ -2346,7 +2345,6 @@ tempname(Node *n, Type *t)
n->op = ONAME; n->op = ONAME;
n->sym = s; n->sym = s;
n->type = t; n->type = t;
n->etype = t->etype;
n->class = PAUTO; n->class = PAUTO;
n->addable = 1; n->addable = 1;
n->ullman = 1; n->ullman = 1;

View File

@ -137,6 +137,10 @@ walkdef(Node *n)
} }
n->walkdef = 2; n->walkdef = 2;
if(n->type != T || n->sym == S) // builtin or no name
goto ret;
init = nil; init = nil;
switch(n->op) { switch(n->op) {
case OLITERAL: case OLITERAL:
@ -151,8 +155,11 @@ walkdef(Node *n)
} }
e = n->defn; e = n->defn;
n->defn = N; n->defn = N;
if(e == N) if(e == N) {
dump("walkdef", n); lineno = n->lineno;
dump("walkdef nil defn", n);
yyerror("xxx");
}
walkexpr(&e, Erv, &init); walkexpr(&e, Erv, &init);
if(e->op != OLITERAL) { if(e->op != OLITERAL) {
yyerror("const initializer must be constant"); yyerror("const initializer must be constant");
@ -313,6 +320,299 @@ implicitstar(Node **nn)
*nn = n; *nn = n;
} }
void
typechecklist(NodeList *l, int top)
{
for(; l; l=l->next)
typecheck(&l->n, top);
}
/*
* type check the whole tree of an expression.
* calculates expression types.
* evaluates compile time constants.
* marks variables that escape the local frame.
* rewrites n->op to be more specific in some cases.
* replaces *np with a new pointer in some cases.
* returns the final value of *np as a convenience.
*/
Node*
typecheck(Node **np, int top)
{
int et, et1, et2;
Node *n, *l, *r;
int lno, ok;
Type *t;
n = *np;
if(n == N || n->typecheck == 1)
return n;
if(n->typecheck == 2)
fatal("typecheck loop");
n->typecheck = 2;
if(n->sym && n->walkdef != 1)
walkdef(n);
lno = setlineno(n);
ok = 0;
switch(n->op) {
default:
// until typecheck is complete, do nothing.
goto ret;
dump("typecheck", n);
fatal("typecheck %O", n->op);
/*
* names
*/
case OLITERAL:
ok |= Erv;
goto ret;
case ONONAME:
ok |= Elv | Erv;
goto ret;
case ONAME:
if(n->etype != 0) {
yyerror("must call builtin %S", n->sym);
goto error;
}
ok |= Erv;
if(n->class != PFUNC)
ok |= Elv;
goto ret;
/*
* types (OIND is with exprs)
*/
case OTYPE:
ok |= Etype;
if(n->type == T)
goto error;
break;
case OTARRAY:
ok |= Etype;
t = typ(TARRAY);
l = n->left;
r = n->right;
if(l == nil) {
t->bound = -1;
} else {
typecheck(&l, Erv | Etype);
walkexpr(&l, Erv | Etype, &n->ninit); // TODO: remove
switch(l->op) {
default:
yyerror("invalid array bound %O", l->op);
goto error;
case OLITERAL:
if(consttype(l) == CTINT) {
t->bound = mpgetfix(l->val.u.xval);
if(t->bound < 0) {
yyerror("array bound must be non-negative");
goto error;
}
}
break;
case OTYPE:
if(l->type == T)
goto error;
if(l->type->etype != TDDD) {
yyerror("invalid array bound %T", l->type);
goto error;
}
t->bound = -100;
break;
}
}
typecheck(&r, Etype);
if(r->type == T)
goto error;
t->type = r->type;
n->op = OTYPE;
n->type = t;
n->left = N;
n->right = N;
checkwidth(t);
break;
case OTMAP:
ok |= Etype;
l = typecheck(&n->left, Etype);
r = typecheck(&n->right, Etype);
if(l->type == T || r->type == T)
goto error;
n->op = OTYPE;
n->type = maptype(l->type, r->type);
n->left = N;
n->right = N;
break;
case OTCHAN:
ok |= Etype;
l = typecheck(&n->left, Etype);
if(l->type == T)
goto error;
t = typ(TCHAN);
t->type = l->type;
t->chan = n->etype;
n->op = OTYPE;
n->type = t;
n->left = N;
n->etype = 0;
break;
case OTSTRUCT:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TSTRUCT);
if(n->type == T)
goto error;
n->list = nil;
break;
case OTINTER:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TINTER);
if(n->type == T)
goto error;
n->type = sortinter(n->type);
break;
case OTFUNC:
ok |= Etype;
n->op = OTYPE;
n->type = functype(n->left, n->list, n->rlist);
if(n->type == T)
goto error;
break;
/*
* exprs
*/
case OADD:
case OAND:
case OANDAND:
case OANDNOT:
case ODIV:
case OEQ:
case OGE:
case OGT:
case OLE:
case OLT:
case OMOD:
case OMUL:
case ONE:
case OOR:
case OOROR:
case OSUB:
case OXOR:
ok |= Erv;
l = typecheck(&n->left, Erv | Eideal);
r = typecheck(&n->right, Erv | Eideal);
if(l->type == T || r->type == T)
goto error;
et1 = l->type->etype;
et2 = r->type->etype;
if(et1 == TIDEAL || et1 == TNIL || et2 == TIDEAL || et2 == TNIL)
if(et1 != TIDEAL && et1 != TNIL || et2 != TIDEAL && et2 != TNIL) {
// ideal mixed with non-ideal
defaultlit2(&l, &r);
n->left = l;
n->right = r;
}
t = l->type;
if(t->etype == TIDEAL)
t = r->type;
et = t->etype;
if(et == TIDEAL)
et = TINT;
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
badbinary:
yyerror("invalid operation: %#N", n);
goto error;
}
if(!okfor[n->op][et])
goto badbinary;
// okfor allows any array == array;
// restrict to slice == nil and nil == slice.
if(l->type->etype == TARRAY && !isslice(l->type))
goto badbinary;
if(r->type->etype == TARRAY && !isslice(r->type))
goto badbinary;
if(isslice(l->type) && !isnil(l) && !isnil(r))
goto badbinary;
evconst(n);
goto ret;
case OCOM:
case OMINUS:
case ONOT:
case OPLUS:
ok |= Erv;
l = typecheck(&n->left, Erv | Eideal);
walkexpr(&n->left, Erv | Eideal, &n->ninit); // TODO: remove
if((t = l->type) == T)
goto error;
if(!okfor[n->op][t->etype]) {
yyerror("invalid operation: %#O %T", n->op, t);
goto error;
}
n->type = t;
goto ret;
/*
* type or expr
*/
case OIND:
typecheck(&n->left, top | Etype);
if(n->left->op == OTYPE) {
ok |= Etype;
n->op = OTYPE;
n->type = ptrto(n->left->type);
n->left = N;
goto ret;
}
// TODO: OIND expression type checking
goto ret;
}
ret:
evconst(n);
if(n->op == OTYPE && !(top & Etype)) {
yyerror("type %T is not an expression", n->type);
goto error;
}
if((top & (Elv|Erv|Etype)) == Etype && n->op != OTYPE) {
yyerror("%O is not a type", n->op);
goto error;
}
/* TODO
if(n->type == T)
fatal("typecheck nil type");
*/
goto out;
error:
n->type = T;
out:
lineno = lno;
n->typecheck = 1;
*np = n;
return n;
}
/* /*
* walk the whole tree of the body of an * walk the whole tree of the body of an
* expression or simple statement. * expression or simple statement.
@ -351,20 +651,13 @@ walkexpr(Node **np, int top, NodeList **init)
if(debug['w'] > 1 && top == Etop) if(debug['w'] > 1 && top == Etop)
dump("walk-before", n); dump("walk-before", n);
if(n->typecheck != 1)
typecheck(&n, top | typeok);
reswitch: reswitch:
t = T; t = T;
et = Txxx; et = Txxx;
switch(n->op) {
case ONAME:
case OTYPE:
case OLITERAL:
case ONONAME:
if(n->sym != S && n->type == T)
walkdef(n);
break;
}
switch(n->op) { switch(n->op) {
default: default:
dump("walk", n); dump("walk", n);
@ -374,80 +667,6 @@ reswitch:
case OTYPE: case OTYPE:
goto ret; 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;
checkwidth(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->list, TSTRUCT);
goto ret;
case OTINTER:
n->op = OTYPE;
n->type = dostruct(n->list, TINTER);
n->type = sortinter(n->type);
goto ret;
case OTFUNC:
n->op = OTYPE;
n->type = functype(n->left, n->list, n->rlist);
goto ret;
case OKEY: case OKEY:
walkexpr(&n->left, top | typeok, init); walkexpr(&n->left, top | typeok, init);
walkexpr(&n->right, top | typeok, init); walkexpr(&n->right, top | typeok, init);
@ -483,7 +702,7 @@ reswitch:
goto ret; goto ret;
case OLITERAL: case OLITERAL:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
n->addable = 1; n->addable = 1;
goto ret; goto ret;
@ -550,7 +769,7 @@ reswitch:
n->op = OCALLINTER; n->op = OCALLINTER;
if(n->left->op == OTYPE) { if(n->left->op == OTYPE) {
n->op = OCONV; n->op = OCONV;
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
// turn CALL(type, arg) into CONV(arg) w/ type. // turn CALL(type, arg) into CONV(arg) w/ type.
n->type = n->left->type; n->type = n->left->type;
@ -777,7 +996,7 @@ reswitch:
walkdottype(n, init); walkdottype(n, init);
// fall through // fall through
case OCONV: case OCONV:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
walkconv(&n, init); walkconv(&n, init);
goto ret; goto ret;
@ -817,9 +1036,8 @@ reswitch:
goto ret; goto ret;
case ONOT: case ONOT:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
evconst(n);
if(n->op == OLITERAL) if(n->op == OLITERAL)
goto ret; goto ret;
walkexpr(&n->left, Erv, init); walkexpr(&n->left, Erv, init);
@ -841,7 +1059,7 @@ reswitch:
case OLSH: case OLSH:
case ORSH: case ORSH:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
walkexpr(&n->left, Erv, init); walkexpr(&n->left, Erv, init);
@ -880,7 +1098,7 @@ reswitch:
case OSUB: case OSUB:
case OMUL: case OMUL:
case ODIV: case ODIV:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
walkexpr(&n->left, Erv, init); walkexpr(&n->left, Erv, init);
@ -935,18 +1153,17 @@ reswitch:
case OMINUS: case OMINUS:
case OPLUS: case OPLUS:
case OCOM: case OCOM:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
walkexpr(&n->left, Erv, init); walkexpr(&n->left, Erv, init);
if(n->left == N) if(n->left == N)
goto ret; goto ret;
evconst(n);
if(n->op == OLITERAL) if(n->op == OLITERAL)
goto ret; goto ret;
break; break;
case OLEN: case OLEN:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
if(n->left == N) { if(n->left == N) {
if(n->list == nil) { if(n->list == nil) {
@ -981,7 +1198,7 @@ reswitch:
goto ret; goto ret;
case OCAP: case OCAP:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
if(n->left == N) { if(n->left == N) {
if(n->list == nil) { if(n->list == nil) {
@ -1033,7 +1250,7 @@ reswitch:
case TSTRING: case TSTRING:
// right side must be an int // right side must be an int
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
defaultlit(&n->right, types[TINT]); defaultlit(&n->right, types[TINT]);
if(n->right->type == T) if(n->right->type == T)
@ -1107,7 +1324,8 @@ reswitch:
goto nottop; goto nottop;
walkexpr(&n->left, top, init); walkexpr(&n->left, top, init);
walkexpr(&n->right, Erv, init); walkexpr(&n->right->left, Erv, init);
walkexpr(&n->right->right, Erv, init);
if(n->left == N || n->right == N) if(n->left == N || n->right == N)
goto ret; goto ret;
defaultlit(&n->left, T); defaultlit(&n->left, T);
@ -1139,7 +1357,7 @@ reswitch:
goto ret; goto ret;
case OADDR: case OADDR:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
defaultlit(&n->left, T); defaultlit(&n->left, T);
if(n->left->op == OCOMPOS) { if(n->left->op == OCOMPOS) {
@ -1225,13 +1443,13 @@ reswitch:
goto ret; goto ret;
case OMAKE: case OMAKE:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
n = makecompat(n); n = makecompat(n);
goto ret; goto ret;
case ONEW: case ONEW:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
if(n->list == nil) { if(n->list == nil) {
yyerror("missing argument to new"); yyerror("missing argument to new");
@ -1295,7 +1513,7 @@ reswitch:
if(n->left->type == T) if(n->left->type == T)
goto ret; goto ret;
et = n->left->type->etype; et = n->left->type->etype;
if(!okforadd[et] && et != TSTRING) if(!okforarith[et] && et != TSTRING)
goto badt; goto badt;
t = types[TBOOL]; t = types[TBOOL];
break; break;
@ -1308,7 +1526,7 @@ reswitch:
if(n->left->type == T) if(n->left->type == T)
goto ret; goto ret;
et = n->left->type->etype; et = n->left->type->etype;
if(!okforadd[et]) if(!okforarith[et])
goto badt; goto badt;
break; break;
@ -1316,7 +1534,7 @@ reswitch:
if(n->left->type == T) if(n->left->type == T)
goto ret; goto ret;
et = n->left->type->etype; et = n->left->type->etype;
if(!okforadd[et]) if(!okforarith[et])
goto badt; goto badt;
if(isfloat[et]) { if(isfloat[et]) {
// TODO(rsc): Can do this more efficiently, // TODO(rsc): Can do this more efficiently,
@ -1394,7 +1612,7 @@ nottop:
if(n->diag) if(n->diag)
goto ret; goto ret;
n->diag = 1; n->diag = 1;
switch(top | typeok) { switch((top | typeok) & ~Eideal) {
default: default:
yyerror("didn't expect %O here [top=%d]", n->op, top); yyerror("didn't expect %O here [top=%d]", n->op, top);
break; break;
@ -2846,7 +3064,7 @@ mapop(Node *n, int top, NodeList **init)
if(cl > 1) if(cl > 1)
yyerror("too many arguments to make map"); yyerror("too many arguments to make map");
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
// newmap(keysize int, valsize int, // newmap(keysize int, valsize int,
@ -2884,7 +3102,7 @@ mapop(Node *n, int top, NodeList **init)
break; break;
case OINDEX: case OINDEX:
if(top != Erv) if(!(top & Erv))
goto nottop; goto nottop;
// mapaccess1(hmap map[any]any, key any) (val any); // mapaccess1(hmap map[any]any, key any) (val any);

View File

@ -133,6 +133,7 @@ fixedbugs/bug039.go:6: variable x redeclared in this block
previous declaration at fixedbugs/bug039.go:5 previous declaration at fixedbugs/bug039.go:5
=========== fixedbugs/bug049.go =========== fixedbugs/bug049.go
fixedbugs/bug049.go:6: invalid operation: s == nil
fixedbugs/bug049.go:6: illegal types for operand: EQ fixedbugs/bug049.go:6: illegal types for operand: EQ
string string
nil nil