diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 05:47:20 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 05:47:20 +0000 |
commit | b9f04a8461a67148848258f8e4b367a1b988038e (patch) | |
tree | 03800353a564c0cdcf3c12bb8940b28389b243a9 /libgo | |
parent | fae3f4598af23b48fed264052e33d5516e31a56c (diff) | |
download | gcc-b9f04a8461a67148848258f8e4b367a1b988038e.zip gcc-b9f04a8461a67148848258f8e4b367a1b988038e.tar.gz gcc-b9f04a8461a67148848258f8e4b367a1b988038e.tar.bz2 |
Fix defer when not calling recover in function with named results.
From-SVN: r178905
Diffstat (limited to 'libgo')
-rw-r--r-- | libgo/runtime/go-defer.c | 10 | ||||
-rw-r--r-- | libgo/runtime/go-defer.h | 7 | ||||
-rw-r--r-- | libgo/runtime/go-panic.c | 6 | ||||
-rw-r--r-- | libgo/runtime/go-unwind.c | 10 |
4 files changed, 27 insertions, 6 deletions
diff --git a/libgo/runtime/go-defer.c b/libgo/runtime/go-defer.c index 6425f05..1f116eb 100644 --- a/libgo/runtime/go-defer.c +++ b/libgo/runtime/go-defer.c @@ -13,7 +13,7 @@ /* This function is called each time we need to defer a call. */ void -__go_defer (void *frame, void (*pfn) (void *), void *arg) +__go_defer (_Bool *frame, void (*pfn) (void *), void *arg) { struct __go_defer_stack *n; @@ -34,7 +34,7 @@ __go_defer (void *frame, void (*pfn) (void *), void *arg) /* This function is called when we want to undefer the stack. */ void -__go_undefer (void *frame) +__go_undefer (_Bool *frame) { if (__go_panic_defer == NULL) return; @@ -53,6 +53,12 @@ __go_undefer (void *frame) __go_panic_defer->__defer = d->__next; __go_free (d); + + /* Since we are executing a defer function here, we know we are + returning from the calling function. If the calling + function, or one of its callees, paniced, then the defer + functions would be executed by __go_panic. */ + *frame = 1; } } diff --git a/libgo/runtime/go-defer.h b/libgo/runtime/go-defer.h index f8924f3..0b20e8f 100644 --- a/libgo/runtime/go-defer.h +++ b/libgo/runtime/go-defer.h @@ -13,9 +13,10 @@ struct __go_defer_stack /* The next entry in the stack. */ struct __go_defer_stack *__next; - /* The frame pointer for the function which called this defer - statement. */ - void *__frame; + /* The stack variable for the function which called this defer + statement. This is set to 1 if we are returning from that + function, 0 if we are panicing through it. */ + _Bool *__frame; /* The value of the panic stack when this function is deferred. This function can not recover this value from the panic stack. diff --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c index b684779..c39ea9f 100644 --- a/libgo/runtime/go-panic.c +++ b/libgo/runtime/go-panic.c @@ -87,6 +87,12 @@ __go_panic (struct __go_empty_interface arg) /* __go_unwind_stack should not return. */ abort (); } + + /* Because we executed that defer function by a panic, and + it did not call recover, we know that we are not + returning from the calling function--we are panicing + through it. */ + *d->__frame = 0; } __go_panic_defer->__defer = d->__next; diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c index 0bc3f1b..e64cf90 100644 --- a/libgo/runtime/go-unwind.c +++ b/libgo/runtime/go-unwind.c @@ -44,7 +44,7 @@ static const _Unwind_Exception_Class __go_exception_class = continue unwinding. */ void -__go_check_defer (void *frame) +__go_check_defer (_Bool *frame) { struct _Unwind_Exception *hdr; @@ -103,8 +103,12 @@ __go_check_defer (void *frame) if (was_recovered) { /* Just return and continue executing Go code. */ + *frame = 1; return; } + + /* We are panicing through this function. */ + *frame = 0; } else if (__go_panic_defer->__defer != NULL && __go_panic_defer->__defer->__pfn == NULL @@ -118,6 +122,10 @@ __go_check_defer (void *frame) d = __go_panic_defer->__defer; __go_panic_defer->__defer = d->__next; __go_free (d); + + /* We are returning from this function. */ + *frame = 1; + return; } |