1
0
mirror of https://github.com/golang/go synced 2024-11-25 01:08:02 -07:00

gc: five bug fixes, one better error.

* check for struct literal assignment to private fields.
* record, fix crash involving parallel map assignment.
* avoid infinite recursion in exportassignok.
* make floating point bounds check precise.
* avoid crash on invalid receiver.

* add context to error about implicit assignment.

Fixes #86.
Fixes #88.
Fixes #158.
Fixes #174.
Fixes #201.
Fixes #204.

R=ken2
https://golang.org/cl/154144
This commit is contained in:
Russ Cox 2009-11-15 12:57:09 -08:00
parent a967f57d19
commit a338231526
17 changed files with 246 additions and 65 deletions

View File

@ -495,10 +495,11 @@ typeinit(void)
mpatofix(maxintval[TUINT32], "0xffffffff"); mpatofix(maxintval[TUINT32], "0xffffffff");
mpatofix(maxintval[TUINT64], "0xffffffffffffffff"); mpatofix(maxintval[TUINT64], "0xffffffffffffffff");
mpatoflt(maxfltval[TFLOAT32], "3.40282347e+38"); /* f is valid float if min < f < max. (min and max are not themselves valid.) */
mpatoflt(minfltval[TFLOAT32], "-3.40282347e+38"); mpatoflt(maxfltval[TFLOAT32], "33554431p103"); /* 2^24-1 p (127-23) + 1/2 ulp*/
mpatoflt(maxfltval[TFLOAT64], "1.7976931348623157e+308"); mpatoflt(minfltval[TFLOAT32], "-33554431p103");
mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308"); mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */
mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
/* for walk to use in error messages */ /* for walk to use in error messages */
types[TFUNC] = functype(N, nil, nil); types[TFUNC] = functype(N, nil, nil);

View File

@ -261,8 +261,8 @@ overflow(Val v, Type *t)
case CTFLT: case CTFLT:
if(!isfloat[t->etype]) if(!isfloat[t->etype])
fatal("overflow: %T floating-point constant", t); fatal("overflow: %T floating-point constant", t);
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) < 0 if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) <= 0
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) > 0) || mpcmpfltflt(v.u.fval, maxfltval[t->etype]) >= 0)
yyerror("constant %#F overflows %T", v.u.fval, t); yyerror("constant %#F overflows %T", v.u.fval, t);
break; break;
} }

View File

@ -302,11 +302,27 @@ NodeList*
variter(NodeList *vl, Node *t, NodeList *el) variter(NodeList *vl, Node *t, NodeList *el)
{ {
int doexpr; int doexpr;
Node *v, *e; Node *v, *e, *as2;
NodeList *init; NodeList *init;
init = nil; init = nil;
doexpr = el != nil; doexpr = el != nil;
if(count(el) == 1 && count(vl) > 1) {
e = el->n;
as2 = nod(OAS2, N, N);
as2->list = vl;
as2->rlist = list1(e);
for(; vl; vl=vl->next) {
v = vl->n;
v->op = ONAME;
declare(v, dclcontext);
v->ntype = t;
v->defn = as2;
}
return list1(as2);
}
for(; vl; vl=vl->next) { for(; vl; vl=vl->next) {
if(doexpr) { if(doexpr) {
if(el == nil) { if(el == nil) {

View File

@ -1048,8 +1048,8 @@ void typechecklist(NodeList*, int);
void typecheckswitch(Node*); void typecheckswitch(Node*);
void typecheckselect(Node*); void typecheckselect(Node*);
void typecheckrange(Node*); void typecheckrange(Node*);
Node* typecheckconv(Node*, Node*, Type*, int); Node* typecheckconv(Node*, Node*, Type*, int, char*);
int checkconv(Type*, Type*, int, int*, int*); int checkconv(Type*, Type*, int, int*, int*, char*);
Node* typecheck(Node**, int); Node* typecheck(Node**, int);
/* /*

View File

@ -1087,6 +1087,8 @@ xfndcl:
LFUNC fndcl fnbody LFUNC fndcl fnbody
{ {
$$ = $2; $$ = $2;
if($$ == N)
break;
$$->nbody = $3; $$->nbody = $3;
funcbody($$); funcbody($$);
} }
@ -1111,10 +1113,19 @@ fndcl:
{ {
Node *rcvr, *t; Node *rcvr, *t;
$$ = N;
if($2 == nil) {
yyerror("method has no receiver");
break;
}
if($2->next != nil) {
yyerror("method has multiple receivers");
break;
}
rcvr = $2->n; rcvr = $2->n;
if($2->next != nil || $2->n->op != ODCLFIELD) { if(rcvr->op != ODCLFIELD) {
yyerror("bad receiver in method"); yyerror("bad receiver in method");
rcvr = N; break;
} }
$$ = nod(ODCLFUNC, N, N); $$ = nod(ODCLFUNC, N, N);

View File

@ -114,6 +114,7 @@ ieeedtod(uint64 *ieee, double native)
double fr, ho, f; double fr, ho, f;
int exp; int exp;
uint32 h, l; uint32 h, l;
uint64 bits;
if(native < 0) { if(native < 0) {
ieeedtod(ieee, -native); ieeedtod(ieee, -native);
@ -129,13 +130,20 @@ ieeedtod(uint64 *ieee, double native)
fr = modf(fr*f, &ho); fr = modf(fr*f, &ho);
h = ho; h = ho;
h &= 0xfffffL; h &= 0xfffffL;
h |= (exp+1022L) << 20;
f = 65536L; f = 65536L;
fr = modf(fr*f, &ho); fr = modf(fr*f, &ho);
l = ho; l = ho;
l <<= 16; l <<= 16;
l |= (int32)(fr*f); l |= (int32)(fr*f);
*ieee = ((uint64)h << 32) | l; bits = ((uint64)h<<32) | l;
if(exp < -1021) {
// gradual underflow
bits |= 1LL<<52;
bits >>= -1021 - exp;
exp = -1022;
}
bits |= (uint64)(exp+1022L) << 52;
*ieee = bits;
} }
int int

View File

@ -66,12 +66,12 @@ typecheckrange(Node *n)
if(v1->defn == n) if(v1->defn == n)
v1->type = t1; v1->type = t1;
else if(v1->type != T && checkconv(t1, v1->type, 0, &op, &et) < 0) else if(v1->type != T && checkconv(t1, v1->type, 0, &op, &et, "range") < 0)
yyerror("cannot assign type %T to %+N", t1, v1); yyerror("cannot assign type %T to %+N", t1, v1);
if(v2) { if(v2) {
if(v2->defn == n) if(v2->defn == n)
v2->type = t2; v2->type = t2;
else if(v2->type != T && checkconv(t2, v2->type, 0, &op, &et) < 0) else if(v2->type != T && checkconv(t2, v2->type, 0, &op, &et, "range") < 0)
yyerror("cannot assign type %T to %+N", t1, v1); yyerror("cannot assign type %T to %+N", t1, v1);
} }

View File

@ -59,6 +59,12 @@ init1(Node *n, NodeList **out)
print("%S\n", n->sym); print("%S\n", n->sym);
*out = list(*out, n->defn); *out = list(*out, n->defn);
break; break;
case OAS2FUNC:
for(l=n->defn->rlist; l; l=l->next)
init1(l->n, out);
*out = list(*out, n->defn);
break;
} }
} }
n->initorder = 1; n->initorder = 1;

View File

@ -19,8 +19,8 @@
static void implicitstar(Node**); static void implicitstar(Node**);
static int onearg(Node*); static int onearg(Node*);
static int lookdot(Node*, Type*); static int lookdot(Node*, Type*);
static void typecheckaste(int, Type*, NodeList*); static void typecheckaste(int, Type*, NodeList*, char*);
static int exportassignok(Type*); static int exportassignok(Type*, char*);
static Type* lookdot1(Sym *s, Type *t, Type *f); static Type* lookdot1(Sym *s, Type *t, Type *f);
static int nokeys(NodeList*); static int nokeys(NodeList*);
static void typecheckcomplit(Node**); static void typecheckcomplit(Node**);
@ -673,7 +673,7 @@ reswitch:
case ODOTMETH: case ODOTMETH:
n->op = OCALLMETH; n->op = OCALLMETH;
typecheckaste(OCALL, getthisx(t), list1(l->left)); typecheckaste(OCALL, getthisx(t), list1(l->left), "method receiver");
break; break;
default: default:
@ -684,7 +684,7 @@ reswitch:
} }
break; break;
} }
typecheckaste(OCALL, getinargx(t), n->list); typecheckaste(OCALL, getinargx(t), n->list, "function argument");
ok |= Etop; ok |= Etop;
if(t->outtuple == 0) if(t->outtuple == 0)
goto ret; goto ret;
@ -768,7 +768,7 @@ reswitch:
convlit1(&n->left, n->type, 1); convlit1(&n->left, n->type, 1);
if((t = n->left->type) == T || n->type == T) if((t = n->left->type) == T || n->type == T)
goto error; goto error;
n = typecheckconv(n, n->left, n->type, 1); n = typecheckconv(n, n->left, n->type, 1, "conversion");
if(n->type == T) if(n->type == T)
goto error; goto error;
goto ret; goto ret;
@ -960,7 +960,7 @@ reswitch:
typechecklist(n->list, Erv | Efnstruct); typechecklist(n->list, Erv | Efnstruct);
if(curfn->type->outnamed && n->list == nil) if(curfn->type->outnamed && n->list == nil)
goto ret; goto ret;
typecheckaste(ORETURN, getoutargx(curfn->type), n->list); typecheckaste(ORETURN, getoutargx(curfn->type), n->list, "return argument");
goto ret; goto ret;
case OSELECT: case OSELECT:
@ -1206,13 +1206,11 @@ nokeys(NodeList *l)
* check implicit or explicit conversion from node type nt to type t. * check implicit or explicit conversion from node type nt to type t.
*/ */
int int
checkconv(Type *nt, Type *t, int explicit, int *op, int *et) checkconv(Type *nt, Type *t, int explicit, int *op, int *et, char *desc)
{ {
*op = OCONV; *op = OCONV;
*et = 0; *et = 0;
// preexisting error // preexisting error
if(t == T || t->etype == TFORW) if(t == T || t->etype == TFORW)
return 0; return 0;
@ -1229,7 +1227,7 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
} }
if(eqtype(t, nt)) { if(eqtype(t, nt)) {
exportassignok(t); exportassignok(t, desc);
*op = OCONVNOP; *op = OCONVNOP;
if(!explicit || t == nt) if(!explicit || t == nt)
return 0; return 0;
@ -1334,15 +1332,17 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
} }
Node* Node*
typecheckconv(Node *nconv, Node *n, Type *t, int explicit) typecheckconv(Node *nconv, Node *n, Type *t, int explicit, char *desc)
{ {
int et, op; int et, op;
Node *n1; Node *n1;
char *prefix;
convlit1(&n, t, explicit); convlit1(&n, t, explicit);
if(n->type == T) if(n->type == T)
return n; return n;
if(n->op == OLITERAL) if(n->op == OLITERAL)
if(explicit || isideal(n->type)) if(explicit || isideal(n->type))
if(cvttype(t, n->type)) { if(cvttype(t, n->type)) {
@ -1354,12 +1354,17 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
return n1; return n1;
} }
switch(checkconv(n->type, t, explicit, &op, &et)) { prefix = "";
if(desc != nil)
prefix = " in ";
else
desc = "";
switch(checkconv(n->type, t, explicit, &op, &et, desc)) {
case -1: case -1:
if(explicit) if(explicit)
yyerror("cannot convert %+N to type %T", n, t); yyerror("cannot convert %+N to type %T%s%s", n, t, prefix, desc);
else else
yyerror("cannot use %+N as type %T", n, t); yyerror("cannot use %+N as type %T%s%s", n, t, prefix, desc);
return n; return n;
case 0: case 0:
@ -1386,7 +1391,7 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
* typecheck assignment: type list = expression list * typecheck assignment: type list = expression list
*/ */
static void static void
typecheckaste(int op, Type *tstruct, NodeList *nl) typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
{ {
Type *t, *tl, *tn; Type *t, *tl, *tn;
Node *n; Node *n;
@ -1409,8 +1414,8 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
} }
if(isddd(tl->type)) if(isddd(tl->type))
goto out; goto out;
if(checkconv(tn->type, tl->type, 0, &xx, &yy) < 0) if(checkconv(tn->type, tl->type, 0, &xx, &yy, desc) < 0)
yyerror("cannot use type %T as type %T", tn->type, tl->type); yyerror("cannot use type %T as type %T in %s", tn->type, tl->type, desc);
tn = tn->down; tn = tn->down;
} }
if(tn != T) if(tn != T)
@ -1434,7 +1439,7 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
n = nl->n; n = nl->n;
setlineno(nl->n); setlineno(nl->n);
if(n->type != T) if(n->type != T)
nl->n = typecheckconv(nil, n, t, 0); nl->n = typecheckconv(nil, n, t, 0, desc);
nl = nl->next; nl = nl->next;
} }
if(nl != nil) { if(nl != nil) {
@ -1452,13 +1457,17 @@ out:
* an unavailable field. * an unavailable field.
*/ */
static int static int
exportassignok(Type *t) exportassignok(Type *t, char *desc)
{ {
Type *f; Type *f;
Sym *s; Sym *s;
if(t == T) if(t == T)
return 1; return 1;
if(t->trecur)
return 1;
t->trecur = 1;
switch(t->etype) { switch(t->etype) {
default: default:
// most types can't contain others; they're all fine. // most types can't contain others; they're all fine.
@ -1471,22 +1480,34 @@ exportassignok(Type *t)
// s == nil doesn't happen for embedded fields (they get the type symbol). // s == nil doesn't happen for embedded fields (they get the type symbol).
// it only happens for fields in a ... struct. // it only happens for fields in a ... struct.
if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0) { if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0) {
yyerror("implicit assignment of %T field '%s'", t, s->name); char *prefix;
return 0;
prefix = "";
if(desc != nil)
prefix = " in ";
else
desc = "";
yyerror("implicit assignment of %T field '%s'%s%s", t, s->name, prefix, desc);
goto no;
} }
if(!exportassignok(f->type)) if(!exportassignok(f->type, desc))
return 0; goto no;
} }
break; break;
case TARRAY: case TARRAY:
if(t->bound < 0) // slices are pointers; that's fine if(t->bound < 0) // slices are pointers; that's fine
break; break;
if(!exportassignok(t->type)) if(!exportassignok(t->type, desc))
return 0; goto no;
break; break;
} }
t->trecur = 0;
return 1; return 1;
no:
t->trecur = 0;
return 0;
} }
@ -1600,6 +1621,7 @@ typecheckcomplit(Node **np)
Node *l, *n, *hash[101]; Node *l, *n, *hash[101];
NodeList *ll; NodeList *ll;
Type *t, *f; Type *t, *f;
Sym *s;
n = *np; n = *np;
@ -1630,11 +1652,11 @@ typecheckcomplit(Node **np)
} }
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
defaultlit(&l->right, t->type); defaultlit(&l->right, t->type);
l->right = typecheckconv(nil, l->right, t->type, 0); l->right = typecheckconv(nil, l->right, t->type, 0, "array index");
} else { } else {
typecheck(&ll->n, Erv); typecheck(&ll->n, Erv);
defaultlit(&ll->n, t->type); defaultlit(&ll->n, t->type);
ll->n = typecheckconv(nil, ll->n, t->type, 0); ll->n = typecheckconv(nil, ll->n, t->type, 0, "array index");
ll->n = nod(OKEY, nodintconst(i), ll->n); ll->n = nod(OKEY, nodintconst(i), ll->n);
ll->n->left->type = types[TINT]; ll->n->left->type = types[TINT];
ll->n->left->typecheck = 1; ll->n->left->typecheck = 1;
@ -1670,8 +1692,8 @@ typecheckcomplit(Node **np)
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
defaultlit(&l->left, t->down); defaultlit(&l->left, t->down);
defaultlit(&l->right, t->type); defaultlit(&l->right, t->type);
l->left = typecheckconv(nil, l->left, t->down, 0); l->left = typecheckconv(nil, l->left, t->down, 0, "map key");
l->right = typecheckconv(nil, l->right, t->type, 0); l->right = typecheckconv(nil, l->right, t->type, 0, "map value");
keydup(l->left, hash, nelem(hash)); keydup(l->left, hash, nelem(hash));
} }
n->op = OMAPLIT; n->op = OMAPLIT;
@ -1689,7 +1711,10 @@ typecheckcomplit(Node **np)
yyerror("too many values in struct initializer"); yyerror("too many values in struct initializer");
continue; continue;
} }
ll->n = typecheckconv(nil, ll->n, f->type, 0); s = f->sym;
if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0)
yyerror("implicit assignment of %T field '%s' in struct literal", t, s->name);
ll->n = typecheckconv(nil, ll->n, f->type, 0, "field value");
ll->n = nod(OKEY, newname(f->sym), ll->n); ll->n = nod(OKEY, newname(f->sym), ll->n);
ll->n->left->typecheck = 1; ll->n->left->typecheck = 1;
f = f->down; f = f->down;
@ -1706,19 +1731,23 @@ typecheckcomplit(Node **np)
typecheck(&ll->n, Erv); typecheck(&ll->n, Erv);
continue; continue;
} }
if(l->left->sym == S) { s = l->left->sym;
if(s == S) {
yyerror("invalid field name %#N in struct initializer", l->left); yyerror("invalid field name %#N in struct initializer", l->left);
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
continue; continue;
} }
l->left = newname(l->left->sym); l->left = newname(s);
l->left->typecheck = 1; l->left->typecheck = 1;
f = lookdot1(l->left->sym, t, t->type); f = lookdot1(s, t, t->type);
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
if(f == nil) if(f == nil) {
yyerror("unknown %T field '%s' in struct literal", t, s->name);
continue; continue;
fielddup(newname(f->sym), hash, nelem(hash)); }
l->right = typecheckconv(nil, l->right, f->type, 0); s = f->sym;
fielddup(newname(s), hash, nelem(hash));
l->right = typecheckconv(nil, l->right, f->type, 0, "field value");
} }
} }
n->op = OSTRUCTLIT; n->op = OSTRUCTLIT;
@ -1879,7 +1908,7 @@ typecheckas(Node *n)
checkassign(n->left); checkassign(n->left);
typecheck(&n->right, Erv); typecheck(&n->right, Erv);
if(n->left->type != T && n->right && n->right->type != T) if(n->left->type != T && n->right && n->right->type != T)
n->right = typecheckconv(nil, n->right, n->left->type, 0); n->right = typecheckconv(nil, n->right, n->left->type, 0, nil);
if(n->left->defn == n && n->left->ntype == N) { if(n->left->defn == n && n->left->ntype == N) {
defaultlit(&n->right, T); defaultlit(&n->right, T);
n->left->type = n->right->type; n->left->type = n->right->type;
@ -1919,7 +1948,7 @@ typecheckas2(Node *n)
// easy // easy
for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next) { for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next) {
if(ll->n->type != T && lr->n->type != T) if(ll->n->type != T && lr->n->type != T)
lr->n = typecheckconv(nil, lr->n, ll->n->type, 0); lr->n = typecheckconv(nil, lr->n, ll->n->type, 0, nil);
if(ll->n->defn == n && ll->n->ntype == N) { if(ll->n->defn == n && ll->n->ntype == N) {
defaultlit(&lr->n, T); defaultlit(&lr->n, T);
ll->n->type = lr->n->type; ll->n->type = lr->n->type;
@ -1937,9 +1966,9 @@ typecheckas2(Node *n)
if(l->type == T) if(l->type == T)
goto out; goto out;
n->op = OAS2MAPW; n->op = OAS2MAPW;
n->rlist->n = typecheckconv(nil, r, l->type->down, 0); n->rlist->n = typecheckconv(nil, r, l->type->down, 0, nil);
r = n->rlist->next->n; r = n->rlist->next->n;
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0); n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0, nil);
goto out; goto out;
} }
@ -1960,7 +1989,7 @@ typecheckas2(Node *n)
t = structfirst(&s, &r->type); t = structfirst(&s, &r->type);
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
if(ll->n->type != T) if(ll->n->type != T)
if(checkconv(t->type, ll->n->type, 0, &op, &et) < 0) if(checkconv(t->type, ll->n->type, 0, &op, &et, nil) < 0)
yyerror("cannot assign type %T to %+N", t->type, ll->n); yyerror("cannot assign type %T to %+N", t->type, ll->n);
if(ll->n->defn == n && ll->n->ntype == N) if(ll->n->defn == n && ll->n->ntype == N)
ll->n->type = t->type; ll->n->type = t->type;
@ -1984,12 +2013,12 @@ typecheckas2(Node *n)
case ODOTTYPE: case ODOTTYPE:
n->op = OAS2DOTTYPE; n->op = OAS2DOTTYPE;
common: common:
if(l->type != T && checkconv(r->type, l->type, 0, &op, &et) < 0) if(l->type != T && checkconv(r->type, l->type, 0, &op, &et, nil) < 0)
yyerror("cannot assign %+N to %+N", r, l); yyerror("cannot assign %+N to %+N", r, l);
if(l->defn == n) if(l->defn == n)
l->type = r->type; l->type = r->type;
l = n->list->next->n; l = n->list->next->n;
if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0) if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et, nil) < 0)
yyerror("cannot assign bool value to %+N", l); yyerror("cannot assign bool value to %+N", l);
if(l->defn == n && l->ntype == N) if(l->defn == n && l->ntype == N)
l->type = types[TBOOL]; l->type = types[TBOOL];

View File

@ -1922,7 +1922,7 @@ vmatch1(Node *l, Node *r)
/* /*
* isolate all left sides * isolate all left sides
*/ */
if(l == N) if(l == N || r == N)
return 0; return 0;
switch(l->op) { switch(l->op) {
case ONAME: case ONAME:

View File

@ -599,8 +599,13 @@ ieeedtof(Ieee *e)
exp++; exp++;
} }
} }
if(exp <= -126 || exp >= 130) if(-148 <= exp && exp <= -126) {
diag("double fp to single fp overflow"); v |= 1<<23;
v >>= -125 - exp;
exp = -126;
}
else if(exp < -148 || exp >= 130)
diag("double fp to single fp overflow: %.17g", ieeedtod(e));
v |= ((exp + 126) & 0xffL) << 23; v |= ((exp + 126) & 0xffL) << 23;
v |= e->h & 0x80000000L; v |= e->h & 0x80000000L;
return v; return v;
@ -620,14 +625,18 @@ ieeedtod(Ieee *ieeep)
} }
if(ieeep->l == 0 && ieeep->h == 0) if(ieeep->l == 0 && ieeep->h == 0)
return 0; return 0;
exp = (ieeep->h>>20) & ((1L<<11)-1L);
exp -= (1L<<10) - 2L;
fr = ieeep->l & ((1L<<16)-1L); fr = ieeep->l & ((1L<<16)-1L);
fr /= 1L<<16; fr /= 1L<<16;
fr += (ieeep->l>>16) & ((1L<<16)-1L); fr += (ieeep->l>>16) & ((1L<<16)-1L);
fr /= 1L<<16; fr /= 1L<<16;
fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); if(exp == -(1L<<10) - 2L) {
fr += (ieeep->h & (1L<<20)-1L);
exp++;
} else
fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
fr /= 1L<<21; fr /= 1L<<21;
exp = (ieeep->h>>20) & ((1L<<11)-1L);
exp -= (1L<<10) - 2L;
return ldexp(fr, exp); return ldexp(fr, exp);
} }

View File

@ -5,6 +5,7 @@
package math_test package math_test
import ( import (
"fmt";
. "math"; . "math";
"testing"; "testing";
) )
@ -272,3 +273,29 @@ func TestHypot(t *testing.T) {
} }
} }
} }
// Check that math constants are accepted by compiler
// and have right value (assumes strconv.Atof works).
// http://code.google.com/p/go/issues/detail?id=201
type floatTest struct {
val interface{};
name string;
str string;
}
var floatTests = []floatTest{
floatTest{float64(MaxFloat64), "MaxFloat64", "1.7976931348623157e+308"},
floatTest{float64(MinFloat64), "MinFloat64", "5e-324"},
floatTest{float32(MaxFloat32), "MaxFloat32", "3.4028235e+38"},
floatTest{float32(MinFloat32), "MinFloat32", "1e-45"},
}
func TestFloatMinMax(t *testing.T) {
for _, tt := range floatTests {
s := fmt.Sprint(tt.val);
if s != tt.str {
t.Errorf("Sprint(%v) = %s, want %s", tt.name, s, tt.str)
}
}
}

View File

@ -1,4 +1,4 @@
// errchk $G $D/$F.go // errchk $G -e $D/$F.go
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
@ -34,4 +34,12 @@ func main() {
x = y; // ERROR "assignment.*Mutex" x = y; // ERROR "assignment.*Mutex"
_ = x; _ = x;
} }
{
x := sync.Mutex{0, 0}; // ERROR "assignment.*Mutex"
_ = x;
}
{
x := sync.Mutex{key: 0}; // ERROR "(unknown|assignment).*Mutex"
_ = x;
}
} }

15
test/fixedbugs/bug214.go Normal file
View File

@ -0,0 +1,15 @@
// $G $D/$F.go || echo BUG: bug214
// 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.
// Used to crash the compiler.
// http://code.google.com/p/go/issues/detail?id=88
package main
func main() {
x := make(map[int]int, 10);
x[0], x[1] = 2, 6;
}

16
test/fixedbugs/bug215.go Normal file
View File

@ -0,0 +1,16 @@
// 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.
// Used to crash the compiler.
// http://code.google.com/p/go/issues/detail?id=158
package main
type A struct {
a A;
} // ERROR "recursive"
func foo() { new(A).bar() }
func (a A) bar() {}

20
test/fixedbugs/bug216.go Normal file
View File

@ -0,0 +1,20 @@
// $G $D/$F.go || echo BUG: bug216
// 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.
// Used to be rejected
// http://code.google.com/p/go/issues/detail?id=188
package main
func complexSqrt(i int) (int, int) { return 0, 1 }
var re, im = complexSqrt(-1)
func main() {
if re != 0 || im != 1 {
println("BUG: bug216: want 0,-1 have ", re, im)
}
}

15
test/fixedbugs/bug217.go Normal file
View File

@ -0,0 +1,15 @@
// 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.
// Used to crash
// http://code.google.com/p/go/issues/detail?id=204
package main
func () x() // ERROR "no receiver"
func (a b, c d) x() // ERROR "multiple receiver"