]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime: turn run time errors checks into panics
authorRuss Cox <rsc@golang.org>
Fri, 2 Apr 2010 05:31:27 +0000 (22:31 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 2 Apr 2010 05:31:27 +0000 (22:31 -0700)
R=ken2, r
CC=golang-dev
https://golang.org/cl/871042

29 files changed:
src/cmd/5g/cgen.c
src/cmd/5g/gg.h
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/ggen.c
src/cmd/6g/gsubr.c
src/cmd/6g/reg.c
src/cmd/8g/cgen.c
src/cmd/8g/gg.h
src/cmd/8g/ggen.c
src/cmd/8g/reg.c
src/cmd/cov/main.c
src/cmd/gc/builtin.c.boot
src/cmd/gc/print.c
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/runtime/complex.c
src/pkg/runtime/error.go
src/pkg/runtime/hashmap.c
src/pkg/runtime/iface.c
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h
src/pkg/runtime/slice.c
src/pkg/runtime/string.cgo
test/golden.out
test/recover.go
test/recover2.go [new file with mode: 0644]

index ce931600ec0719315c1a955e6f14379ede30cbec..cf701a50a0cc948f6313dfcbba9ab10397649e57 100644 (file)
@@ -573,7 +573,7 @@ agen(Node *n, Node *res)
                                        regfree(&n4);
                                        regfree(&n5);
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-                                       ginscall(throwindex, 0);
+                                       ginscall(panicindex, 0);
                                        patch(p1, pc);
                                }
 
@@ -627,7 +627,7 @@ agen(Node *n, Node *res)
                        gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
                        regfree(&n4);
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-                       ginscall(throwindex, 0);
+                       ginscall(panicindex, 0);
                        patch(p1, pc);
                }
 
index 6477452b92f1e4eb07a52203dae4a37fbaef956e..c62efeb6cef0eb4aad1c2125ed751be9df76214a 100644 (file)
@@ -60,8 +60,8 @@ EXTERN        Node*   curfn;
 EXTERN Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
-EXTERN Node*   throwindex;
-EXTERN Node*   throwslice;
+EXTERN Node*   panicindex;
+EXTERN Node*   panicslice;
 EXTERN Node*   throwreturn;
 EXTERN long    unmappedzero;
 EXTERN int     maxstksize;
index 5831d597e4dbbabf8eb208c9f403866700a7de7a..3243bb86343c4464b0ca6f7084577b22fac5f249 100644 (file)
@@ -23,8 +23,8 @@ compile(Node *fn)
                newproc = sysfunc("newproc");
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
-               throwindex = sysfunc("throwindex");
-               throwslice = sysfunc("throwslice");
+               panicindex = sysfunc("panicindex");
+               panicslice = sysfunc("panicslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -142,8 +142,8 @@ ginscall(Node *f, int proc)
                afunclit(&p->to);
                break;
 
-       // TODO(kaib): unify newproc and defer if you can figure out how not to break things
        case 1: // call in new proc (go)
+       case 2: // deferred call (defer)
                regalloc(&r, types[tptr], N);
                p = gins(AMOVW, N, &r);
                p->from.type = D_OREG;
@@ -173,71 +173,23 @@ ginscall(Node *f, int proc)
                p->to.offset = 4;
                regfree(&r);
 
-               ginscall(newproc, 0);
-
-               regalloc(&r, types[tptr], N);
-               p = gins(AMOVW, N, &r);
-               p->from.type = D_OREG;
-               p->from.reg = REGSP;
-               p->from.offset = 0;
-
-               p = gins(AMOVW, &r, N);
-               p->to.type = D_OREG;
-               p->to.reg = REGSP;
-               p->to.offset = 12;
-               p->scond |= C_WBIT;
-               regfree(&r);
-
-               break;
+               if(proc == 1)
+                       ginscall(newproc, 0);
+               else
+                       ginscall(deferproc, 0);
 
-       case 2: // deferred call (defer)
-               regalloc(&r, types[tptr], N);
-               p = gins(AMOVW, N, &r);
-               p->from.type = D_OREG;
+               nodreg(&r, types[tptr], 1);
+               p = gins(AMOVW, N, N);
+               p->from.type = D_CONST;
                p->from.reg = REGSP;
-               
-               p = gins(AMOVW, &r, N);
-               p->to.type = D_OREG;
+               p->from.offset = 12;
                p->to.reg = REGSP;
-               p->to.offset = -8;
-               p->scond |= C_WBIT;
+               p->to.type = D_REG;
 
-               memset(&n1, 0, sizeof n1);
-               n1.op = OADDR;
-               n1.left = f;
-               gins(AMOVW, &n1, &r);
-
-               p = gins(AMOVW, &r, N);
-               p->to.type = D_OREG;
-               p->to.reg = REGSP;
-               p->to.offset = 8;
-
-               nodconst(&con, types[TINT32], argsize(f->type));
-               gins(AMOVW, &con, &r);
-               p = gins(AMOVW, &r, N);
-               p->to.type = D_OREG;
-               p->to.reg = REGSP;
-               p->to.offset = 4;
-               regfree(&r);
-
-               ginscall(deferproc, 0);
-
-               nodreg(&r, types[tptr], D_R1);
-               p = gins(AMOVW, N, &r);
-               p->from.type = D_OREG;
-               p->from.reg = REGSP;
-               p->from.offset = 0;
-
-               p = gins(AMOVW, &r, N);
-               p->to.type = D_OREG;
-               p->to.reg = REGSP;
-               p->to.offset = 8;
-               p->scond |= C_WBIT;
-               
                if(proc == 2) {
                        nodconst(&con, types[TINT32], 0);
-                       nodreg(&r, types[tptr], D_R0);
-                       gins(ACMP, &con, &r);
+                       p = gins(ACMP, &con, N);
+                       p->reg = 0;
                        patch(gbranch(ABNE, T), pret);
                }
                break;
@@ -773,7 +725,7 @@ cmpandthrow(Node *nl, Node *nr)
                        if(cl > cr) {
                                if(throwpc == nil) {
                                        throwpc = pc;
-                                       ginscall(throwslice, 0);
+                                       ginscall(panicslice, 0);
                                } else
                                        patch(gbranch(AB, T), throwpc);
                        }
@@ -807,7 +759,7 @@ cmpandthrow(Node *nl, Node *nr)
        if(throwpc == nil) {
                p1 = gbranch(optoas(op, types[TUINT32]), T);
                throwpc = pc;
-               ginscall(throwslice, 0);
+               ginscall(panicslice, 0);
                patch(p1, pc);
        } else {
                op = brcom(op);
index ad9cad67e05dd2d0c14d7061b83d094279156ecf..ef78157472672264dbbf9352bbdf2c616702610c 100644 (file)
@@ -1724,7 +1724,7 @@ oindex:
                gcmp(optoas(OCMP, types[TUINT32]), reg1, &n3);
                regfree(&n3);
                p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-               ginscall(throwindex, 0);
+               ginscall(panicindex, 0);
                patch(p1, pc);
        }
 
@@ -1780,7 +1780,7 @@ oindex_const:
                        regfree(&n4);
                        regfree(&n3);
                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-                       ginscall(throwindex, 0);
+                       ginscall(panicindex, 0);
                        patch(p1, pc);
                }
 
index 05e36d2a75a05d4a02d4d3fb3f10b6993b971f94..30c1904290eea6dc9e75aa24affe494faa8e9a10 100644 (file)
@@ -527,7 +527,7 @@ agen(Node *n, Node *res)
                                        nodconst(&n2, types[TUINT64], v);
                                        gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-                                       ginscall(throwindex, 0);
+                                       ginscall(panicindex, 0);
                                        patch(p1, pc);
                                }
 
@@ -573,7 +573,7 @@ agen(Node *n, Node *res)
                                nodconst(&n1, types[TUINT64], nl->type->bound);
                        gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-                       ginscall(throwindex, 0);
+                       ginscall(panicindex, 0);
                        patch(p1, pc);
                }
 
index 34b28c05746d1fe98b95acec369e7c74297a2c87..875c77358888c5c9b816dbe9c165885c0adebb80 100644 (file)
@@ -54,8 +54,8 @@ EXTERN        Node*   curfn;
 EXTERN Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
-EXTERN Node*   throwindex;
-EXTERN Node*   throwslice;
+EXTERN Node*   panicindex;
+EXTERN Node*   panicslice;
 EXTERN Node*   throwreturn;
 EXTERN vlong   unmappedzero;
 
index 10cd5829373e03cd4c52f059bed3b7cb10061167..a92d945724227773e1e459efb4e991d82d4d6e86 100644 (file)
@@ -23,8 +23,8 @@ compile(Node *fn)
                newproc = sysfunc("newproc");
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
-               throwindex = sysfunc("throwindex");
-               throwslice = sysfunc("throwslice");
+               panicindex = sysfunc("panicindex");
+               panicslice = sysfunc("panicslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -1119,7 +1119,7 @@ cmpandthrow(Node *nl, Node *nr)
                        if(cl > cr) {
                                if(throwpc == nil) {
                                        throwpc = pc;
-                                       ginscall(throwslice, 0);
+                                       ginscall(panicslice, 0);
                                } else
                                        patch(gbranch(AJMP, T), throwpc);
                        }
@@ -1137,7 +1137,7 @@ cmpandthrow(Node *nl, Node *nr)
        if(throwpc == nil) {
                p1 = gbranch(optoas(op, types[TUINT32]), T);
                throwpc = pc;
-               ginscall(throwslice, 0);
+               ginscall(panicslice, 0);
                patch(p1, pc);
        } else {
                op = brcom(op);
index c5f4dbe451205b0869fa5bae6d448623341d7852..e9ad6c09467ab204e035090e5ee632c7675374b7 100644 (file)
@@ -1867,7 +1867,7 @@ oindex:
                }
                gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
                p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-               ginscall(throwindex, 0);
+               ginscall(panicindex, 0);
                patch(p1, pc);
        }
 
@@ -1924,7 +1924,7 @@ oindex_const:
                        nodconst(&n2, types[TUINT64], v);
                        gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-                       ginscall(throwindex, 0);
+                       ginscall(panicindex, 0);
                        patch(p1, pc);
                }
 
@@ -1958,7 +1958,7 @@ oindex_const_sudo:
                p1 = gins(optoas(OCMP, types[TUINT32]), N, &n2);
                p1->from = *a;
                p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-               ginscall(throwindex, 0);
+               ginscall(panicindex, 0);
                patch(p1, pc);
                a->offset -= Array_nel;
        }
index c8dd9a3ee1d337790a14c5e84b5fce623b1dcfaf..10a00b38df9b157a22b8453e50973c4024f70beb 100644 (file)
@@ -1555,10 +1555,10 @@ noreturn(Prog *p)
        int i;
 
        if(symlist[0] == S) {
-               symlist[0] = pkglookup("throwindex", runtimepkg);
-               symlist[1] = pkglookup("throwslice", runtimepkg);
+               symlist[0] = pkglookup("panicindex", runtimepkg);
+               symlist[1] = pkglookup("panicslice", runtimepkg);
                symlist[2] = pkglookup("throwinit", runtimepkg);
-               symlist[3] = pkglookup("panicl", runtimepkg);
+               symlist[3] = pkglookup("panic", runtimepkg);
        }
 
        s = p->to.sym;
index 6a21225072ed1bf54f1aabe0229dcdb21a70f222..d7a5ab33ab22948ce2b63886b997aa3d20222689 100644 (file)
@@ -549,7 +549,7 @@ agen(Node *n, Node *res)
                                        nodconst(&n2, types[TUINT32], v);
                                        gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-                                       ginscall(throwindex, 0);
+                                       ginscall(panicindex, 0);
                                        patch(p1, pc);
                                }
 
@@ -595,7 +595,7 @@ agen(Node *n, Node *res)
                                nodconst(&n1, types[TUINT32], nl->type->bound);
                        gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-                       ginscall(throwindex, 0);
+                       ginscall(panicindex, 0);
                        patch(p1, pc);
                }
 
index fcef11c3e18059d6f3be6780b79d53919f917498..a00d69711c223b28cef8bf28851518a9fb5be5e4 100644 (file)
@@ -64,8 +64,8 @@ EXTERN        Node*   curfn;
 EXTERN Node*   newproc;
 EXTERN Node*   deferproc;
 EXTERN Node*   deferreturn;
-EXTERN Node*   throwindex;
-EXTERN Node*   throwslice;
+EXTERN Node*   panicindex;
+EXTERN Node*   panicslice;
 EXTERN Node*   throwreturn;
 EXTERN int     maxstksize;
 extern uint32  unmappedzero;
index 193058e206d22698178d96909c2d69deaf190b33..c1cad74bee18defb4c6dbfa27d0155e3b808244c 100644 (file)
@@ -23,8 +23,8 @@ compile(Node *fn)
                newproc = sysfunc("newproc");
                deferproc = sysfunc("deferproc");
                deferreturn = sysfunc("deferreturn");
-               throwindex = sysfunc("throwindex");
-               throwslice = sysfunc("throwslice");
+               panicindex = sysfunc("panicindex");
+               panicslice = sysfunc("panicslice");
                throwreturn = sysfunc("throwreturn");
        }
 
@@ -824,7 +824,7 @@ cmpandthrow(Node *nl, Node *nr)
                        if(cl > cr) {
                                if(throwpc == nil) {
                                        throwpc = pc;
-                                       ginscall(throwslice, 0);
+                                       ginscall(panicslice, 0);
                                } else
                                        patch(gbranch(AJMP, T), throwpc);
                        }
@@ -842,7 +842,7 @@ cmpandthrow(Node *nl, Node *nr)
        if(throwpc == nil) {
                p1 = gbranch(optoas(op, types[TUINT32]), T);
                throwpc = pc;
-               ginscall(throwslice, 0);
+               ginscall(panicslice, 0);
                patch(p1, pc);
        } else {
                op = brcom(op);
index 50f47d9ca2f10b106e0a70ca1828b210cb292a3d..e23205c68faba4788a0a5316280a2e4098ccc952 100644 (file)
@@ -1447,10 +1447,10 @@ noreturn(Prog *p)
        int i;
 
        if(symlist[0] == S) {
-               symlist[0] = pkglookup("throwindex", runtimepkg);
-               symlist[1] = pkglookup("throwslice", runtimepkg);
+               symlist[0] = pkglookup("panicindex", runtimepkg);
+               symlist[1] = pkglookup("panicslice", runtimepkg);
                symlist[2] = pkglookup("throwinit", runtimepkg);
-               symlist[3] = pkglookup("panicl", runtimepkg);
+               symlist[3] = pkglookup("panic", runtimepkg);
        }
 
        s = p->to.sym;
index 899d8163f40b0342208a8b4c0737644ee8b1a9ee..1b3138a7f4472ee649b1bd737ddaae82d7cfbe75 100644 (file)
@@ -201,10 +201,10 @@ missing(uvlong pc, uvlong epc)
        }
 
        if(epc - pc == 5) {
-               // check for CALL sys.throwindex
+               // check for CALL sys.panicindex
                buf[0] = 0;
                machdata->das(text, pc, 0, buf, sizeof buf);
-               if(strstr(buf, "throwindex"))
+               if(strstr(buf, "panicindex"))
                        return;
        }
 
index 59a917a9aea6c65ce474aa7f405aa19910e63608..94efa412bf4c4f5bc3e054d4a159d64dadacca91 100644 (file)
@@ -1,7 +1,8 @@
 char *runtimeimport =
        "package runtime\n"
        "func \"\".mal (? int32) *any\n"
-       "func \"\".throwindex ()\n"
+       "func \"\".panicindex ()\n"
+       "func \"\".panicslice ()\n"
        "func \"\".throwreturn ()\n"
        "func \"\".throwinit ()\n"
        "func \"\".panic (? interface { })\n"
index 79c0e3720ffa3f590b2fd5a62fb5236724f7d1ec..f9799c5231c8b0eb829793ef120e18e6f65993da 100644 (file)
@@ -276,7 +276,10 @@ exprfmt(Fmt *f, Node *n, int prec)
        case ODOTTYPE:
                exprfmt(f, n->left, 7);
                fmtprint(f, ".(");
-               exprfmt(f, n->right, 0);
+               if(n->right != N)
+                       exprfmt(f, n->right, 0);
+               else
+                       fmtprint(f, "%T", n->type);
                fmtprint(f, ")");
                break;
 
index ba79ab92d345161c9725145debcf7f906fd8d80e..e08e1f601743f37ced5a69570c5a5c5cdb900bfb 100644 (file)
@@ -11,7 +11,8 @@ package PACKAGE
 // emitted by compiler, not referred to by go programs
 
 func mal(int32) *any
-func throwindex()
+func panicindex()
+func panicslice()
 func throwreturn()
 func throwinit()
 
index 37b5efa6f83561314dcb42155980c92fbe049f0c..ced798e6ba182f8b3c784b1cf8a50692cb4d11a2 100644 (file)
@@ -1846,8 +1846,6 @@ walkprint(Node *nn, NodeList **init, int defer)
        if(defer) {
                if(op == OPRINTN)
                        fmtprint(&fmt, "\n");
-               if(op == OPANIC)
-                       fmtprint(&fmt, "%%!");
                on = syslook("printf", 1);
                on->type = functype(nil, intypes, nil);
                args->n = nod(OLITERAL, N, N);
@@ -1863,10 +1861,7 @@ walkprint(Node *nn, NodeList **init, int defer)
                typechecklist(calls, Etop);
                walkexprlist(calls, init);
 
-               if(op == OPANIC)
-                       r = mkcall("panicl", T, nil);
-               else
-                       r = nod(OEMPTY, N, N);
+               r = nod(OEMPTY, N, N);
                typecheck(&r, Etop);
                walkexpr(&r, init);
                r->ninit = calls;
index 72c65467d4af39c57d5dd45a2f0d2abfe06d0c21..ca6ed79ba390a10ca4424db17aacf2bf4a1b070d 100644 (file)
@@ -20,7 +20,7 @@ void
                b = -b;
        if(a <= b) {
                if(b == 0)
-                       throw("complex divide");
+                       panicstring("complex divide by zero");
                ratio = denreal/denimag;
                denom = denreal*ratio + denimag;
                quoreal = (numreal*ratio + numimag) / denom;
index a7d3bedb9ccce4042926d265d44794485cc642f7..673e77b2c12a471e1150e6d5ab7e1dfeeceb29f5 100644 (file)
@@ -7,7 +7,12 @@ package runtime
 // The Error interface identifies a run time error.
 type Error interface {
        String() string
-       RuntimeError() // no-op that uniquely identifies runtime.Error
+
+       // RuntimeError is a no-op function but
+       // serves to distinguish types that are runtime
+       // errors from ordinary os.Errors: a type is a
+       // runtime error if it has a RuntimeError method.
+       RuntimeError()
 }
 
 // A TypeAssertionError explains a failed type assertion.
@@ -21,6 +26,8 @@ type TypeAssertionError struct {
        missingMethod   string // one method needed by Interface, missing from Concrete
 }
 
+func (*TypeAssertionError) RuntimeError() {}
+
 func (e *TypeAssertionError) String() string {
        inter := e.interfaceString
        if inter == "" {
@@ -57,8 +64,6 @@ func (e *TypeAssertionError) MissingMethod() string {
        return e.missingMethod
 }
 
-func (*TypeAssertionError) RuntimeError() {}
-
 // For calling from C.
 func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) {
        var t1, t2, t3 Type
@@ -88,12 +93,26 @@ func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *st
        *ret = &TypeAssertionError{t1, t2, t3, s1, s2, s3, meth}
 }
 
+// An errorString represents a runtime error described by a single string.
+type errorString string
+
+func (e errorString) RuntimeError() {}
+
+func (e errorString) String() string {
+       return "runtime error: " + string(e)
+}
+
+// For calling from C.
+func newErrorString(s string, ret *interface{}) {
+       *ret = errorString(s)
+}
+
 type stringer interface {
        String() string
 }
 
 // For calling from C.
-// Prints an argument to panic.
+// Prints an argument passed to panic.
 // There's room for arbitrary complexity here, but we keep it
 // simple and handle just a few important cases: int, string, and Stringer.
 func printany(i interface{}) {
index ccb5cfdb56d2ce992c805231161448b281613d96..f27264b6826b21a10305f7b973b4492c5571b3e3 100644 (file)
@@ -770,10 +770,6 @@ void
 
        mapaccess(h, ak, av, &pres);
 
-// new spec -- all elements have "zero" value
-//     if(!pres)
-//             throw("runtime.mapaccess1: key not in map");
-
        if(debug) {
                prints("runtime.mapaccess1: map=");
                ·printpointer(h);
index 1af7ca7f568790c607e66d963975c9e9b778cc01..28e3edeeef9c750e54e5d59443a7016f95b8849f 100644 (file)
@@ -457,6 +457,7 @@ static uintptr
 ifacehash1(void *data, Type *t)
 {
        int32 alg, wid;
+       Eface err;
 
        if(t == nil)
                return 0;
@@ -464,12 +465,10 @@ ifacehash1(void *data, Type *t)
        alg = t->alg;
        wid = t->size;
        if(algarray[alg].hash == nohash) {
-               // calling nohash will throw too,
+               // calling nohash will panic too,
                // but we can print a better error.
-               printf("hash of unhashable type %S\n", *t->string);
-               if(alg == AFAKE)
-                       throw("fake interface hash");
-               throw("interface hash");
+               ·newErrorString(catstring(gostring((byte*)"hash of unhashable type "), *t->string), &err);
+               ·panic(err);
        }
        if(wid <= sizeof(data))
                return algarray[alg].hash(wid, &data);
@@ -494,17 +493,16 @@ static bool
 ifaceeq1(void *data1, void *data2, Type *t)
 {
        int32 alg, wid;
+       Eface err;
 
        alg = t->alg;
        wid = t->size;
 
        if(algarray[alg].equal == noequal) {
-               // calling noequal will throw too,
+               // calling noequal will panic too,
                // but we can print a better error.
-               printf("comparing uncomparable type %S\n", *t->string);
-               if(alg == AFAKE)
-                       throw("fake interface compare");
-               throw("interface compare");
+               ·newErrorString(catstring(gostring((byte*)"comparing uncomparable type "), *t->string), &err);
+               ·panic(err);
        }
 
        if(wid <= sizeof(data1))
index 02509deb69726017fed2c774a270037078198a2f..27c59218c730306216d0ba20b7d02234d7364dbe 100644 (file)
@@ -42,27 +42,29 @@ panic(int32 unused)
 }
 
 void
throwindex(void)
panicindex(void)
 {
-       throw("index out of range");
+       panicstring("index out of range");
 }
 
 void
throwslice(void)
panicslice(void)
 {
-       throw("slice out of range");
+       panicstring("slice bounds out of range");
 }
 
 void
 ·throwreturn(void)
 {
-       throw("no return at end of a typed function");
+       // can only happen if compiler is broken
+       throw("no return at end of a typed function - compiler is broken");
 }
 
 void
 ·throwinit(void)
 {
-       throw("recursive call during initialization");
+       // can only happen with linker skew
+       throw("recursive call during initialization - linker skew");
 }
 
 void
@@ -75,6 +77,15 @@ throw(int8 *s)
        exit(1);        // even more not reached
 }
 
+void
+panicstring(int8 *s)
+{
+       Eface err;
+       
+       ·newErrorString(gostring((byte*)s), &err);
+       ·panic(err);
+}
+
 void
 mcpy(byte *t, byte *f, uint32 n)
 {
@@ -421,7 +432,7 @@ nohash(uint32 s, void *a)
 {
        USED(s);
        USED(a);
-       throw("hash of unhashable type");
+       panicstring("hash of unhashable type");
        return 0;
 }
 
@@ -431,27 +442,10 @@ noequal(uint32 s, void *a, void *b)
        USED(s);
        USED(a);
        USED(b);
-       throw("comparing uncomparable types");
+       panicstring("comparing uncomparable types");
        return 0;
 }
 
-static void
-noprint(uint32 s, void *a)
-{
-       USED(s);
-       USED(a);
-       throw("print of unprintable type");
-}
-
-static void
-nocopy(uint32 s, void *a, void *b)
-{
-       USED(s);
-       USED(a);
-       USED(b);
-       throw("copy of uncopyable type");
-}
-
 Alg
 algarray[] =
 {
@@ -460,7 +454,6 @@ algarray[] =
 [ASTRING]      { strhash, strequal, strprint, memcopy },
 [AINTER]               { interhash, interequal, interprint, memcopy },
 [ANILINTER]    { nilinterhash, nilinterequal, nilinterprint, memcopy },
-[AFAKE]        { nohash, noequal, noprint, nocopy },
 };
 
 #pragma textflag 7
index b4011b7588adcaaefca29df8a07b5e8509ab6b4c..415dddb867c0cef7fe234c7f2f2bf00d348cff1b 100644 (file)
@@ -300,7 +300,6 @@ enum
        ASTRING,
        AINTER,
        ANILINTER,
-       AFAKE,
        Amax
 };
 
@@ -369,6 +368,7 @@ void        goargs(void);
 void   FLUSH(void*);
 void*  getu(void);
 void   throw(int8*);
+void   panicstring(int8*);
 uint32 rnd(uint32, uint32);
 void   prints(int8*);
 void   printf(int8*, ...);
@@ -379,6 +379,7 @@ void        memmove(void*, void*, uint32);
 void*  mal(uintptr);
 void*  malx(uintptr size, int32 skip_delta);
 uint32 cmpstring(String, String);
+String catstring(String, String);
 String gostring(byte*);
 String gostringw(uint16*);
 void   initsig(void);
@@ -416,6 +417,7 @@ void        free(void *v);
 void   addfinalizer(void*, void(*fn)(void*), int32);
 void   walkfintab(void (*fn)(void*));
 void   runpanic(Panic*);
+void*  getcallersp(void*);
 
 void   exit(int32);
 void   breakpoint(void);
@@ -531,13 +533,15 @@ void      runtime_printslice(Slice);
 void   runtime_printcomplex(Complex128);
 void   reflect·call(byte*, byte*, uint32);
 void   ·panic(Eface);
-
+void   ·panicindex(void);
+void   ·panicslice(void);
 /*
  * runtime c-called (but written in Go)
  */
 void ·newError(String, Eface*);
 void   ·printany(Eface);
 void   ·newTypeAssertionError(Type*, Type*, Type*, String*, String*, String*, String*, Eface*);
+void   ·newErrorString(String, Eface*);
 
 /*
  * wrapped for go users
index 03572e822bc8a3a23b53dfb2e00f5d820c412af1..ca2585c796192a87c4bb79aac1f2ba546d573da6 100644 (file)
@@ -36,19 +36,6 @@ void
        }
 }
 
-static void
-throwslice(uint32 lb, uint32 hb, uint32 n)
-{
-       prints("slice[");
-       ·printint(lb);
-       prints(":");
-       ·printint(hb);
-       prints("] of [");
-       ·printint(n);
-       prints("] array\n");
-       throw("array slice");
-}
-
 // sliceslice(old []any, lb int, hb int, width int) (ary []any);
 void
 ·sliceslice(Slice old, uint32 lb, uint32 hb, uint32 width, Slice ret)
@@ -71,7 +58,7 @@ void
                        ·printint(old.cap);
                        prints("\n");
                }
-               throwslice(lb, hb, old.cap);
+               ·panicslice();
        }
 
        // new array is inside old array
@@ -116,7 +103,7 @@ void
                        ·printint(old.cap);
                        prints("\n");
                }
-               throwslice(lb, old.len, old.cap);
+               ·panicslice();
        }
 
        // new array is inside old array
@@ -165,7 +152,7 @@ void
                        ·printint(width);
                        prints("\n");
                }
-               throwslice(lb, hb, nel);
+               ·panicslice();
        }
 
        // new array is inside old array
index 4a96b83ec023e1c6c86689d79b1518c1666ecb47..005b0ffc80c0892e1c1ff0d390803a4dce4830b9 100644 (file)
@@ -78,34 +78,25 @@ gostringw(uint16 *str)
        return s;
 }
 
-func catstring(s1 String, s2 String) (s3 String) {
-       if(s1.len == 0) {
-               s3 = s2;
-               goto out;
-       }
-       if(s2.len == 0) {
-               s3 = s1;
-               goto out;
-       }
+String
+catstring(String s1, String s2)
+{
+       String s3;
+
+       if(s1.len == 0)
+               return s2;
+       if(s2.len == 0)
+               return s1;
 
        s3 = gostringsize(s1.len + s2.len);
        mcpy(s3.str, s1.str, s1.len);
        mcpy(s3.str+s1.len, s2.str, s2.len);
-out:
+       return s3;
 }
 
-static void
-prbounds(int8* s, int32 a, int32 b, int32 c)
-{
-       prints(s);
-       prints(" ");
-       ·printint(a);
-       prints("<");
-       ·printint(b);
-       prints(">");
-       ·printint(c);
-       prints("\n");
-       throw("string bounds");
+
+func catstring(s1 String, s2 String) (s3 String) {
+       s3 = catstring(s1, s2);
 }
 
 uint32
@@ -159,9 +150,7 @@ func slicestring(si String, lindex int32, hindex int32) (so String) {
 
        if(lindex < 0 || lindex > si.len ||
           hindex < lindex || hindex > si.len) {
-               ·printpc(&si);
-               prints(" ");
-               prbounds("slice", lindex, si.len, hindex);
+               ·panicslice();
        }
 
        l = hindex-lindex;
@@ -177,9 +166,7 @@ func slicestring1(si String, lindex int32) (so String) {
        int32 l;
 
        if(lindex < 0 || lindex > si.len) {
-               ·printpc(&si);
-               prints(" ");
-               prbounds("slice", lindex, si.len, si.len);
+               ·panicslice();
        }
 
        l = si.len-lindex;
@@ -193,9 +180,7 @@ func slicestring1(si String, lindex int32) (so String) {
 
 func indexstring(s String, i int32) (b byte) {
        if(i < 0 || i >= s.len) {
-               ·printpc(&s);
-               prints(" ");
-               prbounds("index", 0, i, s.len);
+               ·panicindex();
        }
 
        b = s.str[i];
index 2bb6f110f739d09eb7d73a008926cbd871b40a3b..e0b6ad6242a72ccfcde4993f0dfe01413c353db9 100644 (file)
@@ -2,26 +2,22 @@
 == ./
 
 =========== ./cmp2.go
-comparing uncomparable type []int
-throw: interface compare
+panic: runtime error: comparing uncomparable type []int
 
 panic PC=xxx
 
 =========== ./cmp3.go
-comparing uncomparable type []int
-throw: interface compare
+panic: runtime error: comparing uncomparable type []int
 
 panic PC=xxx
 
 =========== ./cmp4.go
-hash of unhashable type []int
-throw: interface hash
+panic: runtime error: hash of unhashable type []int
 
 panic PC=xxx
 
 =========== ./cmp5.go
-hash of unhashable type []int
-throw: interface hash
+panic: runtime error: hash of unhashable type []int
 
 panic PC=xxx
 
index 8b47b82475c4cea07d0394295c89c4594f2fca70..ca6f0728860c7aa3006026695df48cd72a7c2475 100644 (file)
@@ -23,21 +23,21 @@ func main() {
 }
 
 func die() {
-       runtime.Breakpoint()    // can't depend on panic
+       runtime.Breakpoint() // can't depend on panic
 }
 
 func mustRecover(x interface{}) {
-       mustNotRecover()        // because it's not a defer call
+       mustNotRecover() // because it's not a defer call
        v := recover()
        if v == nil {
                println("missing recover")
-               die()   // panic is useless here
+               die() // panic is useless here
        }
        if v != x {
                println("wrong value", v, x)
                die()
        }
-       
+
        // the value should be gone now regardless
        v = recover()
        if v != nil {
@@ -49,19 +49,19 @@ func mustRecover(x interface{}) {
 func mustNotRecover() {
        v := recover()
        if v != nil {
-               println("spurious recover")
+               println("spurious recover", v)
                die()
        }
 }
 
 func withoutRecover() {
-       mustNotRecover()        // because it's a sub-call
+       mustNotRecover() // because it's a sub-call
 }
 
 func test1() {
-       defer mustNotRecover()  // because mustRecover will squelch it
-       defer mustRecover(1)    // because of panic below
-       defer withoutRecover()  // should be no-op, leaving for mustRecover to find
+       defer mustNotRecover() // because mustRecover will squelch it
+       defer mustRecover(1)   // because of panic below
+       defer withoutRecover() // should be no-op, leaving for mustRecover to find
        panic(1)
 }
 
@@ -102,14 +102,14 @@ func test2() {
        // It does not see the panic when called from a call within a deferred call (too late)
        // nor does it see the panic when it *is* the deferred call (too early).
        defer mustRecover(2)
-       defer recover() // should be no-op
+       defer recover() // should be no-op
        panic(2)
 }
 
 func test3() {
        defer mustNotRecover()
        defer func() {
-               recover()       // should squelch
+               recover() // should squelch
        }()
        panic(3)
 }
@@ -118,7 +118,7 @@ func test4() {
        // Equivalent to test3 but using defer to make the call.
        defer mustNotRecover()
        defer func() {
-               defer recover() // should squelch
+               defer recover() // should squelch
        }()
        panic(4)
 }
@@ -154,8 +154,8 @@ func test5() {
                println("wrong value", v, 5)
                die()
        }
-       
-       s := try(func() { }, "hi").(string)
+
+       s := try(func() {}, "hi").(string)
        if s != "hi" {
                println("wrong value", s, "hi")
                die()
@@ -166,8 +166,8 @@ func test5() {
                println("try1 wrong value", v, 5)
                die()
        }
-       
-       s = try1(func() { }, "hi").(string)
+
+       s = try1(func() {}, "hi").(string)
        if s != "hi" {
                println("try1 wrong value", s, "hi")
                die()
@@ -183,7 +183,7 @@ func big(mustRecover bool) {
        x[0] = 1
        x[99999] = 1
        _ = x
-       
+
        v := recover()
        if mustRecover {
                if v == nil {
diff --git a/test/recover2.go b/test/recover2.go
new file mode 100644 (file)
index 0000000..96d591a
--- /dev/null
@@ -0,0 +1,86 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 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.
+
+// Test of recover for run-time errors.
+
+// TODO(rsc):
+//     integer divide by zero?
+//     null pointer accesses
+
+package main
+
+import (
+       "os"
+       "strings"
+)
+
+var x = make([]byte, 10)
+
+func main() {
+       test1()
+       test2()
+       test3()
+       test4()
+       test5()
+       test6()
+       test7()
+}
+
+func mustRecover(s string) {
+       v := recover()
+       if v == nil {
+               panic("expected panic")
+       }
+       if e := v.(os.Error).String(); strings.Index(e, s) < 0 {
+               panic("want: " + s + "; have: " + e)
+       }
+}
+
+func test1() {
+       defer mustRecover("index")
+       println(x[123])
+}
+
+func test2() {
+       defer mustRecover("slice")
+       println(x[5:15])
+}
+
+func test3() {
+       defer mustRecover("slice")
+       println(x[11:9])
+}
+
+func test4() {
+       defer mustRecover("interface")
+       var x interface{} = 1
+       println(x.(float))
+}
+
+type T struct {
+       a, b int
+}
+
+func test5() {
+       defer mustRecover("uncomparable")
+       var x T
+       var z interface{} = x
+       println(z != z)
+}
+
+func test6() {
+       defer mustRecover("unhashable")
+       var x T
+       var z interface{} = x
+       m := make(map[interface{}]int)
+       m[z] = 1
+}
+
+func test7() {
+       defer mustRecover("complex divide by zero")
+       var x, y complex
+       println(x / y)
+}