diff options
author | Richard Henderson <rth@redhat.com> | 2005-02-18 18:35:25 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-02-18 18:35:25 -0800 |
commit | 396090773cfa29f9a5973a39a61dfc8d001b9633 (patch) | |
tree | 020d4a99713b8ea013495d485fc2c96d2a5d328e /gcc/cp | |
parent | 5ff489f15bb5916615fbac14fe7fc843d32a6054 (diff) | |
download | gcc-396090773cfa29f9a5973a39a61dfc8d001b9633.zip gcc-396090773cfa29f9a5973a39a61dfc8d001b9633.tar.gz gcc-396090773cfa29f9a5973a39a61dfc8d001b9633.tar.bz2 |
re PR libstdc++/10606 (uncaught_exception() returns false too early)
PR libstdc++/10606
gcc/cp/
* except.c (do_get_exception_ptr): New.
(expand_start_catch_block): Use it.
libstdc++/
* config/linker-map.gnu (CXXABI_1.3.1): Add __cxa_get_exception_ptr.
* libsupc++/eh_alloc.cc (__cxa_allocate_exception): Increment
uncaughtExceptions here instead of ...
* libsupc++/eh_throw.cc (__cxa_throw) ... here.
(__cxa_rethrow): Increment uncaughtExceptions here instead of ...
* libsupc++/eh_catch.cc (__cxa_end_catch): ... here.
(__cxa_get_exception_ptr): New.
* libsupc++/unwind-cxx.h (__cxa_get_exception_ptr): Declare.
From-SVN: r95262
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 92 |
2 files changed, 64 insertions, 34 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 92db68e..62e7a43 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2005-02-18 Richard Henderson <rth@redhat.com> + + PR libstdc++/10606 + * except.c (do_get_exception_ptr): New. + (expand_start_catch_block): Use it. + 2005-02-19 Jakub Jelinek <jakub@redhat.com> * decl.c (start_decl_1): Only check TYPE_NEEDS_CONSTRUCTING diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 4a0ccb9..ef4fb21 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -153,6 +153,26 @@ build_exc_ptr (void) return build0 (EXC_PTR_EXPR, ptr_type_node); } +/* Build up a call to __cxa_get_exception_ptr so that we can build a + copy constructor for the thrown object. */ + +static tree +do_get_exception_ptr (void) +{ + tree fn; + + fn = get_identifier ("__cxa_get_exception_ptr"); + if (!get_global_value_if_present (fn, &fn)) + { + /* Declare void* __cxa_get_exception_ptr (void *). */ + tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); + fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp)); + } + + return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), + NULL_TREE)); +} + /* Build up a call to __cxa_begin_catch, to tell the runtime that the exception has been handled. */ @@ -381,9 +401,8 @@ initialize_handler_parm (tree decl, tree exp) tree expand_start_catch_block (tree decl) { - tree exp = NULL_TREE; + tree exp; tree type; - bool is_java; if (! doing_eh (1)) return NULL_TREE; @@ -397,45 +416,50 @@ expand_start_catch_block (tree decl) else type = NULL_TREE; - is_java = false; - if (decl) + if (decl && decl_is_java_type (type, 1)) + { + /* Java only passes object via pointer and doesn't require + adjusting. The java object is immediately before the + generic exception header. */ + exp = build_exc_ptr (); + exp = build1 (NOP_EXPR, build_pointer_type (type), exp); + exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp, + TYPE_SIZE_UNIT (TREE_TYPE (exp))); + exp = build_indirect_ref (exp, NULL); + initialize_handler_parm (decl, exp); + return type; + } + + /* Call __cxa_end_catch at the end of processing the exception. */ + push_eh_cleanup (type); + + /* If there's no decl at all, then all we need to do is make sure + to tell the runtime that we've begun handling the exception. */ + if (decl == NULL) + finish_expr_stmt (do_begin_catch ()); + + /* If the C++ object needs constructing, we need to do that before + calling __cxa_begin_catch, so that std::uncaught_exception gets + the right value during the copy constructor. */ + else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) { - tree init; + exp = do_get_exception_ptr (); + initialize_handler_parm (decl, exp); + finish_expr_stmt (do_begin_catch ()); + } - if (decl_is_java_type (type, 1)) - { - /* Java only passes object via pointer and doesn't require - adjusting. The java object is immediately before the - generic exception header. */ - init = build_exc_ptr (); - init = build1 (NOP_EXPR, build_pointer_type (type), init); - init = build2 (MINUS_EXPR, TREE_TYPE (init), init, - TYPE_SIZE_UNIT (TREE_TYPE (init))); - init = build_indirect_ref (init, NULL); - is_java = true; - } - else - { - /* C++ requires that we call __cxa_begin_catch to get the - pointer to the actual object. */ - init = do_begin_catch (); - } - + /* Otherwise the type uses a bitwise copy, and we don't have to worry + about the value of std::uncaught_exception and therefore can do the + copy with the return value of __cxa_end_catch instead. */ + else + { + tree init = do_begin_catch (); exp = create_temporary_var (ptr_type_node); DECL_REGISTER (exp) = 1; cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING); finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init)); + initialize_handler_parm (decl, exp); } - else - finish_expr_stmt (do_begin_catch ()); - - /* C++ requires that we call __cxa_end_catch at the end of - processing the exception. */ - if (! is_java) - push_eh_cleanup (type); - - if (decl) - initialize_handler_parm (decl, exp); return type; } |