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
This commit is contained in:
Richard Henderson 2005-02-18 18:35:25 -08:00 committed by Richard Henderson
parent 5ff489f15b
commit 396090773c
9 changed files with 185 additions and 41 deletions

View file

@ -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

View file

@ -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))
{
tree init;
/* 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;
}
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 ();
}
/* 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)))
{
exp = do_get_exception_ptr ();
initialize_handler_parm (decl, exp);
finish_expr_stmt (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;
}

View file

@ -0,0 +1,83 @@
// 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;
}

View file

@ -1,4 +1,17 @@
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.

View file

@ -410,3 +410,9 @@ CXXABI_1.3 {
local:
*;
};
CXXABI_1.3.1 {
__cxa_get_exception_ptr;
} CXXABI_1.3;

View file

@ -147,6 +147,12 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
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));

View file

@ -33,6 +33,15 @@
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()
@ -107,10 +116,7 @@ __cxxabiv1::__cxa_end_catch ()
// 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)
{

View file

@ -66,9 +66,6 @@ __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
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
@ -86,6 +83,8 @@ __cxxabiv1::__cxa_rethrow ()
__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)
{

View file

@ -107,6 +107,7 @@ extern "C" void __cxa_throw (void *thrown_exception,
__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));