From: jakub Date: Wed, 7 Jan 2009 22:50:42 +0000 (+0000) Subject: PR libstdc++/38732 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=d6d31e2de5a5a043328219ba8b14e7422e18f95f PR libstdc++/38732 * libsupc++/unwind-cxx.h (__cxxabiv1::__cxa_exception): Remove referenceCount field again. (__cxxabiv1::__cxa_refcounted_exception): New struct. (__cxxabiv1::__get_refcounted_exception_header_from_obj, __cxxabiv1::__get_refcounted_exception_header_from_ue): New static inline functions. * libsupc++/eh_alloc.cc (__cxxabiv1::__cxa_allocate_exception, __cxxabiv1::__cxa_free_exception): Use __cxa_refcounted_exception instead of __cxa_exception. * libsupc++/eh_throw.cc (__gxx_exception_cleanup, __cxxabiv1::__cxa_throw): Likewise. * libsupc++/eh_ptr.cc (std::rethrow_exception, std::__exception_ptr::exception_ptr::_M_addref, std::__exception_ptr::exception_ptr::_M_release, __gxx_dependent_exception_cleanup): Likewise. * testsuite/18_support/exception/38732.cc: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143170 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 874880896d4..ed698d3d51e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,23 @@ 2009-01-07 Jakub Jelinek + PR libstdc++/38732 + * libsupc++/unwind-cxx.h (__cxxabiv1::__cxa_exception): Remove + referenceCount field again. + (__cxxabiv1::__cxa_refcounted_exception): New struct. + (__cxxabiv1::__get_refcounted_exception_header_from_obj, + __cxxabiv1::__get_refcounted_exception_header_from_ue): New static + inline functions. + * libsupc++/eh_alloc.cc (__cxxabiv1::__cxa_allocate_exception, + __cxxabiv1::__cxa_free_exception): Use __cxa_refcounted_exception + instead of __cxa_exception. + * libsupc++/eh_throw.cc (__gxx_exception_cleanup, + __cxxabiv1::__cxa_throw): Likewise. + * libsupc++/eh_ptr.cc (std::rethrow_exception, + std::__exception_ptr::exception_ptr::_M_addref, + std::__exception_ptr::exception_ptr::_M_release, + __gxx_dependent_exception_cleanup): Likewise. + * testsuite/18_support/exception/38732.cc: New test. + PR libstdc++/38092 * acinclude.m4 (HAVE_AS_SYMVER_DIRECTIVE): New test. * src/compatibility.cc: Don't use .symver directives if diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc index 6bc46fc9a91..495a25f28f0 100644 --- a/libstdc++-v3/libsupc++/eh_alloc.cc +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -1,5 +1,5 @@ // -*- C++ -*- Allocate exception objects. -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 // Free Software Foundation, Inc. // // This file is part of GCC. @@ -103,7 +103,7 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw() { void *ret; - thrown_size += sizeof (__cxa_exception); + thrown_size += sizeof (__cxa_refcounted_exception); ret = malloc (thrown_size); if (! ret) @@ -137,9 +137,9 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw() __cxa_eh_globals *globals = __cxa_get_globals (); globals->uncaughtExceptions += 1; - memset (ret, 0, sizeof (__cxa_exception)); + memset (ret, 0, sizeof (__cxa_refcounted_exception)); - return (void *)((char *)ret + sizeof (__cxa_exception)); + return (void *)((char *)ret + sizeof (__cxa_refcounted_exception)); } @@ -158,7 +158,7 @@ __cxxabiv1::__cxa_free_exception(void *vptr) throw() emergency_used &= ~((bitmask_type)1 << which); } else - free (ptr - sizeof (__cxa_exception)); + free (ptr - sizeof (__cxa_refcounted_exception)); } diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc index 901219a9d12..414a6b9e010 100644 --- a/libstdc++-v3/libsupc++/eh_ptr.cc +++ b/libstdc++-v3/libsupc++/eh_ptr.cc @@ -1,5 +1,5 @@ // -*- C++ -*- Implement the members of exception_ptr. -// Copyright (C) 2008 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009 Free Software Foundation, Inc. // // This file is part of GCC. // @@ -84,8 +84,8 @@ std::__exception_ptr::exception_ptr::_M_addref() throw() { if (_M_exception_object) { - __cxa_exception *eh = - __get_exception_header_from_obj (_M_exception_object); + __cxa_refcounted_exception *eh = + __get_refcounted_exception_header_from_obj (_M_exception_object); __sync_add_and_fetch (&eh->referenceCount, 1); } } @@ -96,12 +96,12 @@ std::__exception_ptr::exception_ptr::_M_release() throw() { if (_M_exception_object) { - __cxa_exception *eh = - __get_exception_header_from_obj (_M_exception_object); + __cxa_refcounted_exception *eh = + __get_refcounted_exception_header_from_obj (_M_exception_object); if (__sync_sub_and_fetch (&eh->referenceCount, 1) == 0) { - if (eh->exceptionDestructor) - eh->exceptionDestructor (_M_exception_object); + if (eh->exc.exceptionDestructor) + eh->exc.exceptionDestructor (_M_exception_object); __cxa_free_exception (_M_exception_object); _M_exception_object = 0; @@ -191,22 +191,22 @@ __gxx_dependent_exception_cleanup (_Unwind_Reason_Code code, { // This cleanup is set only for dependents. __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc); - __cxa_exception *header = - __get_exception_header_from_obj (dep->primaryException); + __cxa_refcounted_exception *header = + __get_refcounted_exception_header_from_obj (dep->primaryException); // We only want to be called through _Unwind_DeleteException. // _Unwind_DeleteException in the HP-UX IA64 libunwind library // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT // like the GCC _Unwind_DeleteException function does. if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) - __terminate (header->terminateHandler); + __terminate (header->exc.terminateHandler); __cxa_free_dependent_exception (dep); if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0) { - if (header->exceptionDestructor) - header->exceptionDestructor (header + 1); + if (header->exc.exceptionDestructor) + header->exc.exceptionDestructor (header + 1); __cxa_free_exception (header + 1); } @@ -217,7 +217,8 @@ void std::rethrow_exception(std::exception_ptr ep) { void *obj = ep._M_get(); - __cxa_exception *eh = __get_exception_header_from_obj (obj); + __cxa_refcounted_exception *eh + = __get_refcounted_exception_header_from_obj (obj); __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception (); dep->primaryException = obj; diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc index 24b357772b4..afe7c683c5b 100644 --- a/libstdc++-v3/libsupc++/eh_throw.cc +++ b/libstdc++-v3/libsupc++/eh_throw.cc @@ -1,5 +1,5 @@ // -*- C++ -*- Exception handling routines for throwing. -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 // Free Software Foundation, Inc. // // This file is part of GCC. @@ -38,21 +38,22 @@ static void __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc) { // This cleanup is set only for primaries. - __cxa_exception *header = __get_exception_header_from_ue (exc); + __cxa_refcounted_exception *header + = __get_refcounted_exception_header_from_ue (exc); // We only want to be called through _Unwind_DeleteException. // _Unwind_DeleteException in the HP-UX IA64 libunwind library // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT // like the GCC _Unwind_DeleteException function does. if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) - __terminate (header->terminateHandler); + __terminate (header->exc.terminateHandler); #ifdef _GLIBCXX_ATOMIC_BUILTINS_4 if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0) { #endif - if (header->exceptionDestructor) - header->exceptionDestructor (header + 1); + if (header->exc.exceptionDestructor) + header->exc.exceptionDestructor (header + 1); __cxa_free_exception (header + 1); #ifdef _GLIBCXX_ATOMIC_BUILTINS_4 @@ -66,23 +67,24 @@ __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo, void (*dest) (void *)) { // Definitely a primary. - __cxa_exception *header = __get_exception_header_from_obj (obj); + __cxa_refcounted_exception *header + = __get_refcounted_exception_header_from_obj (obj); header->referenceCount = 1; - header->exceptionType = tinfo; - header->exceptionDestructor = dest; - header->unexpectedHandler = __unexpected_handler; - header->terminateHandler = __terminate_handler; - __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->unwindHeader.exception_class); - header->unwindHeader.exception_cleanup = __gxx_exception_cleanup; + header->exc.exceptionType = tinfo; + header->exc.exceptionDestructor = dest; + header->exc.unexpectedHandler = __unexpected_handler; + header->exc.terminateHandler = __terminate_handler; + __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->exc.unwindHeader.exception_class); + header->exc.unwindHeader.exception_cleanup = __gxx_exception_cleanup; #ifdef _GLIBCXX_SJLJ_EXCEPTIONS - _Unwind_SjLj_RaiseException (&header->unwindHeader); + _Unwind_SjLj_RaiseException (&header->exc.unwindHeader); #else - _Unwind_RaiseException (&header->unwindHeader); + _Unwind_RaiseException (&header->exc.unwindHeader); #endif // Some sort of unwinding error. Note that terminate is a handler. - __cxa_begin_catch (&header->unwindHeader); + __cxa_begin_catch (&header->exc.unwindHeader); std::terminate (); } diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h index 3f6a76560fd..3e2cf0f00b4 100644 --- a/libstdc++-v3/libsupc++/unwind-cxx.h +++ b/libstdc++-v3/libsupc++/unwind-cxx.h @@ -1,5 +1,5 @@ // -*- C++ -*- Exception handling and frame unwind runtime interface routines. -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 // Free Software Foundation, Inc. // // This file is part of GCC. @@ -53,9 +53,6 @@ namespace __cxxabiv1 struct __cxa_exception { - // Manage this header. - _Atomic_word referenceCount; - // Manage the exception object itself. std::type_info *exceptionType; void (*exceptionDestructor)(void *); @@ -92,6 +89,14 @@ struct __cxa_exception _Unwind_Exception unwindHeader; }; +struct __cxa_refcounted_exception +{ + // Manage this header. + _Atomic_word referenceCount; + // __cxa_exception must be last, and no padding can be after it. + __cxa_exception exc; +}; + // A dependent C++ exception object consists of a wrapper around an unwind // object header with additional C++ specific information, containing a pointer // to a primary exception object. @@ -227,6 +232,21 @@ __get_exception_header_from_ue (_Unwind_Exception *exc) return reinterpret_cast<__cxa_exception *>(exc + 1) - 1; } +// Acquire the C++ refcounted exception header from the C++ object. +static inline __cxa_refcounted_exception * +__get_refcounted_exception_header_from_obj (void *ptr) +{ + return reinterpret_cast<__cxa_refcounted_exception *>(ptr) - 1; +} + +// Acquire the C++ refcounted exception header from the generic exception +// header. +static inline __cxa_refcounted_exception * +__get_refcounted_exception_header_from_ue (_Unwind_Exception *exc) +{ + return reinterpret_cast<__cxa_refcounted_exception *>(exc + 1) - 1; +} + static inline __cxa_dependent_exception * __get_dependent_exception_from_ue (_Unwind_Exception *exc) { diff --git a/libstdc++-v3/testsuite/18_support/exception/38732.cc b/libstdc++-v3/testsuite/18_support/exception/38732.cc new file mode 100644 index 00000000000..9286552035a --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/exception/38732.cc @@ -0,0 +1,93 @@ +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +#include +#include +#include +#include "unwind.h" +#include + +// Before exception_ptr was introduced, some programs copied +// part of unwind-cxx.h and used __cxa_get_globals to get at the +// current exceptionType. __cxa_exception structure is described in the +// C++ ABI, so they have the right to assume it works. +// Ensure it is true. + +struct __cxa_exception +{ + std::type_info *exceptionType; + void (*exceptionDestructor)(void *); + std::unexpected_handler unexpectedHandler; + std::terminate_handler terminateHandler; + __cxa_exception *nextException; + int handlerCount; +#ifdef __ARM_EABI_UNWINDER__ + __cxa_exception* nextPropagatingException; + int propagationCount; +#else + int handlerSwitchValue; + const unsigned char *actionRecord; + const unsigned char *languageSpecificData; + _Unwind_Ptr catchTemp; + void *adjustedPtr; +#endif + _Unwind_Exception unwindHeader; +}; + +struct __cxa_eh_globals +{ + __cxa_exception *caughtExceptions; + unsigned int uncaughtExceptions; +#ifdef __ARM_EABI_UNWINDER__ + __cxa_exception* propagatingExceptions; +#endif +}; + +extern "C" __cxa_eh_globals *__cxa_get_globals () throw(); + +// PR libstdc++/38732 +void test01 () +{ + bool test __attribute__((unused)) = true; + try { + throw 0; + } catch(...) { + __cxa_exception *exc = __cxa_get_globals()->caughtExceptions; + VERIFY ( exc != NULL ); + VERIFY ( typeid(int) == *exc->exceptionType ); + } + try { + throw 0LL; + } catch(...) { + __cxa_exception *exc = __cxa_get_globals()->caughtExceptions; + VERIFY ( exc != NULL ); + VERIFY ( typeid(long long int) == *exc->exceptionType ); + } + try { + throw 0.0; + } catch(...) { + __cxa_exception *exc = __cxa_get_globals()->caughtExceptions; + VERIFY ( exc != NULL ); + VERIFY ( typeid(double) == *exc->exceptionType ); + } +} + +int main () +{ + test01 (); +}