make 6g constants behave as ken proposes. (i hope.)

various bug fixes and tests involving constants.

test/const1.go is the major new test case.

R=ken
OCL=26216
CL=26224
This commit is contained in:
Russ Cox 2009-03-12 19:04:38 -07:00
parent 9b5d82327b
commit 8f194bf5ff
25 changed files with 987 additions and 729 deletions

View file

@ -146,11 +146,11 @@ cgen(Node *n, Node *res)
case ONOT:
p1 = gbranch(AJMP, T);
p2 = pc;
gmove(booltrue, res);
gmove(nodbool(1), res);
p3 = gbranch(AJMP, T);
patch(p1, pc);
bgen(n, 1, p2);
gmove(boolfalse, res);
gmove(nodbool(0), res);
patch(p3, pc);
goto ret;
@ -408,7 +408,7 @@ agen(Node *n, Node *res)
if(nr->addable)
goto irad;
if(nl->addable) {
if(whatis(nr) != Wlitint) {
if(!isconst(nr, CTINT)) {
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
}
@ -423,7 +423,7 @@ agen(Node *n, Node *res)
irad:
regalloc(&n3, types[tptr], res);
agen(nl, &n3);
if(whatis(nr) != Wlitint) {
if(!isconst(nr, CTINT)) {
regalloc(&n1, nr->type, N);
cgen(nr, &n1);
}
@ -438,7 +438,7 @@ agen(Node *n, Node *res)
fatal("index is zero width");
// constant index
if(whatis(nr) == Wlitint) {
if(isconst(nr, CTINT)) {
v = mpgetfix(nr->val.u.xval);
if(isslice(nl->type)) {
@ -618,7 +618,7 @@ bgen(Node *n, int true, Prog *to)
}
if(n == N)
n = booltrue;
n = nodbool(1);
nl = n->left;
nr = n->right;

View file

@ -345,15 +345,6 @@ nodconst(Node *n, Type *t, vlong v)
case TFLOAT64:
case TFLOAT80:
fatal("nodconst: bad type %T", t);
case TPTR32:
case TPTR64:
case TUINT8:
case TUINT16:
case TUINT32:
case TUINT64:
n->val.ctype = CTUINT;
break;
}
}
@ -1102,8 +1093,6 @@ naddr(Node *n, Addr *a)
a->dval = mpgetflt(n->val.u.fval);
break;
case CTINT:
case CTSINT:
case CTUINT:
a->sym = S;
a->type = D_CONST;
a->offset = mpgetfix(n->val.u.xval);
@ -2057,7 +2046,7 @@ oindex:
}
w = n->type->width;
if(whatis(r) == Wlitint)
if(isconst(r, CTINT))
goto oindex_const;
switch(w) {

View file

@ -5,6 +5,16 @@
#include "go.h"
#define TUP(x,y) (((x)<<16)|(y))
static Val toflt(Val);
static Val toint(Val);
static Val tostr(Val);
static void overflow(Val, Type*);
static Val copyval(Val);
/*
* truncate float literal fv to 32-bit or 64-bit precision
* according to type.
*/
void
truncfltlit(Mpflt *fv, Type *t)
{
@ -33,12 +43,28 @@ truncfltlit(Mpflt *fv, Type *t)
}
}
/*
* convert n, if literal, to type t.
* implicit conversion.
*/
void
convlit1(Node *n, Type *t, int conv)
convlit(Node *n, Type *t)
{
int et, wt;
convlit1(n, t, 0);
}
if(n == N || t == T)
/*
* convert n, if literal, to type t.
*/
void
convlit1(Node *n, Type *t, int explicit)
{
int et, ct;
if(n == N || t == T || n->type == T)
return;
et = t->etype;
if(et == TIDEAL || et == TNIL)
return;
switch(n->op) {
@ -53,17 +79,37 @@ convlit1(Node *n, Type *t, int conv)
return;
}
et = t->etype;
wt = whatis(n);
// avoided repeated calculations, errors
if(eqtype(n->type, t, 0)) {
n->type = t;
return;
}
switch(wt) {
ct = consttype(n);
if(ct < 0)
goto bad;
if(et == TINTER) {
if(ct == CTNIL) {
n->type = t;
return;
}
defaultlit(n, T);
return;
}
// if already has non-ideal type, cannot change implicitly
if(n->type->etype != TIDEAL && n->type->etype != TNIL && !explicit)
goto bad;
switch(ct) {
default:
goto bad1;
goto bad;
case Wlitnil:
case CTNIL:
switch(et) {
default:
goto bad1;
goto bad;
case TPTR32:
case TPTR64:
@ -76,450 +122,577 @@ convlit1(Node *n, Type *t, int conv)
}
break;
case Wlitstr:
if(isnilinter(t)) {
defaultlit(n);
return;
}
if(et == TSTRING)
break;
goto bad1;
case CTSTR:
case CTBOOL:
if(et != n->type->etype)
goto bad;
break;
case Wlitbool:
if(isnilinter(t)) {
defaultlit(n);
return;
}
if(et == TBOOL)
break;
goto bad1;
case Wlitint:
if(isnilinter(t)) {
defaultlit(n);
return;
}
case CTINT:
case CTFLT:
ct = n->val.ctype;
if(isint[et]) {
// int to int
if(mpcmpfixfix(n->val.u.xval, minintval[et]) < 0)
goto bad2;
if(mpcmpfixfix(n->val.u.xval, maxintval[et]) > 0)
goto bad2;
break;
}
if(isfloat[et]) {
// int to float
Mpint *xv;
Mpflt *fv;
xv = n->val.u.xval;
if(mpcmpfixflt(xv, minfltval[et]) < 0)
goto bad2;
if(mpcmpfixflt(xv, maxfltval[et]) > 0)
goto bad2;
fv = mal(sizeof(*n->val.u.fval));
n->val.u.fval = fv;
mpmovefixflt(fv, xv);
n->val.ctype = CTFLT;
truncfltlit(fv, t);
break;
}
if(!conv)
goto bad1;
// only done as string(CONST)
if(et == TSTRING) {
Rune rune;
int l;
String *s;
rune = mpgetfix(n->val.u.xval);
l = runelen(rune);
s = mal(sizeof(*s)+l);
s->len = l;
runetochar((char*)(s->s), &rune);
n->val.u.sval = s;
n->val.ctype = CTSTR;
break;
}
goto bad1;
case Wlitfloat:
if(isnilinter(t)) {
defaultlit(n);
return;
}
if(isint[et]) {
// float to int
Mpflt *fv;
fv = n->val.u.fval;
if(mpcmpfltfix(fv, minintval[et]) < 0)
goto bad2;
if(mpcmpfltfix(fv, maxintval[et]) > 0)
goto bad2;
if(floor(mpgetflt(fv)) != mpgetflt(fv))
goto bad3;
n->val.u.xval = mal(sizeof(*n->val.u.xval));
mpmovefltfix(n->val.u.xval, fv);
n->val.ctype = CTINT;
break;
}
if(isfloat[et]) {
// float to float
Mpflt *fv;
fv = n->val.u.fval;
if(mpcmpfltflt(fv, minfltval[et]) < 0)
goto bad2;
if(mpcmpfltflt(fv, maxfltval[et]) > 0)
goto bad2;
truncfltlit(fv, t);
break;
}
goto bad1;
if(ct == CTFLT)
n->val = toint(n->val);
else if(ct != CTINT)
goto bad;
overflow(n->val, t);
} else if(isfloat[et]) {
if(ct == CTINT)
n->val = toflt(n->val);
else if(ct != CTFLT)
goto bad;
overflow(n->val, t);
truncfltlit(n->val.u.fval, t);
} else if(et == TSTRING && ct == CTINT && explicit)
n->val = tostr(n->val);
else
goto bad;
}
n->type = t;
return;
bad1:
yyerror("illegal conversion of %W to %T", wt, t);
return;
bad2:
yyerror("overflow converting constant to %T", t);
return;
bad3:
yyerror("cannot convert non-integer constant to %T", t);
bad:
if(n->type->etype == TIDEAL)
defaultlit(n, T);
yyerror("cannot convert %T constant to %T", n->type, t);
n->type = T;
n->diag = 1;
return;
}
void
convlit(Node *n, Type *t)
static Val
copyval(Val v)
{
convlit1(n, t, 0);
Mpint *i;
Mpflt *f;
switch(v.ctype) {
case CTINT:
i = mal(sizeof(*i));
mpmovefixfix(i, v.u.xval);
v.u.xval = i;
break;
case CTFLT:
f = mal(sizeof(*f));
mpmovefltflt(f, v.u.fval);
v.u.fval = f;
break;
}
return v;
}
static Val
toflt(Val v)
{
Mpflt *f;
if(v.ctype == CTINT) {
f = mal(sizeof(*f));
mpmovefixflt(f, v.u.xval);
v.ctype = CTFLT;
v.u.fval = f;
}
return v;
}
static Val
toint(Val v)
{
Mpint *i;
if(v.ctype == CTFLT) {
i = mal(sizeof(*i));
if(mpmovefltfix(i, v.u.fval) < 0)
yyerror("constant %#F truncated to integer", v.u.fval);
v.ctype = CTINT;
v.u.xval = i;
}
return v;
}
static void
overflow(Val v, Type *t)
{
// v has already been converted
// to appropriate form for t.
if(t == T || t->etype == TIDEAL)
return;
switch(v.ctype) {
case CTINT:
if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0
|| mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
yyerror("constant %B overflows %T", v.u.xval, t);
break;
case CTFLT:
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) < 0
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) > 0)
yyerror("constant %#F overflows %T", v.u.fval, t);
break;
}
}
static Val
tostr(Val v)
{
Rune rune;
int l;
String *s;
switch(v.ctype) {
case CTINT:
if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0
|| mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
yyerror("overflow in int -> string");
rune = mpgetfix(v.u.xval);
l = runelen(rune);
s = mal(sizeof(*s)+l);
s->len = l;
runetochar((char*)s->s, &rune);
v.ctype = CTSTR;
v.u.sval = s;
break;
case CTFLT:
yyerror("no float -> string");
}
return v;
}
int
consttype(Node *n)
{
if(n == N || n->op != OLITERAL)
return -1;
return n->val.ctype;
}
int
isconst(Node *n, int ct)
{
return consttype(n) == ct;
}
/*
* if n is constant, rewrite as OLITERAL node.
*/
void
evconst(Node *n)
{
Node *nl, *nr;
int32 len;
String *str;
int wl, wr;
Mpint *xval;
Mpflt *fval;
xval = nil;
fval = nil;
int wl, wr, lno;
Val v;
nl = n->left;
if(nl == N)
if(nl == N || nl->type == T)
return;
wl = whatis(nl);
switch(wl) {
default:
if(consttype(nl) < 0)
return;
case Wlitint:
case Wlitfloat:
case Wlitbool:
case Wlitstr:
case Wlitnil:
break;
}
wl = nl->type->etype;
if(isint[wl] || isfloat[wl])
wl = TIDEAL;
nr = n->right;
if(nr == N)
goto unary;
wr = whatis(nr);
switch(wr) {
default:
if(nr->type == T)
return;
if(consttype(nr) < 0)
return;
wr = nr->type->etype;
if(isint[wr] || isfloat[wr])
wr = TIDEAL;
case Wlitint:
case Wlitfloat:
case Wlitbool:
case Wlitstr:
case Wlitnil:
// check for compatible general types (numeric, string, etc)
if(wl != wr)
goto illegal;
// check for compatible types.
switch(n->op) {
default:
// ideal const mixes with anything but otherwise must match.
if(nl->type->etype != TIDEAL)
defaultlit(nr, nl->type);
if(nr->type->etype != TIDEAL)
defaultlit(nl, nr->type);
if(nl->type->etype != nr->type->etype)
goto illegal;
break;
case OLSH:
case ORSH:
// right must be unsigned.
// left can be ideal.
defaultlit(nr, types[TUINT]);
break;
}
if(wl != wr) {
if(wl == Wlitfloat && wr == Wlitint) {
xval = nr->val.u.xval;
nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
mpmovefixflt(nr->val.u.fval, xval);
nr->val.ctype = CTFLT;
wr = whatis(nr);
} else
if(wl == Wlitint && wr == Wlitfloat) {
xval = nl->val.u.xval;
nl->val.u.fval = mal(sizeof(*nl->val.u.fval));
mpmovefixflt(nl->val.u.fval, xval);
nl->val.ctype = CTFLT;
wl = whatis(nl);
} else {
yyerror("illegal combination of literals %O %W, %W", n->op, wl, wr);
return;
// copy numeric value to avoid modifying
// n->left, in case someone still refers to it (e.g. iota).
v = nl->val;
if(wl == TIDEAL)
v = copyval(v);
// since wl == wr,
// the only way v.ctype != nr->val.ctype
// is when one is CTINT and the other CTFLT.
// make both CTFLT.
if(v.ctype != nr->val.ctype) {
v = toflt(v);
nr->val = toflt(nr->val);
}
// run op
switch(TUP(n->op, v.ctype)) {
default:
illegal:
yyerror("illegal constant expression %T %O %T",
nl->type, n->op, nr->type);
n->diag = 1;
return;
case TUP(OADD, CTINT):
mpaddfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OSUB, CTINT):
mpsubfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OMUL, CTINT):
mpmulfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(ODIV, CTINT):
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
yyerror("division by zero");
mpmovecfix(v.u.xval, 1);
break;
}
}
// dance to not modify left side
// this is because iota will reuse it
if(wl == Wlitint) {
xval = mal(sizeof(*xval));
mpmovefixfix(xval, nl->val.u.xval);
} else
if(wl == Wlitfloat) {
fval = mal(sizeof(*fval));
mpmovefltflt(fval, nl->val.u.fval);
}
switch(TUP(n->op, wl)) {
default:
yyerror("illegal literal %O %W", n->op, wl);
return;
case TUP(OADD, Wlitint):
mpaddfixfix(xval, nr->val.u.xval);
mpdivfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OSUB, Wlitint):
mpsubfixfix(xval, nr->val.u.xval);
break;
case TUP(OMUL, Wlitint):
mpmulfixfix(xval, nr->val.u.xval);
break;
case TUP(ODIV, Wlitint):
mpdivfixfix(xval, nr->val.u.xval);
break;
case TUP(OMOD, Wlitint):
mpmodfixfix(xval, nr->val.u.xval);
case TUP(OMOD, CTINT):
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
yyerror("division by zero");
mpmovecfix(v.u.xval, 1);
break;
}
mpmodfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OLSH, Wlitint):
mplshfixfix(xval, nr->val.u.xval);
case TUP(OLSH, CTINT):
mplshfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(ORSH, Wlitint):
mprshfixfix(xval, nr->val.u.xval);
case TUP(ORSH, CTINT):
mprshfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OOR, Wlitint):
mporfixfix(xval, nr->val.u.xval);
case TUP(OOR, CTINT):
mporfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OAND, Wlitint):
mpandfixfix(xval, nr->val.u.xval);
case TUP(OAND, CTINT):
mpandfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OANDNOT, Wlitint):
mpandnotfixfix(xval, nr->val.u.xval);
case TUP(OANDNOT, CTINT):
mpandnotfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OXOR, Wlitint):
mpxorfixfix(xval, nr->val.u.xval);
case TUP(OXOR, CTINT):
mpxorfixfix(v.u.xval, nr->val.u.xval);
break;
case TUP(OADD, CTFLT):
mpaddfltflt(v.u.fval, nr->val.u.fval);
break;
case TUP(OSUB, CTFLT):
mpsubfltflt(v.u.fval, nr->val.u.fval);
break;
case TUP(OMUL, CTFLT):
mpmulfltflt(v.u.fval, nr->val.u.fval);
break;
case TUP(ODIV, CTFLT):
if(mpcmpfltc(nr->val.u.fval, 0) == 0) {
yyerror("division by zero");
mpmovecflt(v.u.fval, 1.0);
break;
}
mpdivfltflt(v.u.fval, nr->val.u.fval);
break;
case TUP(OADD, Wlitfloat):
mpaddfltflt(fval, nr->val.u.fval);
break;
case TUP(OSUB, Wlitfloat):
mpsubfltflt(fval, nr->val.u.fval);
break;
case TUP(OMUL, Wlitfloat):
mpmulfltflt(fval, nr->val.u.fval);
break;
case TUP(ODIV, Wlitfloat):
mpdivfltflt(fval, nr->val.u.fval);
break;
case TUP(OEQ, Wlitnil):
case TUP(OEQ, CTNIL):
goto settrue;
case TUP(ONE, Wlitnil):
case TUP(ONE, CTNIL):
goto setfalse;
case TUP(OEQ, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) == 0)
case TUP(OEQ, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) == 0)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) != 0)
case TUP(ONE, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) != 0)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) < 0)
case TUP(OLT, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) < 0)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) <= 0)
case TUP(OLE, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) <= 0)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) >= 0)
case TUP(OGE, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) >= 0)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitint):
if(mpcmpfixfix(xval, nr->val.u.xval) > 0)
case TUP(OGT, CTINT):
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) > 0)
goto settrue;
goto setfalse;
case TUP(OEQ, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) == 0)
case TUP(OEQ, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) == 0)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) != 0)
case TUP(ONE, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) != 0)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) < 0)
case TUP(OLT, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) < 0)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) <= 0)
case TUP(OLE, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) <= 0)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) >= 0)
case TUP(OGE, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) >= 0)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitfloat):
if(mpcmpfltflt(fval, nr->val.u.fval) > 0)
case TUP(OGT, CTFLT):
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) > 0)
goto settrue;
goto setfalse;
case TUP(OEQ, Wlitstr):
case TUP(OEQ, CTSTR):
if(cmpslit(nl, nr) == 0)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitstr):
case TUP(ONE, CTSTR):
if(cmpslit(nl, nr) != 0)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitstr):
case TUP(OLT, CTSTR):
if(cmpslit(nl, nr) < 0)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitstr):
case TUP(OLE, CTSTR):
if(cmpslit(nl, nr) <= 0)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitstr):
case TUP(OGE, CTSTR):
if(cmpslit(nl, nr) >= 0l)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitstr):
case TUP(OGT, CTSTR):
if(cmpslit(nl, nr) > 0)
goto settrue;
goto setfalse;
case TUP(OADD, Wlitstr):
len = nl->val.u.sval->len + nr->val.u.sval->len;
case TUP(OADD, CTSTR):
len = v.u.sval->len + nr->val.u.sval->len;
str = mal(sizeof(*str) + len);
str->len = len;
memcpy(str->s, nl->val.u.sval->s, nl->val.u.sval->len);
memcpy(str->s+nl->val.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len);
memcpy(str->s, v.u.sval->s, v.u.sval->len);
memcpy(str->s+v.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len);
str->len = len;
nl->val.u.sval = str;
v.u.sval = str;
break;
case TUP(OOROR, Wlitbool):
if(nl->val.u.bval || nr->val.u.bval)
case TUP(OOROR, CTBOOL):
if(v.u.bval || nr->val.u.bval)
goto settrue;
goto setfalse;
case TUP(OANDAND, Wlitbool):
if(nl->val.u.bval && nr->val.u.bval)
case TUP(OANDAND, CTBOOL):
if(v.u.bval && nr->val.u.bval)
goto settrue;
goto setfalse;
case TUP(OEQ, CTBOOL):
if(v.u.bval == nr->val.u.bval)
goto settrue;
goto setfalse;
case TUP(ONE, CTBOOL):
if(v.u.bval != nr->val.u.bval)
goto settrue;
goto setfalse;
}
goto ret;
settrue:
*n = *booltrue;
return;
setfalse:
*n = *boolfalse;
return;
unary:
if(wl == Wlitint) {
xval = mal(sizeof(*xval));
mpmovefixfix(xval, nl->val.u.xval);
} else
if(wl == Wlitfloat) {
fval = mal(sizeof(*fval));
mpmovefltflt(fval, nl->val.u.fval);
}
// copy numeric value to avoid modifying
// nl, in case someone still refers to it (e.g. iota).
v = nl->val;
if(wl == TIDEAL)
v = copyval(v);
switch(TUP(n->op, wl)) {
switch(TUP(n->op, v.ctype)) {
default:
yyerror("illegal combination of literals %O %d", n->op, wl);
yyerror("illegal constant expression %O %T %d", n->op, nl->type, v.ctype);
return;
case TUP(OPLUS, Wlitint):
case TUP(OPLUS, CTINT):
break;
case TUP(OMINUS, Wlitint):
mpnegfix(xval);
case TUP(OMINUS, CTINT):
mpnegfix(v.u.xval);
break;
case TUP(OCOM, Wlitint):
mpcomfix(xval);
case TUP(OCOM, CTINT):
mpcomfix(v.u.xval);
break;
case TUP(OPLUS, Wlitfloat):
case TUP(OPLUS, CTFLT):
break;
case TUP(OMINUS, Wlitfloat):
mpnegflt(fval);
case TUP(OMINUS, CTFLT):
mpnegflt(v.u.fval);
break;
case TUP(ONOT, Wlitbool):
if(nl->val.u.bval)
case TUP(ONOT, CTBOOL):
if(!v.u.bval)
goto settrue;
goto setfalse;
}
ret:
// rewrite n in place.
*n = *nl;
n->val = v;
// second half of dance
if(wl == Wlitint) {
n->val.u.xval = xval;
} else
if(wl == Wlitfloat) {
n->val.u.fval = fval;
truncfltlit(fval, n->type);
// lose type name if any:
// type T int
// const A T = 1;
// A+0 has type int, not T.
n->type = types[n->type->etype];
// check range.
lno = lineno;
lineno = n->lineno;
overflow(v, n->type);
lineno = lno;
// truncate precision for non-ideal float.
if(v.ctype == CTFLT && n->type->etype != TIDEAL)
truncfltlit(v.u.fval, n->type);
return;
settrue:
*n = *nodbool(1);
return;
setfalse:
*n = *nodbool(0);
return;
}
Node*
nodlit(Val v)
{
Node *n;
n = nod(OLITERAL, N, N);
n->val = v;
switch(v.ctype) {
default:
fatal("nodlit ctype %d", v.ctype);
case CTSTR:
n->type = types[TSTRING];
break;
case CTBOOL:
n->type = types[TBOOL];
break;
case CTINT:
case CTFLT:
n->type = types[TIDEAL];
break;
case CTNIL:
n->type = types[TNIL];
break;
}
return n;
}
void
defaultlit(Node *n)
defaultlit(Node *n, Type *t)
{
int lno;
if(n == N)
return;
if(n->type != T)
return;
if(n->op != OLITERAL)
if(n->type == T || n->type->etype != TIDEAL)
return;
switch(n->op) {
case OLITERAL:
break;
case OLSH:
case ORSH:
defaultlit(n->left, t);
n->type = n->left->type;
return;
}
lno = lineno;
lineno = n->lineno;
switch(n->val.ctype) {
default:
yyerror("defaultlit: unknown literal: %N", n);
break;
case CTINT:
case CTSINT:
case CTUINT:
n->type = types[TINT];
if(t != T) {
if(isint[t->etype])
n->type = t;
else if(isfloat[t->etype]) {
n->type = t;
n->val = toflt(n->val);
}
}
overflow(n->val, n->type);
break;
case CTFLT:
n->type = types[TFLOAT];
break;
case CTBOOL:
n->type = types[TBOOL];
break;
case CTSTR:
n->type = types[TSTRING];
if(t != T) {
if(isfloat[t->etype])
n->type = t;
else if(isint[t->etype]) {
n->type = t;
n->val = toint(n->val);
}
}
overflow(n->val, n->type);
break;
}
lineno = lno;
}
/*
* defaultlit on both nodes simultaneously;
* if they're both ideal going in they better
* get the same type going out.
*/
void
defaultlit2(Node *l, Node *r)
{
if(l->type == T || r->type == T)
return;
if(l->type->etype != TIDEAL && l->type->etype != TNIL) {
convlit(r, l->type);
return;
}
if(r->type->etype != TIDEAL && r->type->etype != TNIL) {
convlit(l, r->type);
return;
}
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
convlit(l, types[TFLOAT]);
convlit(r, types[TFLOAT]);
return;
}
convlit(l, types[TINT]);
convlit(r, types[TINT]);
}
int

View file

@ -23,6 +23,8 @@ dodclvar(Node *n, Type *t)
if(n == N)
return;
if(t != T && (t->etype == TIDEAL || t->etype == TNIL))
fatal("dodclvar %T", t);
for(; n->op == OLIST; n = n->right)
dodclvar(n->left, t);
@ -1284,7 +1286,7 @@ fninit(Node *n)
r = list(r, a);
// (4)
a = nod(OAS, done, booltrue);
a = nod(OAS, done, nodbool(1));
r = list(r, a);
// (5)
@ -1460,7 +1462,7 @@ loop:
a = nod(OAS, v, N);
if(t == T) {
gettype(e, a);
defaultlit(e);
defaultlit(e, T);
dodclvar(v, e->type);
} else
dodclvar(v, t);
@ -1475,7 +1477,7 @@ loop:
/*
* declare constants from grammar
* new_name_list [type] [= expr_list]
* new_name_list [[type] = expr_list]
*/
void
constiter(Node *vv, Type *t, Node *cc)
@ -1483,9 +1485,14 @@ constiter(Node *vv, Type *t, Node *cc)
Iter viter, citer;
Node *v, *c;
if(cc == N)
if(cc == N) {
if(t != T)
yyerror("constdcl cannot have type without expr");
cc = lastconst;
t = lasttype;
}
lastconst = cc;
lasttype = t;
vv = rev(vv);
cc = rev(treecopy(cc));
@ -1499,7 +1506,7 @@ loop:
}
if(v == N || c == N) {
yyerror("shape error in var dcl");
yyerror("shape error in const dcl");
iota += 1;
return;
}
@ -1507,6 +1514,8 @@ loop:
gettype(c, N);
if(t != T)
convlit(c, t);
if(t == T)
lasttype = c->type;
dodclconst(v, c);
v = listnext(&viter);
@ -1587,5 +1596,6 @@ yes:
mpmovecfix(val.u.xval, v);
n = nod(OLITERAL, N, N);
n->val = val;
n->type = types[TINT];
return n;
}

View file

@ -110,7 +110,7 @@ dumpexportconst(Sym *s)
Bprint(bout, "\t");
Bprint(bout, "const %lS", s);
if(t != T)
if(t != T && t->etype != TIDEAL)
Bprint(bout, " %#T", t);
Bprint(bout, " = ");
@ -118,8 +118,6 @@ dumpexportconst(Sym *s)
default:
fatal("dumpexportconst: unknown ctype: %S", s);
case CTINT:
case CTSINT:
case CTUINT:
Bprint(bout, "%B\n", n->val.u.xval);
break;
case CTBOOL:
@ -343,18 +341,14 @@ mypackage(Node *ss)
}
void
importconst(Node *ss, Type *t, Val *v)
importconst(Node *ss, Type *t, Node *n)
{
Node *n;
Sym *s;
if(!exportname(ss->sym->name) && !mypackage(ss))
return;
n = nod(OLITERAL, N, N);
n->val = *v;
n->type = t;
convlit(n, t);
s = importsym(ss, LACONST);
if(s->oconst != N) {
// TODO: check if already the same.
@ -363,7 +357,7 @@ importconst(Node *ss, Type *t, Val *v)
dodclconst(newname(s), n);
if(debug['e'])
if(debug['E'])
print("import const %S\n", s);
}
@ -385,7 +379,7 @@ importvar(Node *ss, Type *t, int ctxt)
checkwidth(t);
addvar(newname(s), t, ctxt);
if(debug['e'])
if(debug['E'])
print("import var %S %lT\n", s, t);
}
@ -410,7 +404,7 @@ importtype(Node *ss, Type *t)
s->otype->sym = s;
checkwidth(s->otype);
if(debug['e'])
if(debug['E'])
print("import type %S %lT\n", s, t);
}

View file

@ -371,6 +371,10 @@ enum
TFORWSTRUCT,
TFORWINTER,
// pseudo-types for literals
TIDEAL,
TNIL,
NTYPE,
};
enum
@ -378,35 +382,12 @@ enum
CTxxx,
CTINT,
CTSINT,
CTUINT,
CTFLT,
CTSTR,
CTBOOL,
CTNIL,
};
enum
{
/* indications for whatis() */
Wnil = 0,
Wtnil,
Wtfloat,
Wtint,
Wtbool,
Wtstr,
Wlitfloat,
Wlitint,
Wlitbool,
Wlitstr,
Wlitnil,
Wtunkn,
};
enum
{
/* types of channel */
@ -518,10 +499,9 @@ EXTERN int dclcontext; // PEXTERN/PAUTO
EXTERN int importflag;
EXTERN int inimportsys;
EXTERN Node* booltrue;
EXTERN Node* boolfalse;
EXTERN uint32 iota;
EXTERN Node* lastconst;
EXTERN Type* lasttype;
EXTERN int32 vargen;
EXTERN int32 exportgen;
EXTERN int32 maxarg;
@ -594,7 +574,7 @@ void mpdivfixfix(Mpint *a, Mpint *b);
void mpmodfixfix(Mpint *a, Mpint *b);
void mpatofix(Mpint *a, char *s);
void mpatoflt(Mpflt *a, char *s);
void mpmovefltfix(Mpint *a, Mpflt *b);
int mpmovefltfix(Mpint *a, Mpflt *b);
void mpmovefixflt(Mpflt *a, Mpint *b);
int Bconv(Fmt*);
@ -611,7 +591,7 @@ void mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d);
void mpdivfract(Mpint *a, Mpint *b);
void mpnegfix(Mpint *a);
void mpandfixfix(Mpint *a, Mpint *b);
void mpnotandfixfix(Mpint *a, Mpint *b);
void mpandnotfixfix(Mpint *a, Mpint *b);
void mplshfixfix(Mpint *a, Mpint *b);
void mporfixfix(Mpint *a, Mpint *b);
void mprshfixfix(Mpint *a, Mpint *b);
@ -651,6 +631,7 @@ void fatal(char*, ...);
void linehist(char*, int32);
int32 setlineno(Node*);
Node* nod(int, Node*, Node*);
Node* nodlit(Val);
Node* list(Node*, Node*);
Type* typ(int);
Dcl* dcl(void);
@ -680,9 +661,10 @@ void argtype(Node*, Type*);
int eqargs(Type*, Type*);
uint32 typehash(Type*, int);
void frame(int);
Node* literal(int32);
Node* dobad(void);
Node* nodintconst(int32);
Node* nodintconst(int64);
Node* nodnil(void);
Node* nodbool(int);
void ullmancalc(Node*);
void badtype(int, Type*, Type*);
Type* ptrto(Type*);
@ -735,7 +717,8 @@ void dodclvar(Node*, Type*);
Type* dodcltype(Type*);
void updatetype(Type*, Type*);
void dodclconst(Node*, Node*);
void defaultlit(Node*);
void defaultlit(Node*, Type*);
void defaultlit2(Node*, Node*);
int listcount(Node*);
void addmethod(Node*, Type*, int);
Node* methodname(Node*, Type*);
@ -806,7 +789,7 @@ void doimport6(Node*, Node*);
void doimport7(Node*, Node*);
void doimport8(Node*, Val*, Node*);
void doimport9(Sym*, Node*);
void importconst(Node *ss, Type *t, Val *v);
void importconst(Node *ss, Type *t, Node *v);
void importmethod(Sym *s, Type *t);
void importtype(Node *ss, Type *t);
void importvar(Node *ss, Type *t, int ctxt);
@ -826,7 +809,6 @@ void walkas(Node*);
void walkbool(Node*);
void walkswitch(Node*);
void walkselect(Node*);
int whatis(Node*);
void walkdot(Node*);
Node* ascompatee(int, Node**, Node**);
Node* ascompatet(int, Node**, Type**, int);
@ -871,6 +853,8 @@ void convlit(Node*, Type*);
void evconst(Node*);
int cmpslit(Node *l, Node *r);
int smallintconst(Node*);
int consttype(Node*);
int isconst(Node*, int);
/*
* gen.c/gsubr.c/obj.c

View file

@ -73,7 +73,7 @@
%type <type> indcl fnlitdcl dotdotdot
%type <val> oliteral
%type <val> hidden_constant
%type <node> hidden_constant
%type <node> hidden_dcl hidden_structdcl
%type <type> hidden_type hidden_type1 hidden_type2
%type <node> hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r
@ -447,12 +447,12 @@ simple_stmt:
}
| expr LINC
{
$$ = nod(OASOP, $1, literal(1));
$$ = nod(OASOP, $1, nodintconst(1));
$$->etype = OADD;
}
| expr LDEC
{
$$ = nod(OASOP, $1, literal(1));
$$ = nod(OASOP, $1, nodintconst(1));
$$->etype = OSUB;
}
@ -822,10 +822,22 @@ uexpr:
pexpr:
LLITERAL
{
$$ = nod(OLITERAL, N, N);
$$->val = $1;
if($1.ctype == CTSTR)
$$->type = types[TSTRING];
$$ = nodlit($1);
}
| LNIL
{
Val v;
v.ctype = CTNIL;
$$ = nodlit(v);
}
| LTRUE
{
$$ = nodbool(1);
}
| LFALSE
{
$$ = nodbool(0);
}
| laconst
{
@ -833,22 +845,9 @@ pexpr:
$$->val = $1->oconst->val;
$$->type = $1->oconst->type;
}
| LNIL
{
$$ = nod(OLITERAL, N, N);
$$->val.ctype = CTNIL;
}
| LTRUE
{
$$ = booltrue;
}
| LFALSE
{
$$ = boolfalse;
}
| LIOTA
{
$$ = literal(iota);
$$ = nodintconst(iota);
$$->iota = 1; // flag to reevaluate on copy
}
| name
@ -1828,11 +1827,11 @@ hidden_import:
}
| LCONST hidden_pkg_importsym '=' hidden_constant
{
importconst($2, T, &$4);
importconst($2, types[TIDEAL], $4);
}
| LCONST hidden_pkg_importsym hidden_type '=' hidden_constant
{
importconst($2, $3, &$5);
importconst($2, $3, $5);
}
| LTYPE hidden_pkg_importsym hidden_type
{
@ -1870,11 +1869,7 @@ hidden_type1:
}
| '[' LLITERAL ']' hidden_type
{
Node *n;
n = nod(OLITERAL, N, N);
n->val = $2;
$$ = aindex(n, $4);
$$ = aindex(nodlit($2), $4);
}
| LMAP '[' hidden_type ']' hidden_type
{
@ -1978,15 +1973,18 @@ hidden_funres:
hidden_constant:
LLITERAL
{
$$ = nodlit($1);
}
| '-' LLITERAL
{
$$ = $2;
switch($$.ctype){
$$ = nodlit($2);
switch($$->val.ctype){
case CTINT:
mpnegfix($$.u.xval);
mpnegfix($$->val.u.xval);
break;
case CTFLT:
mpnegflt($$.u.fval);
mpnegflt($$->val.u.fval);
break;
default:
yyerror("bad negated constant");
@ -1994,11 +1992,11 @@ hidden_constant:
}
| LTRUE
{
$$ = booltrue->val;
$$ = nodbool(1);
}
| LFALSE
{
$$ = boolfalse->val;
$$ = nodbool(0);
}
hidden_importsym:

View file

@ -58,7 +58,6 @@ mainlex(int argc, char *argv[])
fmtinstall('L', Lconv); // line number
fmtinstall('B', Bconv); // big numbers
fmtinstall('F', Fconv); // big float numbers
fmtinstall('W', Wconv); // whatis numbers (Wlitint)
lexinit();
lineno = 1;
@ -115,13 +114,14 @@ usage:
print("flags:\n");
print(" -I DIR search for packages in DIR\n");
print(" -d print declarations\n");
print(" -e no limit on number of errors printed\n");
print(" -f print stack frame structure\n");
print(" -h panic on an error\n");
print(" -k name specify package name\n");
print(" -o file specify output file\n");
print(" -p print the assembly language\n");
print(" -w print the parse tree after typing\n");
print(" -x print lex tokens\n");
print(" -h panic on an error\n");
myexit(0);
return 0;
}
@ -1276,20 +1276,12 @@ lexinit(void)
/* for walk to use in error messages */
types[TFUNC] = functype(N, N, N);
/* types used in front end */
types[TNIL] = typ(TNIL);
types[TIDEAL] = typ(TIDEAL);
/* pick up the backend typedefs */
belexinit(LBASETYPE);
booltrue = nod(OLITERAL, N, N);
booltrue->val.u.bval = 1;
booltrue->val.ctype = CTBOOL;
booltrue->type = types[TBOOL];
booltrue->addable = 1;
boolfalse = nod(OLITERAL, N, N);
boolfalse->val.u.bval = 0;
boolfalse->val.ctype = CTBOOL;
boolfalse->type = types[TBOOL];
boolfalse->addable = 1;
}
struct

View file

@ -154,10 +154,22 @@ mpmovefixflt(Mpflt *a, Mpint *b)
mpnorm(a);
}
void
// convert (truncate) b to a.
// return -1 (but still convert) if b was non-integer.
int
mpmovefltfix(Mpint *a, Mpflt *b)
{
mpmovecfix(a, mpgetflt(b));
Mpflt f;
*a = b->val;
mpshiftfix(a, b->exp);
if(b->exp < 0) {
f.val = *a;
f.exp = 0;
mpnorm(&f);
if(mpcmpfltflt(b, &f) != 0)
return -1;
}
return 0;
}
void
@ -303,7 +315,7 @@ bad:
//
// fixed point input
// required syntax is [+-][0[x]]d*
//
//
void
mpatofix(Mpint *a, char *as)
{
@ -422,8 +434,20 @@ Fconv(Fmt *fp)
{
char buf[500];
Mpflt *fvp, fv;
double d;
fvp = va_arg(fp->args, Mpflt*);
if(fp->flags & FmtSharp) {
// alternate form - decimal for error messages.
// for well in range, convert to double and use print's %g
if(-900 < fvp->exp && fvp->exp < 900) {
d = mpgetflt(fvp);
return fmtprint(fp, "%g", d);
}
// TODO(rsc): for well out of range, print
// an approximation like 1.234e1000
}
if(sigfig(fvp) == 0) {
snprint(buf, sizeof(buf), "0p+0");
goto out;

View file

@ -159,6 +159,7 @@ mpneg(Mpint *a)
}
}
// shift left by s (or right by -s)
void
mpshiftfix(Mpint *a, int s)
{

View file

@ -29,7 +29,7 @@ yyerror(char *fmt, ...)
*(int*)0 = 0;
nerrors++;
if(nerrors >= 10)
if(nerrors >= 10 && !debug['e'])
fatal("too many errors");
}
@ -351,7 +351,7 @@ dobad(void)
}
Node*
nodintconst(int32 v)
nodintconst(int64 v)
{
Node *c;
@ -360,11 +360,34 @@ nodintconst(int32 v)
c->val.u.xval = mal(sizeof(*c->val.u.xval));
mpmovecfix(c->val.u.xval, v);
c->val.ctype = CTINT;
c->type = types[TINT];
c->type = types[TIDEAL];
ullmancalc(c);
return c;
}
Node*
nodnil(void)
{
Node *c;
c = nodintconst(0);
c->val.ctype = CTNIL;
c->type = types[TNIL];
return c;
}
Node*
nodbool(int b)
{
Node *c;
c = nodintconst(0);
c->val.ctype = CTBOOL;
c->val.u.bval = b;
c->type = types[TBOOL];
return c;
}
Node*
rev(Node *na)
{
@ -437,19 +460,17 @@ aindex(Node *b, Type *t)
bound = -1; // open bound
walktype(b, Erv);
switch(whatis(b)) {
default: // variable bound
yyerror("array bound must be an integer expression");
break;
case Wnil: // open bound
break;
case Wlitint: // fixed bound
bound = mpgetfix(b->val.u.xval);
if(bound < 0)
yyerror("array bound must be non negative");
break;
if(b != nil) {
switch(consttype(b)) {
default:
yyerror("array bound must be an integer expression");
break;
case CTINT:
bound = mpgetfix(b->val.u.xval);
if(bound < 0)
yyerror("array bound must be non negative");
break;
}
}
// fixed array
@ -569,64 +590,6 @@ dump(char *s, Node *n)
dodump(n, 1);
}
int
whatis(Node *n)
{
Type *t;
if(n == N)
return Wnil;
if(n->op == OLITERAL) {
switch(n->val.ctype) {
default:
break;
case CTINT:
case CTSINT:
case CTUINT:
return Wlitint;
case CTFLT:
return Wlitfloat;
case CTBOOL:
return Wlitbool;
case CTSTR:
return Wlitstr;
case CTNIL:
return Wlitnil; // not used
}
return Wtunkn;
}
t = n->type;
if(t == T)
return Wtnil;
switch(t->etype) {
case TINT:
case TINT8:
case TINT16:
case TINT32:
case TINT64:
case TUINT:
case TUINT8:
case TUINT16:
case TUINT32:
case TUINT64:
case TUINTPTR:
return Wtint;
case TFLOAT:
case TFLOAT32:
case TFLOAT64:
case TFLOAT80:
return Wtfloat;
case TBOOL:
return Wtbool;
case TSTRING:
return Wtstr;
}
return Wtunkn;
}
/*
s%,%,\n%g
s%\n+%\n%g
@ -1013,6 +976,8 @@ basicnames[] =
[TANY] = "any",
[TDDD] = "...",
[TSTRING] = "string",
[TNIL] = "nil",
[TIDEAL] = "ideal",
};
int
@ -1302,8 +1267,6 @@ Nconv(Fmt *fp)
snprint(buf1, sizeof(buf1), "LITERAL-ctype=%d", n->val.ctype);
break;
case CTINT:
case CTSINT:
case CTUINT:
snprint(buf1, sizeof(buf1), "I%B", n->val.u.xval);
break;
case CTFLT:
@ -1363,7 +1326,7 @@ treecopy(Node *n)
case OLITERAL:
if(n->iota) {
m = literal(iota);
m = nodintconst(iota);
break;
}
m = nod(OXXX, N, N);
@ -1416,34 +1379,6 @@ Zconv(Fmt *fp)
return 0;
}
static char*
wnames[] =
{
[Wnil] = "Wnil",
[Wtnil] = "Wtnil",
[Wtfloat] = "Wtfloat",
[Wtint] = "Wtint",
[Wtbool] = "Wtbool",
[Wtstr] = "Wtstr",
[Wlitfloat] = "float constant",
[Wlitint] = "int constant",
[Wlitbool] = "bool",
[Wlitstr] = "string",
[Wlitnil] = "nil",
};
int
Wconv(Fmt *fp)
{
int w;
w = va_arg(fp->args, int);
if(w < 0 || w >= nelem(wnames) || wnames[w] == nil)
return fmtprint(fp, "W-%d", w);
return fmtstrcpy(fp, wnames[w]);
}
int
isnil(Node *n)
{
@ -2043,18 +1978,6 @@ ptrto(Type *t)
return t1;
}
Node*
literal(int32 v)
{
Node *n;
n = nod(OLITERAL, N, N);
n->val.u.xval = mal(sizeof(*n->val.u.xval));
n->val.ctype = CTINT;
mpmovecfix(n->val.u.xval, v);
return n;
}
void
frame(int context)
{

View file

@ -448,7 +448,7 @@ walkswitch(Node *sw)
*/
walkstate(sw->ninit);
if(sw->ntest == N)
sw->ntest = booltrue;
sw->ntest = nodbool(1);
casebody(sw);
/*
@ -466,7 +466,7 @@ walkswitch(Node *sw)
return;
}
arg = Snorm;
if(whatis(sw->ntest) == Wlitbool) {
if(isconst(sw->ntest, CTBOOL)) {
arg = Strue;
if(sw->ntest->val.u.xval == 0)
arg = Sfalse;
@ -523,10 +523,10 @@ iscaseconst(Node *t)
{
if(t == N || t->left == N)
return 0;
switch(whatis(t->left)) {
case Wlitfloat:
case Wlitint:
case Wlitstr:
switch(consttype(t->left)) {
case CTFLT:
case CTINT:
case CTSTR:
return 1;
}
return 0;
@ -616,19 +616,23 @@ csort(Case *l, int(*f)(Case*, Case*))
int
casecmp(Case *c1, Case *c2)
{
int w;
int ct;
Node *n1, *n2;
w = whatis(c1->node->left);
if(w != whatis(c2->node->left))
n1 = c1->node->left;
n2 = c2->node->left;
ct = n1->val.ctype;
if(ct != n2->val.ctype)
fatal("casecmp1");
switch(w) {
case Wlitfloat:
return mpcmpfltflt(c1->node->left->val.u.fval, c2->node->left->val.u.fval);
case Wlitint:
return mpcmpfixfix(c1->node->left->val.u.xval, c2->node->left->val.u.xval);
case Wlitstr:
return cmpslit(c1->node->left, c2->node->left);
switch(ct) {
case CTFLT:
return mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
case CTINT:
return mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
case CTSTR:
return cmpslit(n1, n2);
}
fatal("casecmp2");

View file

@ -356,7 +356,7 @@ loop:
goto ret;
walktype(n->left, Erv);
convlit(n->left, types[TFUNC]);
defaultlit(n->left, T);
t = n->left->type;
if(t == T)
@ -367,11 +367,8 @@ loop:
if(n->left->op == ODOTINTER)
n->op = OCALLINTER;
if(isptr[t->etype])
t = t->type;
if(t->etype != TFUNC) {
yyerror("call of a non-function %T", t);
yyerror("call of a non-function: %T", t);
goto ret;
}
@ -406,7 +403,9 @@ loop:
n->right = reorder1(l);
if(isselect(n)) {
// clear output bool - special prob with selectsend
r = ascompatte(n->op, getoutarg(t), &boolfalse, 0);
Node *b;
b = nodbool(0);
r = ascompatte(n->op, getoutarg(t), &b, 0);
n->right = list(n->right, r);
}
break;
@ -586,7 +585,7 @@ loop:
if(l == N)
goto ret;
walktype(l, Erv);
// structure literal
if(t->etype == TSTRUCT) {
indir(n, structlit(n, N));
@ -623,6 +622,9 @@ loop:
case ONOT:
if(top != Erv)
goto nottop;
evconst(n);
if(n->op == OLITERAL)
goto ret;
walktype(n->left, Erv);
if(n->left == N || n->left->type == T)
goto ret;
@ -634,15 +636,11 @@ loop:
goto nottop;
walktype(n->left, Elv);
l = n->left;
if(l->op != OINDEX) {
if(n->etype == OLSH || n->etype == ORSH)
goto shft;
goto com;
}
if(!istype(l->left->type, TMAP))
goto com;
indir(n, mapop(n, top));
goto ret;
if(l->op == OINDEX && istype(l->left->type, TMAP))
indir(n, mapop(n, top));
if(n->etype == OLSH || n->etype == ORSH)
goto shft;
goto com;
case OLSH:
case ORSH:
@ -657,14 +655,14 @@ loop:
evconst(n);
if(n->op == OLITERAL)
goto ret;
if(n->left->type == T)
convlit(n->left, types[TINT]);
if(n->right->type == T)
convlit(n->right, types[TUINT]);
// do NOT defaultlit n->left.
// let parent defaultlit or convlit instead.
defaultlit(n->right, types[TUINT]);
if(n->left->type == T || n->right->type == T)
goto ret;
if(issigned[n->right->type->etype])
goto badt;
// check of n->left->type happens in second switch.
break;
case OMOD:
@ -695,8 +693,7 @@ loop:
evconst(n);
if(n->op == OLITERAL)
goto ret;
convlit(n->left, n->right->type);
convlit(n->right, n->left->type);
defaultlit2(n->left, n->right);
if(n->left->type == T || n->right->type == T)
goto ret;
if(!eqtype(n->left->type, n->right->type, 0))
@ -749,6 +746,7 @@ loop:
if(top != Erv)
goto nottop;
walktype(n->left, Erv);
defaultlit(n->left, T);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
@ -757,7 +755,7 @@ loop:
default:
goto badt;
case TSTRING:
if(whatis(n->left) == Wlitstr)
if(isconst(n->left, CTSTR))
nodconst(n, types[TINT], n->left->val.u.sval->len);
break;
case TMAP:
@ -774,8 +772,8 @@ loop:
if(top != Erv)
goto nottop;
walktype(n->left, Erv);
defaultlit(n->left, T);
implicitstar(&n->left);
evconst(n);
t = n->left->type;
if(t == T)
goto ret;
@ -800,7 +798,7 @@ loop:
if(n->left == N || n->right == N)
goto ret;
defaultlit(n->left);
defaultlit(n->left, T);
implicitstar(&n->left);
t = n->left->type;
@ -809,17 +807,16 @@ loop:
switch(t->etype) {
default:
defaultlit(n->right, T);
goto badt;
case TSTRING:
// right side must be an int
if(top != Erv)
goto nottop;
if(n->right->type == T) {
convlit(n->right, types[TINT]);
if(n->right->type == T)
break;
}
defaultlit(n->right, types[TINT]);
if(n->right->type == T)
break;
if(!isint[n->right->type->etype])
goto badt;
indir(n, stringop(n, top));
@ -827,11 +824,9 @@ loop:
case TMAP:
// right side must be map type
if(n->right->type == T) {
convlit(n->right, t->down);
if(n->right->type == T)
break;
}
defaultlit(n->right, t->down);
if(n->right->type == T)
break;
if(!eqtype(n->right->type, t->down, 0))
goto badt;
n->type = t->type;
@ -841,14 +836,11 @@ loop:
case TARRAY:
// right side must be an int
if(n->right->type == T) {
convlit(n->right, types[TINT]);
if(n->right->type == T)
break;
}
defaultlit(n->right, types[TINT]);
if(n->right->type == T)
break;
if(!isint[n->right->type->etype])
goto badt;
n->type = t->type;
break;
}
@ -871,7 +863,7 @@ loop:
case OSEND:
if(top == Elv)
goto nottop;
walktype(n->left, Erv); // chan
walktype(n->left, Erv); // chan
walktype(n->right, Erv); // e
indir(n, chanop(n, top));
goto ret;
@ -897,7 +889,9 @@ loop:
walktype(n->right, Erv);
if(n->left == N || n->right == N)
goto ret;
convlit(n->left, types[TSTRING]);
defaultlit(n->left, T);
defaultlit(n->right->left, types[TUINT]);
defaultlit(n->right->right, types[TUINT]);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
@ -919,12 +913,14 @@ loop:
case ODOTINTER:
if(top == Etop)
goto nottop;
defaultlit(n->left, T);
walkdot(n);
goto ret;
case OADDR:
if(top != Erv)
goto nottop;
defaultlit(n->left, T);
if(n->left->op == OCOMPOS && n->left->type != T) {
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
// initialize with
@ -968,13 +964,13 @@ loop:
yyerror("cannot take address of function");
}
}
walktype(n->left, Elv);
addrescapes(n->left);
if(n->left == N)
goto ret;
walktype(n->left, Elv);
t = n->left->type;
if(t == T)
goto ret;
addrescapes(n->left);
n->type = ptrto(t);
goto ret;
@ -984,6 +980,7 @@ loop:
if(top == Elv) // even if n is lvalue, n->left is rvalue
top = Erv;
walktype(n->left, top);
defaultlit(n->left, T);
if(n->left == N)
goto ret;
t = n->left->type;
@ -1041,12 +1038,8 @@ loop:
case ONE:
if(n->left->type == T)
goto ret;
if(isslice(n->left->type)) {
t = types[TBOOL];
break;
}
et = n->left->type->etype;
if(!okforeq[et])
if(!okforeq[et] && !isslice(n->left->type))
goto badt;
if(isinter(n->left->type)) {
indir(n, ifaceop(T, n, n->op));
@ -1085,18 +1078,14 @@ loop:
et = n->left->type->etype;
if(!okforadd[et])
goto badt;
if(!isfloat[et])
break;
l = nod(OLITERAL, N, N);
l->val.u.fval = mal(sizeof(*l->val.u.fval));
l->val.ctype = CTFLT;
mpmovecflt(l->val.u.fval, 0.0);
l = nod(OSUB, l, n->left);
indir(n, l);
walktype(n, Erv);
goto ret;
if(isfloat[et]) {
// TODO(rsc): Can do this more efficiently,
// but OSUB is wrong. Should be in back end anyway.
indir(n, nod(OMUL, n->left, nodintconst(-1)));
walktype(n, Erv);
goto ret;
}
break;
case OLSH:
case ORSH:
@ -1109,17 +1098,27 @@ loop:
if(n->left->type == T)
goto ret;
et = n->left->type->etype;
if(!okforand[et])
if(et != TIDEAL && !okforand[et])
goto badt;
break;
}
if(t == T)
if(t == T) {
t = n->left->type;
// throw away name:
// type MyInt int
// var x MyInt = 0;
// -x has type int, not MyInt.
if(t != T)
t = types[t->etype];
}
n->type = t;
goto ret;
nottop:
if(n->diag)
goto ret;
n->diag = 1;
switch(top) {
default:
yyerror("didn't expect %O here", n->op);
@ -1137,6 +1136,9 @@ nottop:
goto ret;
badt:
if(n->diag)
goto ret;
n->diag = 1;
if(n->right == N) {
if(n->left == N) {
badtype(n->op, T, T);
@ -1160,14 +1162,13 @@ void
walkbool(Node *n)
{
walktype(n, Erv);
defaultlit(n, T);
addtotop(n);
if(n != N && n->type != T)
if(!eqtype(n->type, types[TBOOL], 0))
yyerror("IF and FOR require a boolean type");
}
void
walkconv(Node *n)
{
@ -1182,12 +1183,15 @@ walkconv(Node *n)
if(l == N)
return;
walktype(l, Erv);
convlit1(l, t, 1);
if(l->type == T)
return;
// if using .(T), interface assertion.
if(n->op == ODOTTYPE) {
// interface conversion
defaultlit(l, T);
if(!isinter(l->type))
yyerror("type assertion requires interface on left, have %T", l->type);
et = ifaceas(n->type, l->type, 1);
if(et != Inone) {
indir(n, ifaceop(n->type, l, et));
@ -1197,6 +1201,9 @@ walkconv(Node *n)
}
// otherwise, conversion.
convlit1(l, t, 1);
if(l->type == T)
return;
// nil conversion
if(eqtype(t, l->type, 0)) {
@ -1208,7 +1215,6 @@ walkconv(Node *n)
}
// simple fix-float
if(l->type != T)
if(isint[l->type->etype] || isfloat[l->type->etype])
if(isint[t->etype] || isfloat[t->etype]) {
evconst(n);
@ -1324,6 +1330,7 @@ recv:
a = c->left; // nil elem
a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL;
a->type = types[TNIL];
r = a;
a = c->left; // chan
@ -1797,7 +1804,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp)
st = typ(TSTRUCT); // generated structure
ft = T; // last field
while(r != N) {
defaultlit(r);
defaultlit(r, T);
// generate the next structure field
t = typ(TFIELD);
@ -1968,7 +1975,7 @@ prcompat(Node *n, int fmt)
Node *on;
Type *t;
Iter save;
int w, notfirst;
int notfirst, et;
r = N;
l = listfirst(&save, &n);
@ -1989,49 +1996,42 @@ loop:
r = list(r, nod(OCALL, on, N));
}
w = whatis(l);
switch(w) {
default:
if(l->type == T)
goto out;
if(isinter(l->type)) {
on = syslook("printinter", 1);
argtype(on, l->type); // any-1
break;
}
if(isptr[l->type->etype]
|| l->type->etype == TCHAN
|| l->type->etype == TMAP
|| l->type->etype == TFUNC) {
on = syslook("printpointer", 1);
argtype(on, l->type); // any-1
break;
}
if(isslice(l->type)) {
on = syslook("printarray", 1);
argtype(on, l->type); // any-1
walktype(l, Erv);
if(l->op == OLITERAL) {
switch(l->val.ctype) {
case CTINT:
defaultlit(l, types[TINT64]);
break;
case CTFLT:
defaultlit(l, types[TFLOAT64]);
break;
}
}
if(l->type == T)
goto out;
et = l->type->etype;
if(isinter(l->type)) {
on = syslook("printinter", 1);
argtype(on, l->type); // any-1
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
on = syslook("printpointer", 1);
argtype(on, l->type); // any-1
} else if(isslice(l->type)) {
on = syslook("printarray", 1);
argtype(on, l->type); // any-1
} else if(isint[et]) {
on = syslook("printint", 0);
} else if(isfloat[et]) {
on = syslook("printfloat", 0);
} else if(et == TBOOL) {
on = syslook("printbool", 0);
} else if(et == TSTRING) {
on = syslook("printstring", 0);
} else {
badtype(OPRINT, l->type, T);
l = listnext(&save);
goto loop;
case Wlitint:
case Wtint:
on = syslook("printint", 0);
break;
case Wlitfloat:
case Wtfloat:
on = syslook("printfloat", 0);
break;
case Wlitbool:
case Wtbool:
on = syslook("printbool", 0);
break;
case Wlitstr:
case Wtstr:
on = syslook("printstring", 0);
break;
}
t = *getinarg(on->type);
@ -2538,6 +2538,7 @@ chanop(Node *n, int top)
goto shape;
// chanrecv2(hchan *chan any) (elem any, pres bool);
defaultlit(n->right->left, T);
t = fixchan(n->right->left->type);
if(t == T)
break;
@ -2560,7 +2561,7 @@ chanop(Node *n, int top)
goto recv2;
// chanrecv1(hchan *chan any) (elem any);
defaultlit(n->left, T);
t = fixchan(n->left->type);
if(t == T)
break;
@ -2588,6 +2589,7 @@ chanop(Node *n, int top)
if(a == N) {
a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL;
a->type = types[TNIL];
} else
a = nod(OADDR, a, N);
@ -3072,7 +3074,7 @@ colas(Node *nl, Node *nr)
while(l != N) {
walktype(r, Erv);
defaultlit(r);
defaultlit(r, T);
a = old2new(l, r->type);
n = list(n, a);
@ -3215,9 +3217,9 @@ ary:
hk = nod(OXXX, N, N); // hidden key
tempname(hk, types[TINT]); // maybe TINT32
n->ninit = nod(OAS, hk, literal(0));
n->ninit = nod(OAS, hk, nodintconst(0));
n->ntest = nod(OLT, hk, nod(OLEN, m, N));
n->nincr = nod(OASOP, hk, literal(1));
n->nincr = nod(OASOP, hk, nodintconst(1));
n->nincr->etype = OADD;
if(local)
@ -3250,9 +3252,10 @@ map:
r = nod(OCALL, on, r);
n->ninit = r;
r = nod(OINDEX, hk, literal(0));
r = nod(OINDEX, hk, nodintconst(0));
a = nod(OLITERAL, N, N);
a->val.ctype = CTNIL;
a->type = types[TNIL];
r = nod(ONE, r, a);
n->ntest = r;
@ -3678,19 +3681,14 @@ loop:
* the current function returns. mark any local vars
* as needing to move to the heap.
*/
static char *pnames[] = {
[PAUTO] "auto",
[PPARAM] "param",
[PPARAMOUT] "param_out",
};
void
addrescapes(Node *n)
{
char buf[100];
switch(n->op) {
default:
dump("addrescapes", n);
// probably a type error already.
// dump("addrescapes", n);
break;
case ONAME:
@ -3702,8 +3700,6 @@ addrescapes(Node *n)
break;
case PAUTO:
case PPARAM:
if(debug['E'])
print("%L %s %S escapes %p\n", n->lineno, pnames[n->class], n->sym, n);
// if func param, need separate temporary
// to hold heap pointer.
if(n->class == PPARAM) {

View file

@ -235,7 +235,7 @@ func str(val int64) string { // do it here rather than with fmt to avoid depend
}
func Errstr(errno int64) string {
if errno < 0 || errno >= len(error) {
if errno < 0 || errno >= int64(len(error)) {
return "Error " + str(errno)
}
return error[errno]

View file

@ -285,7 +285,7 @@ func str(val int64) string { // do it here rather than with fmt to avoid depend
}
func Errstr(errno int64) string {
if errno < 0 || errno >= len(error) {
if errno < 0 || errno >= int64(len(error)) {
return "Error " + str(errno)
}
return error[errno]

View file

@ -14,6 +14,9 @@ const (
c1 = chuge >> 100;
c3div2 = 3/2;
c1e3 = 1e3;
ctrue = true;
cfalse = !ctrue;
)
const (
@ -111,4 +114,7 @@ func floats() {
func main() {
ints();
floats();
assert(ctrue == true, "ctrue == true");
assert(cfalse == false, "cfalse == false");
}

79
test/const1.go Normal file
View file

@ -0,0 +1,79 @@
// errchk $G -e $F.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
type I interface {}
const (
// assume all types behave similarly to int8/uint8
Int8 int8 = 101;
Minus1 int8 = -1;
Uint8 uint8 = 102;
Const = 103;
Float32 float32 = 104.5;
Float float = 105.5;
ConstFloat = 106.5;
Big float64 = 1e300;
String = "abc";
Bool = true;
)
var (
a1 = Int8 * 100; // ERROR "overflows"
a2 = Int8 * -1; // OK
a3 = Int8 * 1000; // ERROR "overflows"
a4 = Int8 * int8(1000); // ERROR "overflows"
a5 = int8(Int8 * 1000); // ERROR "overflows"
a6 = int8(Int8 * int8(1000)); // ERROR "overflows"
a7 = Int8 - 2*Int8 - 2*Int8; // ERROR "overflows"
a8 = Int8 * Const / 100; // ERROR "overflows"
a9 = Int8 * (Const / 100); // OK
b1 = Uint8 * Uint8; // ERROR "overflows"
b2 = Uint8 * -1; // ERROR "overflows"
b3 = Uint8 - Uint8; // OK
b4 = Uint8 - Uint8 - Uint8; // ERROR "overflows"
b5 = uint8(^0); // ERROR "overflows"
b6 = ^uint8(0); // ERROR "overflows"
b7 = uint8(Minus1); // ERROR "overflows"
b8 = uint8(int8(-1)); // ERROR "overflows"
b8a = uint8(-1); // ERROR "overflows"
b9 byte = (1<<10) >> 8; // OK
b10 byte = (1<<10); // ERROR "overflows"
b11 byte = (byte(1)<<10) >> 8; // ERROR "overflows"
b12 byte = 1000; // ERROR "overflows"
b13 byte = byte(1000); // ERROR "overflows"
b14 byte = byte(100) * byte(100); // ERROR "overflows"
b15 byte = byte(100) * 100; // ERROR "overflows"
b16 byte = byte(0) * 1000; // ERROR "overflows"
b16a byte = 0 * 1000; // OK
b17 byte = byte(0) * byte(1000); // ERROR "overflows"
b18 byte = Uint8/0; // ERROR "division by zero"
c1 float64 = Big;
c2 float64 = Big*Big; // ERROR "overflows"
c3 float64 = float64(Big)*Big; // ERROR "overflows"
c4 = Big*Big; // ERROR "overflows"
c5 = Big/0; // ERROR "division by zero"
)
func f(int);
func main() {
f(Int8); // ERROR "convert"
f(Minus1); // ERROR "convert"
f(Uint8); // ERROR "convert"
f(Const); // OK
f(Float32); // ERROR "convert"
f(Float); // ERROR "convert"
f(ConstFloat); // ERROR "truncate"
f(ConstFloat - 0.5); // OK
f(Big); // ERROR "convert"
f(String); // ERROR "convert"
f(Bool); // ERROR "convert"
}

12
test/const2.go Normal file
View file

@ -0,0 +1,12 @@
// errchk $G $D/$F.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
const (
A int = 1;
B byte; // ERROR "type without expr"
)

29
test/const3.go Normal file
View file

@ -0,0 +1,29 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
type T int
func (t T) String() string {
return fmt.Sprintf("T%d", t);
}
const (
A T = 1<<(1<<iota);
B;
C;
D;
E;
)
func main() {
s := fmt.Sprintf("%v %v %v %v %v", A, B, C, D, E);
if s != "T2 T4 T16 T256 T65536" {
panicln("type info didn't propagate in const: got", s);
}
}

53
test/convert.go Normal file
View file

@ -0,0 +1,53 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "unsafe"
func typeof(x interface{}) string {
val, typ, indir := sys.Reflect(x);
return typ;
}
func f() int {
return 0;
}
func g() int {
return 0;
}
type T func() int
var m = map[string] T {
"f": f
}
type A int
type B int
var a A = 1;
var b B = 2;
var x int;
func main() {
want := typeof(g);
if t := typeof(f); t != want {
panicln("type of f is", t, "want", want);
}
want = typeof(x);
if t := typeof(+a); t != want {
panicln("type of +a is", t, "want", want);
}
if t := typeof(a+0); t != want {
panicln("type of a+0 is", t, "want", want);
}
if t := typeof(a+b); t != want {
panicln("type of a+b is", t, "want", want);
}
}

View file

@ -4,6 +4,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// ! errchk $G -e $D/$F.go
package main
// explicit conversions are okay, even if they overflow
@ -20,10 +22,10 @@ var s string;
var bad1 string = 1; // ERROR "conver|incompatible"
var bad2 = s + 1; // ERROR "conver|incompatible"
var bad3 = s + 'a'; // ERROR "conver|incompatible"
var bad4 = "a" + 1; // ERROR "literals|incompatible"
var bad5 = "a" + 'a'; // ERROR "literals|incompatible"
var bad4 = "a" + 1; // ERROR "literals|incompatible|convert"
var bad5 = "a" + 'a'; // ERROR "literals|incompatible|convert"
var bad6 int = 1.5; // ERROR "convert"
var bad6 int = 1.5; // ERROR "convert|truncate"
var bad7 int = 1e100; // ERROR "overflow"
var bad8 float32 = 1e200; // ERROR "overflow"

View file

@ -63,11 +63,11 @@ pr -n -t $SOURCEFILE | grep '// ERROR' | while read line; do
mv -f $TMPTMP $TMPALL
if test -z "$errmsg"; then
bug
echo 1>&2 "errchk: $SOURCEFILE: missing expected error message on line $lineno: '$regexp'"
echo 1>&2 "errchk: $SOURCEFILE:$lineno: missing expected error: '$regexp'"
echo 1 > $TMPSTAT
elif ! echo "$errmsg" | egrep -q "$regexp"; then
bug
echo 1>&2 "errchk: $SOURCEFILE: error message on line $lineno does not match '$regexp'"
echo 1>&2 "errchk: $SOURCEFILE:$lineno: error message does not match '$regexp'"
echo 1>&2 $errmsg
echo 1 > $TMPSTAT
fi

View file

@ -33,13 +33,14 @@ func main() {
f = f3div2;
assert(f == f3div2, "f == f3div2");
i = f3div2; // BUG: probably shouldn't compile
i = f3div2; // ERROR "truncate"
assert(i == c3div2, "i == c3div2 from f3div2");
assert(i != f3div2, "i != f3div2"); // BUG: certainly shouldn't fail
assert(i != f3div2, "i != f3div2"); // ERROR "truncate"
const g float64 = 1.0;
i = g; // BUG: shouldn't compile
i = g; // ERROR "convert"
const h float64 = 3.14;
i = h; // BUG: certainly shouldn't compile
i = h; // ERROR "convert"
i = int(h); // ERROR "truncate"
}

View file

@ -7,6 +7,6 @@
package main
func main() {
var x int64 = 0;
println(x != nil); // ERROR "illegal|incompatible"
println(0 != nil); // ERROR "illegal|incompatible"
println(x != nil); // ERROR "illegal|incompatible|nil constant"
println(0 != nil); // ERROR "illegal|incompatible|nil constant"
}

View file

@ -32,17 +32,12 @@ pc: xxx
=========== ./convlit.go
BUG: errchk: ./convlit.go: missing expected error message on line 16: 'conver|incompatible'
errchk: ./convlit.go: missing expected error message on line 22: 'convert'
errchk: ./convlit.go: missing expected error message on line 23: 'overflow'
errchk: ./convlit.go: missing expected error message on line 24: 'overflow'
errchk: ./convlit.go: unmatched error messages:
BUG: errchk: ./convlit.go: unmatched error messages:
==================================================
./convlit.go:8: cannot convert non-integer constant to int
./convlit.go:11: overflow converting constant to int
./convlit.go:12: overflow converting constant to float
./convlit.go:8: cannot convert non-integer constant to int
./convlit.go:8: fatal error: too many errors
./convlit.go:8: constant 1.5 truncated to integer
./convlit.go:11: constant 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows int
./convlit.go:12: constant 34911850510716223476646871064527264675788468424693128821036252992306087892081078460155404277013793117885253p+2968 overflows float
./convlit.go:9: constant 1.5 truncated to integer
==================================================
=========== ./helloworld.go
@ -116,7 +111,7 @@ bugs/bug108.go:4: stupid shift: 1025
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug108.go
=========== bugs/bug115.go
bugs/bug115.go:8: overflow converting constant to uint
bugs/bug115.go:8: constant -1 overflows uint
BUG: bug115 should compile
=========== bugs/bug117.go
@ -129,7 +124,9 @@ BUG: should compile
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug125.go
=========== bugs/bug131.go
BUG: should not compile
bugs/bug131.go:7: cannot convert uint64 constant to int64
bugs/bug131.go:7: illegal types for operand: AS
int64
=========== bugs/bug132.go
BUG: compilation succeeds incorrectly
@ -138,12 +135,11 @@ BUG: compilation succeeds incorrectly
BUG: should not compile
=========== bugs/bug138.go
bugs/bug138.go:8: overflow converting constant to uint
bugs/bug138.go:8: illegal combination of literals CONV 7
bugs/bug138.go:8: constant -1 overflows uint
BUG should compile
=========== fixedbugs/bug016.go
fixedbugs/bug016.go:7: overflow converting constant to uint
fixedbugs/bug016.go:7: constant -3 overflows uint
=========== fixedbugs/bug027.go
hi
@ -177,7 +173,7 @@ fixedbugs/bug039.go:6: variable x redeclared in this block
fixedbugs/bug041.go:5: export of incomplete type t
=========== fixedbugs/bug049.go
fixedbugs/bug049.go:6: illegal conversion of nil to string
fixedbugs/bug049.go:6: cannot convert nil constant to string
=========== fixedbugs/bug050.go
fixedbugs/bug050.go:3: package statement must be first
@ -187,7 +183,7 @@ sys.6:1 fixedbugs/bug050.go:3: syntax error near package
fixedbugs/bug051.go:10: expression must be a constant
=========== fixedbugs/bug062.go
fixedbugs/bug062.go:6: illegal conversion of nil to string
fixedbugs/bug062.go:6: cannot convert nil constant to string
fixedbugs/bug062.go:6: illegal types for operand: AS
string
@ -210,9 +206,13 @@ fixedbugs/bug072.go:6: bug: undefined
fixedbugs/bug073.go:8: illegal types for operand: LSH
int
int
fixedbugs/bug073.go:8: illegal types for operand: AS
int
fixedbugs/bug073.go:9: illegal types for operand: RSH
int
int
fixedbugs/bug073.go:9: illegal types for operand: AS
int
=========== fixedbugs/bug074.go
fixedbugs/bug074.go:6: invalid type for composite literal: string
@ -227,18 +227,6 @@ fixedbugs/bug083.dir/bug1.go:9: syntax error near t0
=========== fixedbugs/bug086.go
fixedbugs/bug086.go:5: function ends without a return statement
=========== fixedbugs/bug090.go
fixedbugs/bug090.go:32: cannot convert non-integer constant to int
fixedbugs/bug090.go:32: illegal types for operand: AS
int
fixedbugs/bug090.go:34: cannot convert non-integer constant to int
fixedbugs/bug090.go:34: illegal types for operand: CALL
bool
fixedbugs/bug090.go:40: cannot convert non-integer constant to int
fixedbugs/bug090.go:40: illegal types for operand: AS
int
float64
=========== fixedbugs/bug091.go
fixedbugs/bug091.go:15: c: undefined
fixedbugs/bug091.go:15: illegal types for operand: AS