Re: std::rethrow_exception is broken
Jonathan Wakely jwak...@redhat.com writes: On 25/03/14 17:25 +, Jonathan Wakely wrote: Tested x86_64-linux, I plan to commit this to trunk soon. commit 06a845f80204947afd6866109db58cc85dc87117 Author: Jonathan Wakely jwak...@redhat.com Date: Tue Mar 25 14:42:45 2014 + PR libstdc++/60612 * libsupc++/eh_ptr.cc: Assert __cxa_dependent_exception layout is compatible with __cxa_exception. * libsupc++/unwind-cxx.h (__cxa_dependent_exception): Add padding. Fix typos in comments. * testsuite/18_support/exception_ptr/60612-terminate.cc: New. * testsuite/18_support/exception_ptr/60612-unexpected.cc: New. Committed to trunk. Unfortunately, the new tests FAIL on non-C99 targets (i386-pc-solaris2.9 in my case): FAIL: 18_support/exception_ptr/60612-terminate.cc (test for excess errors) Excess errors: /vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/18_support/exception_ptr/6061 2-terminate.cc:26:27: error: '_Exit' was not declared in this scope WARNING: 18_support/exception_ptr/60612-terminate.cc compilation failed to produ ce executable The following patch fixes this, following the idiom often used in the libstdc++ testsuite. Tested with the appropriate runtest invocation on i386-pc-solaris2.{9,11}. Ok for mainline? When looking into this, I noticed that this idiom is very widespread in the v3 testsuite, but IMNSHO a *very bad* idea since it hides the fact that many tests are acutually UNSUPPORTED, but appear to PASS, while the only thing that passes is an empty main. I had something similar recently when all C99 functionality in libstdc++ got disabled, but testsuite results barely changed. Unless someone strongly objects, I expect to change those tests to use corresponding dg-require-* keywords to make mark them appropriately once 4.9 branches. Rainer 2014-03-31 Rainer Orth r...@cebitec.uni-bielefeld.de * testsuite/18_support/exception_ptr/60612-terminate.cc (terminate, f): Wrap in _GLIBCXX_USE_C99. * testsuite/18_support/exception_ptr/60612-unexpected.cc: Likewise. # HG changeset patch # Parent 23f930c5334d34dff20abb2647f50b4a095481e4 Fix 18_support/exception_ptr/60612-*.cc on non-C99 targets diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc --- a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc +++ b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc @@ -23,6 +23,7 @@ #include exception #include stdlib.h +#ifdef _GLIBCXX_USE_C99 void terminate() { _Exit(0); } void f() noexcept @@ -34,8 +35,12 @@ void f() noexcept std::rethrow_exception(std::current_exception()); } } +#endif int main() { +#ifdef _GLIBCXX_USE_C99 f(); +#endif + return 0; } diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc --- a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc +++ b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc @@ -23,6 +23,7 @@ #include exception #include stdlib.h +#ifdef _GLIBCXX_USE_C99 void unexpected() { _Exit(0); } void f() throw() @@ -34,8 +35,11 @@ void f() throw() std::rethrow_exception(std::current_exception()); } } +#endif int main() { +#ifdef _GLIBCXX_USE_C99 f(); +#endif } -- - Rainer Orth, Center for Biotechnology, Bielefeld University
Re: std::rethrow_exception is broken
On 31/03/14 14:13 +0200, Rainer Orth wrote: Unfortunately, the new tests FAIL on non-C99 targets (i386-pc-solaris2.9 in my case): FAIL: 18_support/exception_ptr/60612-terminate.cc (test for excess errors) Excess errors: /vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/18_support/exception_ptr/6061 2-terminate.cc:26:27: error: '_Exit' was not declared in this scope WARNING: 18_support/exception_ptr/60612-terminate.cc compilation failed to produ ce executable Sorry about that. Does Solaris 9 not support C99 at all, or does it only define _Exit when __STDC_VERSION__ has the right value? The following patch fixes this, following the idiom often used in the libstdc++ testsuite. Tested with the appropriate runtest invocation on i386-pc-solaris2.{9,11}. Ok for mainline? The patch is OK, thanks. When looking into this, I noticed that this idiom is very widespread in the v3 testsuite, but IMNSHO a *very bad* idea since it hides the fact that many tests are acutually UNSUPPORTED, but appear to PASS, while the only thing that passes is an empty main. I had something similar recently when all C99 functionality in libstdc++ got disabled, but testsuite results barely changed. I completely agree it's a bad idea. Unless someone strongly objects, I expect to change those tests to use corresponding dg-require-* keywords to make mark them appropriately once 4.9 branches. I certainly don't object, but you should be aware that once we're in stage 1 I want to review all our uses of _GLIBCXX_USE_C99 and replace it with more fine-grained checks. We should at least have separate macros for: * we can use the C99 library in C++11 mode (true for a modern libc that checks for __cplusplus = 201103L) * we can use the C99 library in C++98 mode (true for glibc, because we define _GNU_SOURCE)
Re: std::rethrow_exception is broken
Hi Jonathan, On 31/03/14 14:13 +0200, Rainer Orth wrote: Unfortunately, the new tests FAIL on non-C99 targets (i386-pc-solaris2.9 in my case): FAIL: 18_support/exception_ptr/60612-terminate.cc (test for excess errors) Excess errors: /vol/gcc/src/hg/trunk/local/libstdc++-v3/testsuite/18_support/exception_ptr/6061 2-terminate.cc:26:27: error: '_Exit' was not declared in this scope WARNING: 18_support/exception_ptr/60612-terminate.cc compilation failed to produ ce executable Sorry about that. Does Solaris 9 not support C99 at all, or does it only define _Exit when __STDC_VERSION__ has the right value? no C99 support at all. That only appeared in Solaris 10. When looking into this, I noticed that this idiom is very widespread in the v3 testsuite, but IMNSHO a *very bad* idea since it hides the fact that many tests are acutually UNSUPPORTED, but appear to PASS, while the only thing that passes is an empty main. I had something similar recently when all C99 functionality in libstdc++ got disabled, but testsuite results barely changed. I completely agree it's a bad idea. Unless someone strongly objects, I expect to change those tests to use corresponding dg-require-* keywords to make mark them appropriately once 4.9 branches. I certainly don't object, but you should be aware that once we're in stage 1 I want to review all our uses of _GLIBCXX_USE_C99 and replace it with more fine-grained checks. We should at least have separate macros for: * we can use the C99 library in C++11 mode (true for a modern libc that checks for __cplusplus = 201103L) * we can use the C99 library in C++98 mode (true for glibc, because we define _GNU_SOURCE) Good to know, thanks for the heads-up. Rainer -- - Rainer Orth, Center for Biotechnology, Bielefeld University
Re: std::rethrow_exception is broken
On 29/03/14 19:55 +0100, Daniel Krügler wrote: 2014-03-28 13:37 GMT+01:00 Jonathan Wakely jwak...@redhat.com: On 27/03/14 23:00 +0100, Daniel Krügler wrote: I'm in favour for changing it, what about something like layout mismatch ? How about this? __cxa_dependent_exception::termHandler layout must be consistent with __cxa_exception::termHandler Yes, this seems even better to me. This improves the static assertion messages, as suggested by François and Daniel. Tested x86_64-linux, committed to trunk. commit f92ce7260937614a7897d9890c022812794f793b Author: Jonathan Wakely jwak...@redhat.com Date: Wed Mar 12 21:36:53 2014 + 2014-03-12 Lars Gullik Bj??nnes lar...@gullik.org Jonathan Wakely jwak...@redhat.com PR libstdc++/60270 * include/std/iomanip (_Quoted_string operator): Do not clear string if input is not quoted. * testsuite/27_io/manipulators/standard/char/60270.cc: New. diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip index b2c7b95..73822db 100644 --- a/libstdc++-v3/include/std/iomanip +++ b/libstdc++-v3/include/std/iomanip @@ -415,8 +415,6 @@ _GLIBCXX_END_NAMESPACE_VERSION const _Quoted_stringbasic_string_CharT, _Traits, _Alloc, _CharT __str) { - __str._M_string.clear(); - _CharT __c; __is __c; if (!__is.good()) @@ -427,6 +425,7 @@ _GLIBCXX_END_NAMESPACE_VERSION __is __str._M_string; return __is; } + __str._M_string.clear(); std::ios_base::fmtflags __flags = __is.flags(__is.flags() ~std::ios_base::skipws); do diff --git a/libstdc++-v3/testsuite/27_io/manipulators/standard/char/60270.cc b/libstdc++-v3/testsuite/27_io/manipulators/standard/char/60270.cc new file mode 100644 index 000..b2b213b --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/manipulators/standard/char/60270.cc @@ -0,0 +1,38 @@ +// { dg-do run } +// { dg-options -std=gnu++14 } + +// Copyright (C) 2014 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 3, 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 COPYING3. If not see +// http://www.gnu.org/licenses/. + +// 27.7.6 - Quoted manipulators[quoted.manip] + +// libstdc++/60270 + +#include string +#include sstream +#include iomanip +#include testsuite_hooks.h + +int main() +{ + std::istringstream in; + std::string s = xxx; + in s; + VERIFY( !s.empty() ); + in std::quoted(s); + VERIFY( !s.empty() ); +} commit aeebd7a5d8e91d309070757e9732127e28527512 Author: redi redi@138bc75d-0d04-0410-961f-82ee72b054a4 Date: Mon Mar 31 18:16:14 2014 + * libsupc++/eh_ptr.cc: Improve static_assert messages. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208965 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc index 8c25a81..f974309 100644 --- a/libstdc++-v3/libsupc++/eh_ptr.cc +++ b/libstdc++-v3/libsupc++/eh_ptr.cc @@ -48,7 +48,8 @@ templatetypename Ex static_assert( termHandler__cxa_exception() == termHandler__cxa_dependent_exception(), - __cxa_dependent_exception::termHandler layout is correct ); + __cxa_dependent_exception::termHandler layout must be + consistent with __cxa_exception::termHandler ); #ifndef __ARM_EABI_UNWINDER__ templatetypename Ex @@ -57,7 +58,8 @@ templatetypename Ex static_assert( adjptr__cxa_exception() == adjptr__cxa_dependent_exception(), - __cxa_dependent_exception::adjustedPtr layout is correct ); + __cxa_dependent_exception::adjustedPtr layout must be + consistent with __cxa_exception::adjustedPtr ); #endif }
Re: std::rethrow_exception is broken
On 31/03/14 19:17 +0100, Jonathan Wakely wrote: This improves the static assertion messages, as suggested by François and Daniel. Tested x86_64-linux, committed to trunk. Oops, apparently mutt doesn't attach attachments until you actually send the mail, by which time the file I was attaching had changed! *This* improves the static assertion messages, not the last patch. commit 0aedd873a6ccc367bac38e1edc347f1774310ebe Author: Jonathan Wakely jwak...@redhat.com Date: Mon Mar 31 17:51:43 2014 +0100 * libsupc++/eh_ptr.cc: Improve static_assert messages. diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc index 8c25a81..f974309 100644 --- a/libstdc++-v3/libsupc++/eh_ptr.cc +++ b/libstdc++-v3/libsupc++/eh_ptr.cc @@ -48,7 +48,8 @@ templatetypename Ex static_assert( termHandler__cxa_exception() == termHandler__cxa_dependent_exception(), - __cxa_dependent_exception::termHandler layout is correct ); + __cxa_dependent_exception::termHandler layout must be + consistent with __cxa_exception::termHandler ); #ifndef __ARM_EABI_UNWINDER__ templatetypename Ex @@ -57,7 +58,8 @@ templatetypename Ex static_assert( adjptr__cxa_exception() == adjptr__cxa_dependent_exception(), - __cxa_dependent_exception::adjustedPtr layout is correct ); + __cxa_dependent_exception::adjustedPtr layout must be + consistent with __cxa_exception::adjustedPtr ); #endif }
Re: std::rethrow_exception is broken
On 25/03/14 17:25 +, Jonathan Wakely wrote: Tested x86_64-linux, I plan to commit this to trunk soon. commit 06a845f80204947afd6866109db58cc85dc87117 Author: Jonathan Wakely jwak...@redhat.com Date: Tue Mar 25 14:42:45 2014 + PR libstdc++/60612 * libsupc++/eh_ptr.cc: Assert __cxa_dependent_exception layout is compatible with __cxa_exception. * libsupc++/unwind-cxx.h (__cxa_dependent_exception): Add padding. Fix typos in comments. * testsuite/18_support/exception_ptr/60612-terminate.cc: New. * testsuite/18_support/exception_ptr/60612-unexpected.cc: New. Committed to trunk.
Re: std::rethrow_exception is broken
On 24/03/14 19:19 +, Jonathan Wakely wrote: There is a lot of code in libsupc++/eh_* that relies on __cxa_exception and __cxa_dependent_exception having similar layouts, so tricks like this work: static inline void* __gxx_caught_object(_Unwind_Exception* eo) { // Bad as it looks, this actually works for dependent exceptions too. __cxa_exception* header = __get_exception_header_from_ue (eo); return header-adjustedPtr; } The idea is that although the eo might be a pointer to the unwindHeader member of either __cxa_exception or __cxa_dependent_exception, the adjustedPtr member will be always be at the same location relative to the unwindHeader member, so it Just Works. Except it doesn't. offsetof(__cxa_exception, unwindHeader) == 80 offsetof(__cxa_dependent_exception, unwindHeader) == 80 offsetof(__cxa_exception, adjustedPtr) == 72 offsetof(__cxa_dependent_exception, adjustedPtr) == 64 Here's the output of GDB's pahole on __cxa_exception (gdb) pahole struct __cxxabiv1::__cxa_exception struct __cxxabiv1::__cxa_exception { /* 0 8 */std::type_info * exceptionType /* 8 8 */void (*)(void *) exceptionDestructor /* 16 8 */void (*)(void) unexpectedHandler /* 24 8 */void (*)(void) terminateHandler /* 32 8 */__cxxabiv1::__cxa_exception * nextException /* 40 4 */int handlerCount /* 44 4 */int handlerSwitchValue /* 48 8 */const unsigned char * actionRecord /* 56 8 */const unsigned char * languageSpecificData /* 64 8 */unsigned long catchTemp /* 72 8 */void * adjustedPtr /* 80 32 */ struct _Unwind_Exception { /* 0 8 */ unsigned long exception_class /* 8 8 */ void (*)(_Unwind_Reason_Code, _Unwind_Exception *) exception_cleanup /* 16 8 */ unsigned long private_1 /* 24 8 */ unsigned long private_2 } unwindHeader } And here's the current definition of __cxa_dependent_exception: (gdb) pahole struct __cxxabiv1::__cxa_dependent_exception struct __cxxabiv1::__cxa_dependent_exception { /* 0 8 */void * primaryException /* 8 8 */void (*)(void) unexpectedHandler /* 16 8 */void (*)(void) terminateHandler /* 24 8 */__cxxabiv1::__cxa_exception * nextException /* 32 4 */int handlerCount /* 36 4 */int handlerSwitchValue /* 40 8 */const unsigned char * actionRecord /* 48 8 */const unsigned char * languageSpecificData /* 56 8 */unsigned long catchTemp /* 64 8 */void * adjustedPtr /* XXX 64 bit hole, try to pack */ /* 80 32 */ struct _Unwind_Exception { /* 0 8 */ unsigned long exception_class /* 8 8 */ void (*)(_Unwind_Reason_Code, _Unwind_Exception *) exception_cleanup /* 16 8 */ unsigned long private_1 /* 24 8 */ unsigned long private_2 } unwindHeader } Notice the hole right before the unwindHeader member which is not there in __cxa_exception. All the member which are supposed to be at the same offsets as in __cxa_exception are 8 bytes earlier. The attached patch adds a __padding member near the start so changes that to: (gdb) pahole struct __cxxabiv1::__cxa_dependent_exception struct __cxxabiv1::__cxa_dependent_exception { /* 0 8 */void * primaryException /* 8 8 */void (*)(void *) __padding /* 16 8 */void (*)(void) unexpectedHandler /* 24 8 */void (*)(void) terminateHandler /* 32 8 */__cxxabiv1::__cxa_exception * nextException /* 40 4 */int handlerCount /* 44 4 */int handlerSwitchValue /* 48 8 */const unsigned char * actionRecord /* 56 8 */const unsigned char * languageSpecificData /* 64 8 */unsigned long catchTemp /* 72 8 */void * adjustedPtr /* 80 32 */ struct _Unwind_Exception { /* 0 8 */ unsigned long exception_class /* 8 8 */ void (*)(_Unwind_Reason_Code, _Unwind_Exception *) exception_cleanup /* 16 8 */ unsigned long private_1 /* 24 8 */ unsigned long private_2 } unwindHeader } That change allows all the pointer tricks in libsupc++/eh_*.cc to continue working. It's a change to the layout of a low-level type, which is not visible to users linking to libsupc++.so, but anyone linking statically will not be able to mix code using GCC 4.9's libsupc++.a with the libsupc++.a from previous versions if they use std::rethrow_exception() anywhere. Tested x86_64-linux, I plan to commit this to trunk soon. commit 06a845f80204947afd6866109db58cc85dc87117 Author: Jonathan Wakely jwak...@redhat.com Date: Tue Mar 25 14:42:45 2014 + PR libstdc++/60612 * libsupc++/eh_ptr.cc: Assert __cxa_dependent_exception layout is compatible with __cxa_exception. * libsupc++/unwind-cxx.h (__cxa_dependent_exception): Add padding. Fix typos in comments.
std::rethrow_exception is broken
There is a lot of code in libsupc++/eh_* that relies on __cxa_exception and __cxa_dependent_exception having similar layouts, so tricks like this work: static inline void* __gxx_caught_object(_Unwind_Exception* eo) { // Bad as it looks, this actually works for dependent exceptions too. __cxa_exception* header = __get_exception_header_from_ue (eo); return header-adjustedPtr; } The idea is that although the eo might be a pointer to the unwindHeader member of either __cxa_exception or __cxa_dependent_exception, the adjustedPtr member will be always be at the same location relative to the unwindHeader member, so it Just Works. Except it doesn't. offsetof(__cxa_exception, unwindHeader) == 80 offsetof(__cxa_dependent_exception, unwindHeader) == 80 offsetof(__cxa_exception, adjustedPtr) == 72 offsetof(__cxa_dependent_exception, adjustedPtr) == 64 This is the cause of PR 60612, and means we need to fix a lot of code by explicitly checking the exception class (see attached patch for a partial fix doing that in two places) or we need to change the layout of __cxa_dependent_exception (and then add some tests to verify the assumptions implicit in the code!) I don't think this is all fixable in time for 4.9.0, but the attached patch fixes one part of the problem, so I'm probably going to commit it and then work on a more complete fix later. commit 0e783c3897f1d1905bd64129e6eb9902a523626a Author: Jonathan Wakely jwak...@redhat.com Date: Mon Mar 24 12:30:20 2014 + PR libstdc++/60612 * libsupc++/eh_call.cc (__cxa_call_terminate): Handle dependent exceptions. * libsupc++/eh_personality.cc (__cxa_call_unexpected): Likewise. * libsupc++/unwind-cxx.h: Fix typos in comments. * testsuite/18_support/exception_ptr/60612-terminate.cc: New. * testsuite/18_support/exception_ptr/60612-unexpected.cc: New. diff --git a/libstdc++-v3/libsupc++/eh_call.cc b/libstdc++-v3/libsupc++/eh_call.cc index 7677692..ac75813 100644 --- a/libstdc++-v3/libsupc++/eh_call.cc +++ b/libstdc++-v3/libsupc++/eh_call.cc @@ -48,10 +48,12 @@ __cxa_call_terminate(_Unwind_Exception* ue_header) throw () // exception. */ if (__is_gxx_exception_class(ue_header-exception_class)) { - __cxa_exception* xh; - - xh = __get_exception_header_from_ue(ue_header); - __terminate(xh-terminateHandler); + std::terminate_handler th; + if (__is_dependent_exception(ue_header-exception_class)) + th = __get_dependent_exception_from_ue(ue_header)-terminateHandler; + else + th = __get_exception_header_from_ue(ue_header)-terminateHandler; + __terminate(th); } } /* Call the global routine if we don't have anything better. */ diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc index f315a83..698dc7d 100644 --- a/libstdc++-v3/libsupc++/eh_personality.cc +++ b/libstdc++-v3/libsupc++/eh_personality.cc @@ -737,20 +737,35 @@ __cxa_call_unexpected (void *exc_obj_in) } end_catch_protect_obj; lsda_header_info info; - __cxa_exception *xh = __get_exception_header_from_ue (exc_obj); const unsigned char *xh_lsda; _Unwind_Sword xh_switch_value; std::terminate_handler xh_terminate_handler; - + std::unexpected_handler xh_unexpected_handler; // If the unexpectedHandler rethrows the exception (e.g. to categorize it), // it will clobber data about the current handler. So copy the data out now. - xh_lsda = xh-languageSpecificData; - xh_switch_value = xh-handlerSwitchValue; - xh_terminate_handler = xh-terminateHandler; - info.ttype_base = (_Unwind_Ptr) xh-catchTemp; + if (__is_dependent_exception(exc_obj-exception_class)) +{ + __cxa_dependent_exception *xh = __get_dependent_exception_from_ue (exc_obj); + + xh_lsda = xh-languageSpecificData; + xh_switch_value = xh-handlerSwitchValue; + xh_terminate_handler = xh-terminateHandler; + xh_unexpected_handler = xh-unexpectedHandler; + info.ttype_base = (_Unwind_Ptr) xh-catchTemp; +} + else +{ + __cxa_exception *xh = __get_exception_header_from_ue (exc_obj); + + xh_lsda = xh-languageSpecificData; + xh_switch_value = xh-handlerSwitchValue; + xh_terminate_handler = xh-terminateHandler; + xh_unexpected_handler = xh-unexpectedHandler; + info.ttype_base = (_Unwind_Ptr) xh-catchTemp; +} __try -{ __unexpected (xh-unexpectedHandler); } +{ __unexpected (xh_unexpected_handler); } __catch(...) { // Get the exception thrown from unexpected. diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h index a7df603..1ca6d94 100644 --- a/libstdc++-v3/libsupc++/unwind-cxx.h +++ b/libstdc++-v3/libsupc++/unwind-cxx.h @@ -81,7 +81,7 @@ struct __cxa_exception // Stack of exceptions in cleanups. __cxa_exception* nextPropagatingException; - // The nuber of active cleanup handlers