mirror of
https://github.com/golang/go
synced 2024-11-21 23:24:41 -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:
parent
a967f57d19
commit
a338231526
@ -495,10 +495,11 @@ typeinit(void)
|
||||
mpatofix(maxintval[TUINT32], "0xffffffff");
|
||||
mpatofix(maxintval[TUINT64], "0xffffffffffffffff");
|
||||
|
||||
mpatoflt(maxfltval[TFLOAT32], "3.40282347e+38");
|
||||
mpatoflt(minfltval[TFLOAT32], "-3.40282347e+38");
|
||||
mpatoflt(maxfltval[TFLOAT64], "1.7976931348623157e+308");
|
||||
mpatoflt(minfltval[TFLOAT64], "-1.7976931348623157e+308");
|
||||
/* f is valid float if min < f < max. (min and max are not themselves valid.) */
|
||||
mpatoflt(maxfltval[TFLOAT32], "33554431p103"); /* 2^24-1 p (127-23) + 1/2 ulp*/
|
||||
mpatoflt(minfltval[TFLOAT32], "-33554431p103");
|
||||
mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */
|
||||
mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
|
||||
|
||||
/* for walk to use in error messages */
|
||||
types[TFUNC] = functype(N, nil, nil);
|
||||
|
@ -261,8 +261,8 @@ overflow(Val v, Type *t)
|
||||
case CTFLT:
|
||||
if(!isfloat[t->etype])
|
||||
fatal("overflow: %T floating-point constant", t);
|
||||
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) < 0
|
||||
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) > 0)
|
||||
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;
|
||||
}
|
||||
|
@ -302,11 +302,27 @@ NodeList*
|
||||
variter(NodeList *vl, Node *t, NodeList *el)
|
||||
{
|
||||
int doexpr;
|
||||
Node *v, *e;
|
||||
Node *v, *e, *as2;
|
||||
NodeList *init;
|
||||
|
||||
init = 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) {
|
||||
if(doexpr) {
|
||||
if(el == nil) {
|
||||
|
@ -1048,8 +1048,8 @@ void typechecklist(NodeList*, int);
|
||||
void typecheckswitch(Node*);
|
||||
void typecheckselect(Node*);
|
||||
void typecheckrange(Node*);
|
||||
Node* typecheckconv(Node*, Node*, Type*, int);
|
||||
int checkconv(Type*, Type*, int, int*, int*);
|
||||
Node* typecheckconv(Node*, Node*, Type*, int, char*);
|
||||
int checkconv(Type*, Type*, int, int*, int*, char*);
|
||||
Node* typecheck(Node**, int);
|
||||
|
||||
/*
|
||||
|
@ -1087,6 +1087,8 @@ xfndcl:
|
||||
LFUNC fndcl fnbody
|
||||
{
|
||||
$$ = $2;
|
||||
if($$ == N)
|
||||
break;
|
||||
$$->nbody = $3;
|
||||
funcbody($$);
|
||||
}
|
||||
@ -1111,10 +1113,19 @@ fndcl:
|
||||
{
|
||||
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;
|
||||
if($2->next != nil || $2->n->op != ODCLFIELD) {
|
||||
if(rcvr->op != ODCLFIELD) {
|
||||
yyerror("bad receiver in method");
|
||||
rcvr = N;
|
||||
break;
|
||||
}
|
||||
|
||||
$$ = nod(ODCLFUNC, N, N);
|
||||
|
@ -114,6 +114,7 @@ ieeedtod(uint64 *ieee, double native)
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
uint32 h, l;
|
||||
uint64 bits;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
@ -129,13 +130,20 @@ ieeedtod(uint64 *ieee, double native)
|
||||
fr = modf(fr*f, &ho);
|
||||
h = ho;
|
||||
h &= 0xfffffL;
|
||||
h |= (exp+1022L) << 20;
|
||||
f = 65536L;
|
||||
fr = modf(fr*f, &ho);
|
||||
l = ho;
|
||||
l <<= 16;
|
||||
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
|
||||
|
@ -66,12 +66,12 @@ typecheckrange(Node *n)
|
||||
|
||||
if(v1->defn == n)
|
||||
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);
|
||||
if(v2) {
|
||||
if(v2->defn == n)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,12 @@ init1(Node *n, NodeList **out)
|
||||
print("%S\n", n->sym);
|
||||
*out = list(*out, n->defn);
|
||||
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;
|
||||
|
@ -19,8 +19,8 @@
|
||||
static void implicitstar(Node**);
|
||||
static int onearg(Node*);
|
||||
static int lookdot(Node*, Type*);
|
||||
static void typecheckaste(int, Type*, NodeList*);
|
||||
static int exportassignok(Type*);
|
||||
static void typecheckaste(int, Type*, NodeList*, char*);
|
||||
static int exportassignok(Type*, char*);
|
||||
static Type* lookdot1(Sym *s, Type *t, Type *f);
|
||||
static int nokeys(NodeList*);
|
||||
static void typecheckcomplit(Node**);
|
||||
@ -673,7 +673,7 @@ reswitch:
|
||||
|
||||
case ODOTMETH:
|
||||
n->op = OCALLMETH;
|
||||
typecheckaste(OCALL, getthisx(t), list1(l->left));
|
||||
typecheckaste(OCALL, getthisx(t), list1(l->left), "method receiver");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -684,7 +684,7 @@ reswitch:
|
||||
}
|
||||
break;
|
||||
}
|
||||
typecheckaste(OCALL, getinargx(t), n->list);
|
||||
typecheckaste(OCALL, getinargx(t), n->list, "function argument");
|
||||
ok |= Etop;
|
||||
if(t->outtuple == 0)
|
||||
goto ret;
|
||||
@ -768,7 +768,7 @@ reswitch:
|
||||
convlit1(&n->left, n->type, 1);
|
||||
if((t = n->left->type) == T || n->type == T)
|
||||
goto error;
|
||||
n = typecheckconv(n, n->left, n->type, 1);
|
||||
n = typecheckconv(n, n->left, n->type, 1, "conversion");
|
||||
if(n->type == T)
|
||||
goto error;
|
||||
goto ret;
|
||||
@ -960,7 +960,7 @@ reswitch:
|
||||
typechecklist(n->list, Erv | Efnstruct);
|
||||
if(curfn->type->outnamed && n->list == nil)
|
||||
goto ret;
|
||||
typecheckaste(ORETURN, getoutargx(curfn->type), n->list);
|
||||
typecheckaste(ORETURN, getoutargx(curfn->type), n->list, "return argument");
|
||||
goto ret;
|
||||
|
||||
case OSELECT:
|
||||
@ -1206,13 +1206,11 @@ nokeys(NodeList *l)
|
||||
* check implicit or explicit conversion from node type nt to type t.
|
||||
*/
|
||||
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;
|
||||
*et = 0;
|
||||
|
||||
|
||||
|
||||
// preexisting error
|
||||
if(t == T || t->etype == TFORW)
|
||||
return 0;
|
||||
@ -1229,7 +1227,7 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
|
||||
}
|
||||
|
||||
if(eqtype(t, nt)) {
|
||||
exportassignok(t);
|
||||
exportassignok(t, desc);
|
||||
*op = OCONVNOP;
|
||||
if(!explicit || t == nt)
|
||||
return 0;
|
||||
@ -1334,15 +1332,17 @@ checkconv(Type *nt, Type *t, int explicit, int *op, int *et)
|
||||
}
|
||||
|
||||
Node*
|
||||
typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
|
||||
typecheckconv(Node *nconv, Node *n, Type *t, int explicit, char *desc)
|
||||
{
|
||||
int et, op;
|
||||
Node *n1;
|
||||
char *prefix;
|
||||
|
||||
convlit1(&n, t, explicit);
|
||||
if(n->type == T)
|
||||
return n;
|
||||
|
||||
|
||||
if(n->op == OLITERAL)
|
||||
if(explicit || isideal(n->type))
|
||||
if(cvttype(t, n->type)) {
|
||||
@ -1354,12 +1354,17 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
|
||||
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:
|
||||
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
|
||||
yyerror("cannot use %+N as type %T", n, t);
|
||||
yyerror("cannot use %+N as type %T%s%s", n, t, prefix, desc);
|
||||
return n;
|
||||
|
||||
case 0:
|
||||
@ -1386,7 +1391,7 @@ typecheckconv(Node *nconv, Node *n, Type *t, int explicit)
|
||||
* typecheck assignment: type list = expression list
|
||||
*/
|
||||
static void
|
||||
typecheckaste(int op, Type *tstruct, NodeList *nl)
|
||||
typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
|
||||
{
|
||||
Type *t, *tl, *tn;
|
||||
Node *n;
|
||||
@ -1409,8 +1414,8 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
|
||||
}
|
||||
if(isddd(tl->type))
|
||||
goto out;
|
||||
if(checkconv(tn->type, tl->type, 0, &xx, &yy) < 0)
|
||||
yyerror("cannot use type %T as type %T", tn->type, tl->type);
|
||||
if(checkconv(tn->type, tl->type, 0, &xx, &yy, desc) < 0)
|
||||
yyerror("cannot use type %T as type %T in %s", tn->type, tl->type, desc);
|
||||
tn = tn->down;
|
||||
}
|
||||
if(tn != T)
|
||||
@ -1434,7 +1439,7 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
|
||||
n = nl->n;
|
||||
setlineno(nl->n);
|
||||
if(n->type != T)
|
||||
nl->n = typecheckconv(nil, n, t, 0);
|
||||
nl->n = typecheckconv(nil, n, t, 0, desc);
|
||||
nl = nl->next;
|
||||
}
|
||||
if(nl != nil) {
|
||||
@ -1452,13 +1457,17 @@ out:
|
||||
* an unavailable field.
|
||||
*/
|
||||
static int
|
||||
exportassignok(Type *t)
|
||||
exportassignok(Type *t, char *desc)
|
||||
{
|
||||
Type *f;
|
||||
Sym *s;
|
||||
|
||||
if(t == T)
|
||||
return 1;
|
||||
if(t->trecur)
|
||||
return 1;
|
||||
t->trecur = 1;
|
||||
|
||||
switch(t->etype) {
|
||||
default:
|
||||
// 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).
|
||||
// it only happens for fields in a ... struct.
|
||||
if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0) {
|
||||
yyerror("implicit assignment of %T field '%s'", t, s->name);
|
||||
return 0;
|
||||
char *prefix;
|
||||
|
||||
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))
|
||||
return 0;
|
||||
if(!exportassignok(f->type, desc))
|
||||
goto no;
|
||||
}
|
||||
break;
|
||||
|
||||
case TARRAY:
|
||||
if(t->bound < 0) // slices are pointers; that's fine
|
||||
break;
|
||||
if(!exportassignok(t->type))
|
||||
return 0;
|
||||
if(!exportassignok(t->type, desc))
|
||||
goto no;
|
||||
break;
|
||||
}
|
||||
t->trecur = 0;
|
||||
return 1;
|
||||
|
||||
no:
|
||||
t->trecur = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1600,6 +1621,7 @@ typecheckcomplit(Node **np)
|
||||
Node *l, *n, *hash[101];
|
||||
NodeList *ll;
|
||||
Type *t, *f;
|
||||
Sym *s;
|
||||
|
||||
n = *np;
|
||||
|
||||
@ -1630,11 +1652,11 @@ typecheckcomplit(Node **np)
|
||||
}
|
||||
typecheck(&l->right, Erv);
|
||||
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 {
|
||||
typecheck(&ll->n, Erv);
|
||||
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->left->type = types[TINT];
|
||||
ll->n->left->typecheck = 1;
|
||||
@ -1670,8 +1692,8 @@ typecheckcomplit(Node **np)
|
||||
typecheck(&l->right, Erv);
|
||||
defaultlit(&l->left, t->down);
|
||||
defaultlit(&l->right, t->type);
|
||||
l->left = typecheckconv(nil, l->left, t->down, 0);
|
||||
l->right = typecheckconv(nil, l->right, t->type, 0);
|
||||
l->left = typecheckconv(nil, l->left, t->down, 0, "map key");
|
||||
l->right = typecheckconv(nil, l->right, t->type, 0, "map value");
|
||||
keydup(l->left, hash, nelem(hash));
|
||||
}
|
||||
n->op = OMAPLIT;
|
||||
@ -1689,7 +1711,10 @@ typecheckcomplit(Node **np)
|
||||
yyerror("too many values in struct initializer");
|
||||
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->left->typecheck = 1;
|
||||
f = f->down;
|
||||
@ -1706,19 +1731,23 @@ typecheckcomplit(Node **np)
|
||||
typecheck(&ll->n, Erv);
|
||||
continue;
|
||||
}
|
||||
if(l->left->sym == S) {
|
||||
s = l->left->sym;
|
||||
if(s == S) {
|
||||
yyerror("invalid field name %#N in struct initializer", l->left);
|
||||
typecheck(&l->right, Erv);
|
||||
continue;
|
||||
}
|
||||
l->left = newname(l->left->sym);
|
||||
l->left = newname(s);
|
||||
l->left->typecheck = 1;
|
||||
f = lookdot1(l->left->sym, t, t->type);
|
||||
f = lookdot1(s, t, t->type);
|
||||
typecheck(&l->right, Erv);
|
||||
if(f == nil)
|
||||
if(f == nil) {
|
||||
yyerror("unknown %T field '%s' in struct literal", t, s->name);
|
||||
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;
|
||||
@ -1879,7 +1908,7 @@ typecheckas(Node *n)
|
||||
checkassign(n->left);
|
||||
typecheck(&n->right, Erv);
|
||||
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) {
|
||||
defaultlit(&n->right, T);
|
||||
n->left->type = n->right->type;
|
||||
@ -1919,7 +1948,7 @@ typecheckas2(Node *n)
|
||||
// easy
|
||||
for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next) {
|
||||
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) {
|
||||
defaultlit(&lr->n, T);
|
||||
ll->n->type = lr->n->type;
|
||||
@ -1937,9 +1966,9 @@ typecheckas2(Node *n)
|
||||
if(l->type == T)
|
||||
goto out;
|
||||
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;
|
||||
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0);
|
||||
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0, nil);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1960,7 +1989,7 @@ typecheckas2(Node *n)
|
||||
t = structfirst(&s, &r->type);
|
||||
for(ll=n->list; ll; ll=ll->next) {
|
||||
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);
|
||||
if(ll->n->defn == n && ll->n->ntype == N)
|
||||
ll->n->type = t->type;
|
||||
@ -1984,12 +2013,12 @@ typecheckas2(Node *n)
|
||||
case ODOTTYPE:
|
||||
n->op = OAS2DOTTYPE;
|
||||
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);
|
||||
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(types[TBOOL], l->type, 0, &op, &et, nil) < 0)
|
||||
yyerror("cannot assign bool value to %+N", l);
|
||||
if(l->defn == n && l->ntype == N)
|
||||
l->type = types[TBOOL];
|
||||
|
@ -1922,7 +1922,7 @@ vmatch1(Node *l, Node *r)
|
||||
/*
|
||||
* isolate all left sides
|
||||
*/
|
||||
if(l == N)
|
||||
if(l == N || r == N)
|
||||
return 0;
|
||||
switch(l->op) {
|
||||
case ONAME:
|
||||
|
@ -599,8 +599,13 @@ ieeedtof(Ieee *e)
|
||||
exp++;
|
||||
}
|
||||
}
|
||||
if(exp <= -126 || exp >= 130)
|
||||
diag("double fp to single fp overflow");
|
||||
if(-148 <= exp && exp <= -126) {
|
||||
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 |= e->h & 0x80000000L;
|
||||
return v;
|
||||
@ -620,14 +625,18 @@ ieeedtod(Ieee *ieeep)
|
||||
}
|
||||
if(ieeep->l == 0 && ieeep->h == 0)
|
||||
return 0;
|
||||
exp = (ieeep->h>>20) & ((1L<<11)-1L);
|
||||
exp -= (1L<<10) - 2L;
|
||||
fr = ieeep->l & ((1L<<16)-1L);
|
||||
fr /= 1L<<16;
|
||||
fr += (ieeep->l>>16) & ((1L<<16)-1L);
|
||||
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;
|
||||
exp = (ieeep->h>>20) & ((1L<<11)-1L);
|
||||
exp -= (1L<<10) - 2L;
|
||||
return ldexp(fr, exp);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
package math_test
|
||||
|
||||
import (
|
||||
"fmt";
|
||||
. "math";
|
||||
"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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// errchk $G $D/$F.go
|
||||
// errchk $G -e $D/$F.go
|
||||
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
@ -34,4 +34,12 @@ func main() {
|
||||
x = y; // ERROR "assignment.*Mutex"
|
||||
_ = 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
15
test/fixedbugs/bug214.go
Normal 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
16
test/fixedbugs/bug215.go
Normal 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
20
test/fixedbugs/bug216.go
Normal 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
15
test/fixedbugs/bug217.go
Normal 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"
|
||||
|
Loading…
Reference in New Issue
Block a user