+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
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. */
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;
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;
}
--- /dev/null
+// PR libstdc++/10606
+// { dg-do run }
+
+#include <exception>
+#include <cstdlib>
+
+
+struct Check {
+ int obj1, obj2;
+ bool state;
+};
+
+static Check const data[] = {
+ { 0, 0, false }, // construct [0]
+ { 1, 0, true }, // [1] = [0]
+ { 0, 0, true }, // destruct [0]
+ { 2, 1, true }, // [2] = [1]
+ { 2, 2, true }, // destruct [2]
+ { 3, 1, true }, // [3] = [1]
+ { 3, 3, false }, // destruct [3]
+ { 1, 1, false }, // destruct [1]
+ { 9, 9, false } // end-of-data
+};
+
+static int pos = 0;
+
+static void test(int obj1, int obj2, bool state)
+{
+ if (obj1 != data[pos].obj1) abort ();
+ if (obj2 != data[pos].obj2) abort ();
+ if (state != data[pos].state) abort ();
+ pos++;
+}
+
+
+struct S {
+ int id;
+ S ();
+ S (const S &);
+ ~S ();
+};
+
+static int next_id = 0;
+
+S::S()
+ : id (next_id++)
+{
+ test (id, id, std::uncaught_exception ());
+}
+
+S::S(const S &x)
+ : id (next_id++)
+{
+ test (id, x.id, std::uncaught_exception ());
+}
+
+S::~S()
+{
+ test (id, id, std::uncaught_exception ());
+}
+
+extern void foo (S *);
+
+int main()
+{
+ try
+ {
+ try
+ {
+ S s0;
+ throw s0; // s1 is the exception object
+ }
+ catch (S s2)
+ {
+ throw;
+ }
+ }
+ catch (S s3)
+ {
+ }
+
+ return 0;
+}
+2005-02-18 Richard Henderson <rth@redhat.com>
+
+ PR libstdc++/10606
+ * 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.
+
2005-02-18 Matt Austern <austern@apple.com>
+
* testsuite/tr1/6_containers/unordered/insert/array_syntax.cc: Fix
test case to use assignment instead of ==
* testsuite/tr1/6_containers/unordered/insert/map_range.cc: New test.
local:
*;
};
+
+CXXABI_1.3.1 {
+
+ __cxa_get_exception_ptr;
+
+} CXXABI_1.3;
std::terminate ();
}
+ // We have an uncaught exception as soon as we allocate memory. This
+ // yields uncaught_exception() true during the copy-constructor that
+ // initializes the exception object. See Issue 475.
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ globals->uncaughtExceptions += 1;
+
memset (ret, 0, sizeof (__cxa_exception));
return (void *)((char *)ret + sizeof (__cxa_exception));
using namespace __cxxabiv1;
+extern "C" void *
+__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw()
+{
+ _Unwind_Exception *exceptionObject
+ = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
+ __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
+
+ return header->adjustedPtr;
+}
extern "C" void *
__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw()
// This exception was rethrown. Decrement the (inverted) catch
// count and remove it from the chain when it reaches zero.
if (++count == 0)
- {
- globals->uncaughtExceptions += 1;
- globals->caughtExceptions = header->nextException;
- }
+ globals->caughtExceptions = header->nextException;
}
else if (--count == 0)
{
header->unwindHeader.exception_class = __gxx_exception_class;
header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
- __cxa_eh_globals *globals = __cxa_get_globals ();
- globals->uncaughtExceptions += 1;
-
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&header->unwindHeader);
#else
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
+ globals->uncaughtExceptions += 1;
+
// Watch for luser rethrowing with no active exception.
if (header)
{
__attribute__((noreturn));
// Used to implement exception handlers.
+extern "C" void *__cxa_get_exception_ptr (void *) throw();
extern "C" void *__cxa_begin_catch (void *) throw();
extern "C" void __cxa_end_catch ();
extern "C" void __cxa_rethrow () __attribute__((noreturn));