Node *fn, *tmp;
NodeList *body, *init;
Type *th, *t;
+ int lno;
t = n->type;
init = nil;
a = n->right;
+ lno = setlineno(a);
if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
a = nod(OCONV, n->right, N);
a->type = types[TSTRING];
typechecklist(body, Etop);
n->nbody = concat(body, n->nbody);
walkstmt(&n);
+
+ lineno = lno;
}
void runtime·newproc(void);
void runtime·newstack(void);
void runtime·morestack(void);
+void runtime·sigpanic(void);
// This code is also used for the 386 tracebacks.
// Use uintptr for an appropriate word-sized integer.
byte *fp;
Stktop *stk;
Func *f;
+ bool waspanic;
USED(lr0);
pc = (uintptr)pc0;
lr = 0;
fp = nil;
+ waspanic = false;
// If the PC is goexit, the goroutine hasn't started yet.
if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
if(pc > f->entry)
runtime·printf("+%p", (uintptr)(pc - f->entry));
tracepc = pc; // back up to CALL instruction for funcline.
- if(n > 0 && pc > f->entry)
+ if(n > 0 && pc > f->entry && !waspanic)
tracepc--;
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
runtime·printf("\t%S(", f->name);
n++;
}
+ waspanic = f->entry == (uintptr)runtime·sigpanic;
+
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
fp += 2*sizeof(uintptr);
void runtime·newproc(void);
void runtime·newstack(void);
void runtime·morestack(void);
+void runtime·sigpanic(void);
void _div(void);
void _mod(void);
void _divu(void);
int32 i, n, iter;
uintptr pc, lr, tracepc, x;
byte *fp, *p;
+ bool waspanic;
Stktop *stk;
Func *f;
pc = (uintptr)pc0;
lr = (uintptr)lr0;
fp = nil;
+ waspanic = false;
// If the PC is goexit, the goroutine hasn't started yet.
if(pc == (uintptr)runtime·goexit) {
if(pc > f->entry)
runtime·printf("+%p", (uintptr)(pc - f->entry));
tracepc = pc; // back up to CALL instruction for funcline.
- if(n > 0 && pc > f->entry)
+ if(n > 0 && pc > f->entry && !waspanic)
tracepc -= sizeof(uintptr);
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
runtime·printf("\t%S(", f->name);
runtime·prints(")\n");
n++;
}
+
+ waspanic = f->entry == (uintptr)runtime·sigpanic;
if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
{
runtime·throw("too many writes on closed pipe");
}
+
+/*
+ * placeholder - once notes are implemented,
+ * a signal generating a panic must appear as
+ * a call to this function for correct handling by
+ * traceback.
+ */
+void
+runtime·sigpanic(void)
+{
+}
uint32 runtime·panicking;
+/*
+ * We assume that all architectures turn faults and the like
+ * into apparent calls to runtime.sigpanic. If we see a "call"
+ * to runtime.sigpanic, we do not back up the PC to find the
+ * line number of the CALL instruction, because there is no CALL.
+ */
+void runtime·sigpanic(void);
+
int32
runtime·gotraceback(void)
{
void
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
{
- Func *f;
+ Func *f, *g;
uintptr pc;
-
- if(runtime·callers(1+skip, &retpc, 1) == 0) {
+ uintptr rpc[2];
+
+ /*
+ * Ask for two PCs: the one we were asked for
+ * and what it called, so that we can see if it
+ * "called" sigpanic.
+ */
+ retpc = 0;
+ if(runtime·callers(1+skip-1, rpc, 2) < 2) {
retfile = runtime·emptystring;
retline = 0;
retbool = false;
- } else if((f = runtime·findfunc(retpc)) == nil) {
+ } else if((f = runtime·findfunc(rpc[1])) == nil) {
retfile = runtime·emptystring;
retline = 0;
retbool = true; // have retpc at least
} else {
+ retpc = rpc[1];
retfile = f->src;
pc = retpc;
- if(pc > f->entry)
+ g = runtime·findfunc(rpc[0]);
+ if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
pc--;
retline = runtime·funcline(f, pc);
retbool = true;
}
+ FLUSH(&retpc);
FLUSH(&retfile);
FLUSH(&retline);
FLUSH(&retbool);
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "runtime"
+ "strings"
+)
+
+func f() {
+ var x *string
+
+ for _, i := range *x { // THIS IS LINE 17
+ println(i)
+ }
+}
+
+func g() {
+}
+
+func main() {
+ defer func() {
+ for i := 0;; i++ {
+ pc, file, line, ok := runtime.Caller(i)
+ if !ok {
+ print("BUG: bug348: cannot find caller\n")
+ return
+ }
+ if !strings.Contains(file, "bug348.go") || runtime.FuncForPC(pc).Name() != "main.f" {
+ // walk past runtime frames
+ continue
+ }
+ if line != 17 {
+ print("BUG: bug348: panic at ", file, ":", line, " in ", runtime.FuncForPC(pc).Name(), "\n")
+ return
+ }
+ recover()
+ return
+ }
+ }()
+ f()
+}