tempfree(&n1);
return;
}
-
+
// 64-bit ops are hard on 32-bit machine.
if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) {
switch(n->op) {
}
}
- if(isfloat[n->type->etype] && isfloat[nl->type->etype])
+ if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
goto flt;
switch(n->op) {
// unary
cgen(nl, &f0);
- if(n->op != OCONV)
+ if(n->op != OCONV && n->op != OPLUS)
gins(foptoas(n->op, n->type, 0), &f0, &f0);
gmove(&f0, res);
return;
Node *n, *nn;
n = *np;
- if(n == N || t == T || n->type == T || isideal(t) || eqtype(t, n->type))
+ if(n == N || t == T || n->type == T || isideal(t) || n->type == t)
return;
if(!explicit && !isideal(n->type))
return;
s = mal(sizeof(*s)+l);
s->len = l;
runetochar((char*)s->s, &rune);
+ memset(&v, 0, sizeof v);
v.ctype = CTSTR;
v.u.sval = s;
break;
case CTFLT:
yyerror("no float -> string");
+
+ case CTNIL:
+ memset(&v, 0, sizeof v);
+ v.ctype = CTSTR;
+ v.u.sval = mal(sizeof *s);
+ break;
}
return v;
}
}
return;
+ case TUP(OCONV, CTNIL):
+ case TUP(OARRAYBYTESTR, CTNIL):
+ if(n->type->etype == TSTRING) {
+ v = tostr(v);
+ nl->type = n->type;
+ break;
+ }
+ // fall through
case TUP(OCONV, CTINT):
case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR):
- case TUP(OCONV, CTNIL):
- case TUP(OARRAYBYTESTR, CTNIL):
convlit1(&nl, n->type, 1);
break;
default:
fatal("nodlit ctype %d", v.ctype);
case CTSTR:
- n->type = types[TSTRING];
+ n->type = idealstring;
break;
case CTBOOL:
- n->type = types[TBOOL];
+ n->type = idealbool;
break;
case CTINT:
case CTFLT:
}
defaultlit(&n->left, t);
defaultlit(&n->right, t);
- n->type = n->left->type;
+ if(n->type == idealbool || n->type == idealstring)
+ n->type = types[n->type->etype];
+ else
+ n->type = n->left->type;
return;
}
}
yyerror("defaultlit: unknown literal: %#N", n);
break;
+ case CTBOOL:
+ n->type = types[TBOOL];
+ break;
case CTINT:
n->type = types[TINT];
if(t != T) {
r = *rp;
if(l->type == T || r->type == T)
return;
- if(l->type->etype != TIDEAL && l->type->etype != TNIL) {
+ if(!isideal(l->type)) {
convlit(rp, l->type);
return;
}
- if(r->type->etype != TIDEAL && r->type->etype != TNIL) {
+ if(!isideal(r->type)) {
convlit(lp, r->type);
return;
}
Bprint(bout, "\t");
Bprint(bout, "const %lS", s);
- if(t != T && t->etype != TIDEAL)
+ if(t != T && !isideal(t))
Bprint(bout, " %#T", t);
Bprint(bout, " = ");
switch(nr->op) {
case ONAME:
- gused(nr);
+ if(!(nr->class & PHEAP))
+ gused(nr);
break;
// unary
EXTERN Type* types[NTYPE];
EXTERN Type* idealstring;
+EXTERN Type* idealbool;
EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE];
s->def->iota = 1;
s->def->sym = s;
- s = pkglookup("true", "/builtin/");
- s->def = nodbool(1);
- s->def->sym = lookup("true");
-
- s = pkglookup("false", "/builtin/");
- s->def = nodbool(0);
- s->def->sym = lookup("false");
-
-
// logically, the type of a string literal.
// types[TSTRING] is the named type string
// (the type of x in var x string or var x = "hello").
// (the type of x in const x = "hello").
// TODO(rsc): this may need some more thought.
idealstring = typ(TSTRING);
+ idealbool = typ(TBOOL);
+
+ s = pkglookup("true", "/builtin/");
+ s->def = nodbool(1);
+ s->def->sym = lookup("true");
+ s->def->type = idealbool;
+
+ s = pkglookup("false", "/builtin/");
+ s->def = nodbool(0);
+ s->def->sym = lookup("false");
+ s->def->type = idealbool;
s = lookup("_");
s->block = -100;
Sym *s;
Node *n;
- if(isptr[t->etype] && t->type == T)
+ if((isptr[t->etype] && t->type == T) || isideal(t))
fatal("typename %T", t);
s = typesym(t);
if(s->def == N) {
Type *t1;
Sym *tsym;
- if(t->etype == TNIL || t->etype == TIDEAL || t == idealstring)
- fatal("dtypesym ideal %T", t);
+ if(isideal(t))
+ fatal("dtypesym %T", t);
s = typesym(t);
if(s->flags & SymSiggen)
c = nodintconst(0);
c->val.ctype = CTBOOL;
c->val.u.bval = b;
- c->type = types[TBOOL];
+ c->type = idealbool;
return c;
}
return fmtprint(fp, "%S", s);
}
- if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil)
+ if(t->etype < nelem(basicnames) && basicnames[t->etype] != nil) {
+ if(isideal(t) && t->etype != TIDEAL && t->etype != TNIL)
+ fmtprint(fp, "ideal ");
return fmtprint(fp, "%s", basicnames[t->etype]);
+ }
switch(t->etype) {
case TPTR32:
{
if(t == T)
return 0;
- if(t == idealstring)
- return 1;
- return t->etype == TNIL || t->etype == TIDEAL;
+ return t == idealstring || t == idealbool || t->etype == TNIL || t->etype == TIDEAL;
}
/*
if(ll->n->op == OTYPE)
yyerror("type %T is not an expression", ll->n->type);
else if(ll->n->type != T && !eqtype(ll->n->type, t))
- yyerror("case %+N in switch of %+N %#O", ll->n, n->ntest, ll->n->op);
+ yyerror("case %+N in %T switch", ll->n, t);
break;
case Etype: // type switch
if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL))
goto badbinary;
t = l->type;
if(iscmp[n->op]) {
- t = types[TBOOL];
+ t = idealbool;
evconst(n);
if(n->op != OLITERAL) {
defaultlit2(&l, &r, 1);
goto error;
// TODO: more aggressive
n->etype = 0;
- if(top & Erv)
+ n->type = T;
+ if(top & Erv) {
n->op = OSENDNB;
- n->type = types[TBOOL];
+ n->type = idealbool;
+ }
goto ret;
case OSLICE:
goto error;
}
if(n->op == OCLOSED) {
- n->type = types[TBOOL];
+ n->type = idealbool;
ok |= Erv;
} else
ok |= Etop;
return 1;
}
+/*
+ * check implicit or explicit conversion from node type nt to type t.
+ */
int
checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
{
*op = OCONV;
*et = 0;
+
+
// preexisting error
if(t == T || t->etype == TFORW)
return 0;
// accept anything involving interfaces and let ifacecvt
// generate a good message. some messages have to be
// delayed anyway.
+ // TODO(rsc): now that everything is delayed for whole-package
+ // compilation, the messages could be generated right here.
if(isnilinter(t) || isnilinter(nt) || isinter(t) || isinter(nt)) {
*et = ifaceas1(t, nt, 0);
*op = OCONVIFACE;
return n;
if(n->op == OLITERAL)
- if(explicit || n->type->etype == TIDEAL || n->type == idealstring || n->type->etype == TNIL)
+ if(explicit || isideal(n->type))
if(cvttype(t, n->type)) {
// can convert literal in place
// TODO(rsc) is this needed?
return n;
}
+ if(op == OCONVIFACE)
+ defaultlit(&n, T);
+
if(nconv == N)
nconv = nod(OCONV, n, N);
nconv->op = op;
n->op = OAS2MAPW;
n->rlist->n = typecheckconv(nil, r, l->type->down, 0);
r = n->rlist->next->n;
- n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0);
+ n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 1);
goto out;
}
if(l->defn == n)
l->type = r->type;
l = n->list->next->n;
- if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0)
+ if(l->type != T && checkconv(idealbool, l->type, 0, &op, &et) < 0)
yyerror("cannot assign bool value to %+N", l);
if(l->defn == n && l->ntype == N)
l->type = types[TBOOL];
if(n->etype == OANDNOT) {
n->etype = OAND;
n->right = nod(OCOM, n->right, N);
- n->right->type = n->right->left->type;
+ typecheck(&n->right, Erv);
goto ret;
}
walkexpr(&n->right, init);
n->op = OAND;
n->right = nod(OCOM, n->right, N);
- n->right->type = n->right->left->type;
+ typecheck(&n->right, Erv);
goto ret;
case ODIV: