aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 05:47:20 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 05:47:20 +0000
commitb9f04a8461a67148848258f8e4b367a1b988038e (patch)
tree03800353a564c0cdcf3c12bb8940b28389b243a9 /libgo
parentfae3f4598af23b48fed264052e33d5516e31a56c (diff)
downloadgcc-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.c10
-rw-r--r--libgo/runtime/go-defer.h7
-rw-r--r--libgo/runtime/go-panic.c6
-rw-r--r--libgo/runtime/go-unwind.c10
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;
}