]> Cypherpunks repositories - gostls13.git/commitdiff
gc: five bug fixes, one better error.
authorRuss Cox <rsc@golang.org>
Sun, 15 Nov 2009 20:57:09 +0000 (12:57 -0800)
committerRuss Cox <rsc@golang.org>
Sun, 15 Nov 2009 20:57:09 +0000 (12:57 -0800)
* 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

17 files changed:
src/cmd/gc/align.c
src/cmd/gc/const.c
src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/obj.c
src/cmd/gc/range.c
src/cmd/gc/sinit.c
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c
src/cmd/ld/lib.c
src/pkg/math/all_test.go
test/assign.go
test/fixedbugs/bug214.go [new file with mode: 0644]
test/fixedbugs/bug215.go [new file with mode: 0644]
test/fixedbugs/bug216.go [new file with mode: 0644]
test/fixedbugs/bug217.go [new file with mode: 0644]

index ba43fa05ba47db59612a73890ba8c0d718fe0d5e..d1cc9c23b61804ca743d9de2ac76d7e459b4e3c4 100644 (file)
@@ -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);
index 8cc4c247d63fae942ea0a4fbdbd20a7a52dbee8f..b11ab1c7f8f2fcc2050d561f5e98d77e6219d8b5 100644 (file)
@@ -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;
        }
index 3493e37deebc87f6b9bbc5ac6e780412c583964a..ec386f3a0cb808b6d4912967dd35c16aeb30298b 100644 (file)
@@ -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) {
index cf7862e76da16a1ec7ce507f8151e41762c62d87..f5b88ff593d125bc08511399b172b035a7c60024 100644 (file)
@@ -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);
 
 /*
index 79c720a648e7489ab3a678be7fe7f17fa6a87854..921ff1ed46a5444dd8d5874dd91217414293fbeb 100644 (file)
@@ -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);
index 49216b9534b1ba7af1e45852cd5553eaaab43bde..5b6bb1bf3825e53cf2d54aecdbda21d6fe3f340e 100644 (file)
@@ -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
index 393dd6426a3fe054efe428b41e75ef8f8c3ad9b8..758cd4f29b959528903ce7d59cd1b7e84f00db18 100644 (file)
@@ -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);
        }
 
index d25694fb7856a9c5aa09b3840ac07ae031e1f70d..dc95360ee88a63a7215464d8348d38bb65d14669 100644 (file)
@@ -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;
index b87da542554bb3eed67376fbe1a0df896c40215e..108a2d3e9bffbe3044d3f19c57da09120d02a4ad 100644 (file)
@@ -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];
index c2d54d251de2bdee30428f40a3b26cae4c637fb2..6aa23783f58e246efbaee4278e443faaf679507e 100644 (file)
@@ -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:
index 4a518c79b1ed5b046e6e93ec5b04d499aff14555..232916845e061dd971cf603ea1696aa61fc5b83e 100644 (file)
@@ -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);
 }
 
index 8b4299e7e71d29f361859f617c82253d32882eef..09992283754812594bd83f060d4597b2ea074e89 100644 (file)
@@ -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)
+               }
+       }
+}
index ba80c8de510f93c23273e4b226c83af4f3115bbc..842bd62d4d0a28c51e8239a2204410acee4318e7 100644 (file)
@@ -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;
+       }
 }
diff --git a/test/fixedbugs/bug214.go b/test/fixedbugs/bug214.go
new file mode 100644 (file)
index 0000000..502e698
--- /dev/null
@@ -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;
+}
diff --git a/test/fixedbugs/bug215.go b/test/fixedbugs/bug215.go
new file mode 100644 (file)
index 0000000..d58786c
--- /dev/null
@@ -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()       {}
diff --git a/test/fixedbugs/bug216.go b/test/fixedbugs/bug216.go
new file mode 100644 (file)
index 0000000..76f8546
--- /dev/null
@@ -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)
+       }
+}
diff --git a/test/fixedbugs/bug217.go b/test/fixedbugs/bug217.go
new file mode 100644 (file)
index 0000000..98334c4
--- /dev/null
@@ -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"
+