Message ID | CAH6eHdQUaz7Gd5bjQEX1hpTBvtg2ugu+CbPEwJpuYX4KzH0vnQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | PR libstdc++/85222 allow catching iostream errors as gcc4-compatible ios::failure | expand |
On Tue, 10 Apr 2018, Jonathan Wakely wrote: > Define a new exception type derived from std::ios::failure[abi:cxx11] > which also aggregates an object of the gcc4-compatible ios::failure > type. Make __throw_ios_failure throw this new type for iostream errors > that raise exceptions. Provide custom type info for the new type so that > it can be caught by handlers for the gcc4-compatible ios::failure type > as well as handlers for ios::failure[abi:cxx11] and its bases. > > PR libstdc++/85222 > * src/c++11/Makefile.am [ENABLE_DUAL_ABI]: Add special rules for > cxx11-ios_failure.cc to rewrite type info for __ios_failure. > * src/c++11/Makefile.in: Regenerate. > * src/c++11/cxx11-ios_failure.cc (__ios_failure, __iosfail_type_info): > New types. > [_GLIBCXX_USE_DUAL_ABI] (__throw_ios_failure): Define here. > * src/c++11/ios.cc (__throw_ios_failure): Remove definition. > * src/c++98/ios_failure.cc (__construct_ios_failure) > (__destroy_ios_failure, is_ios_failure_handler): New functions. > [!_GLIBCXX_USE_DUAL_ABI] (__throw_ios_failure): Define here. > * testsuite/27_io/ios_base/failure/dual_abi.cc: New. > * testsuite/27_io/basic_ios/copyfmt/char/1.cc: Revert changes to > handler types, to always catch std::ios_base::failure. > * testsuite/27_io/basic_ios/exceptions/char/1.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_arithmetic/char/ > exceptions_failbit.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/ > exceptions_failbit.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_other/char/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_other/wchar_t/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_istream/sentry/char/12297.cc: Likewise. > * testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc: Likewise. > * testsuite/27_io/basic_ostream/inserters_other/char/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_ostream/inserters_other/wchar_t/ > exceptions_null.cc: Likewise. > * testsuite/27_io/ios_base/storage/2.cc: Likewise. > > Tested x86_64-linux and powerpc64-linux, with the default config, and > --disable-libstdcxx-dual-abi, and > --with-default-libstdcxx-abi=gcc4-compatible. I intend to commit this > to trunk and gcc-7-branch soon. Thanks for working on this! Richard.
On 10 April 2018 at 00:36, Jonathan Wakely wrote: > Define a new exception type derived from std::ios::failure[abi:cxx11] > which also aggregates an object of the gcc4-compatible ios::failure > type. Make __throw_ios_failure throw this new type for iostream errors > that raise exceptions. Provide custom type info for the new type so that > it can be caught by handlers for the gcc4-compatible ios::failure type > as well as handlers for ios::failure[abi:cxx11] and its bases. > > PR libstdc++/85222 > * src/c++11/Makefile.am [ENABLE_DUAL_ABI]: Add special rules for > cxx11-ios_failure.cc to rewrite type info for __ios_failure. > * src/c++11/Makefile.in: Regenerate. > * src/c++11/cxx11-ios_failure.cc (__ios_failure, __iosfail_type_info): > New types. > [_GLIBCXX_USE_DUAL_ABI] (__throw_ios_failure): Define here. > * src/c++11/ios.cc (__throw_ios_failure): Remove definition. > * src/c++98/ios_failure.cc (__construct_ios_failure) > (__destroy_ios_failure, is_ios_failure_handler): New functions. > [!_GLIBCXX_USE_DUAL_ABI] (__throw_ios_failure): Define here. > * testsuite/27_io/ios_base/failure/dual_abi.cc: New. > * testsuite/27_io/basic_ios/copyfmt/char/1.cc: Revert changes to > handler types, to always catch std::ios_base::failure. > * testsuite/27_io/basic_ios/exceptions/char/1.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_arithmetic/char/ > exceptions_failbit.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/ > exceptions_failbit.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_other/char/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_istream/extractors_other/wchar_t/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_istream/sentry/char/12297.cc: Likewise. > * testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc: Likewise. > * testsuite/27_io/basic_ostream/inserters_other/char/ > exceptions_null.cc: Likewise. > * testsuite/27_io/basic_ostream/inserters_other/wchar_t/ > exceptions_null.cc: Likewise. > * testsuite/27_io/ios_base/storage/2.cc: Likewise. > > Tested x86_64-linux and powerpc64-linux, with the default config, and > --disable-libstdcxx-dual-abi, and > --with-default-libstdcxx-abi=gcc4-compatible. I intend to commit this > to trunk and gcc-7-branch soon. This removes the #define for _GLIBCXX_USE_CXX11_ABI from the top of src/c++11/ios.cc, because __throw_ios_failure is no longer defined there. Tested as before, committed to trunk. commit 845d8dc521d0958b625f2bc691b284e221009929 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Apr 11 13:47:31 2018 +0100 Remove #define made redundant by r259281 The definition of __throw_ios_failure is no longer in this file, so setting the macro here is unnecessary. * src/c++11/ios.cc: Remove redundant macro definition. diff --git a/libstdc++-v3/src/c++11/ios.cc b/libstdc++-v3/src/c++11/ios.cc index e928c594149..82063e4b2f5 100644 --- a/libstdc++-v3/src/c++11/ios.cc +++ b/libstdc++-v3/src/c++11/ios.cc @@ -26,10 +26,6 @@ // ISO C++ 14882: 27.4 Iostreams base classes // -// Determines the version of ios_base::failure thrown by __throw_ios_failure. -// If !_GLIBCXX_USE_DUAL_ABI this will get undefined automatically. -#define _GLIBCXX_USE_CXX11_ABI 1 - #include <ios> #include <limits>
This fixes some comments with misspelled files and classes. Committed to trunk and gcc-7-branch. It occurred to me that the name of the new __ios_failure type is visible in the verbose terminate handler messages: terminate called after throwing an instance of 'std::__ios_failure' what(): basic_filebuf::underflow error reading the file: Is a directory Aborted (core dumped) And that there's no need for this type to use a reserved name. Users can't refer to it, or define macros that affect it (because it's never exposed in headers). So we could call it something else, like std::ios_failure rather than std::__ios_failure. Anybody got a preference they want to argue for? commit a28bcba2a812d4eac6da8ce86907b670361a09a6 Author: Jonathan Wakely <jwakely@redhat.com> Date: Thu Apr 12 21:28:38 2018 +0100 Fix comments that misspell names of files and classes * src/c++11/Makefile.am: Fix comment. * src/c++11/Makefile.in: Regenerate. * src/c++11/cxx11-ios_failure.cc: Fix comment. * src/c++98/ios_failure.cc: Likewise. diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 6f49f0d55d3..8d524b67232 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -127,7 +127,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -fimplicit-templates -c $< if ENABLE_DUAL_ABI -# Rewrite the type info for __dual_abi_ios_failure. +# Rewrite the type info for __ios_failure. rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \ -e 'n' \ -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \ diff --git a/libstdc++-v3/src/c++11/cxx11-ios_failure.cc b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc index 847b5946234..b1e4bfb2b44 100644 --- a/libstdc++-v3/src/c++11/cxx11-ios_failure.cc +++ b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc @@ -140,7 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __ios_failure can be upcast to the type in a catch handler. bool __iosfail_type_info::__do_upcast(const __class_type_info *dst_type, - void **obj_ptr) const + void **obj_ptr) const { // If the handler is for the gcc4-compatible ios::failure type then // catch the object stored in __ios_failure::buf instead of @@ -150,7 +150,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION *obj_ptr = static_cast<__ios_failure*>(*obj_ptr)->buf; return true; } - // Otherwise proceeed as normal to see if the handler matches. + // Otherwise proceed as normal to see if the handler matches. return __class_type_info::__do_upcast(dst_type, obj_ptr); } #else // ! __cpp_rtti diff --git a/libstdc++-v3/src/c++98/ios_failure.cc b/libstdc++-v3/src/c++98/ios_failure.cc index a2fc5593e15..49d24f49620 100644 --- a/libstdc++-v3/src/c++98/ios_failure.cc +++ b/libstdc++-v3/src/c++98/ios_failure.cc @@ -57,7 +57,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if _GLIBCXX_USE_DUAL_ABI // When the dual ABI is enabled __throw_ios_failure() is defined in - // src/c++11/ios_failure.cc + // src/c++11/cxx11-ios_failure.cc #if __cpp_rtti // If RTTI is enabled the exception type thrown will use these functions to // construct/destroy a gcc4-compatible ios::failure object in a buffer,
Darwin has double underscores at the start of mangled names, so this fixes the sed command to be more flexible. Committed to trunk and gcc-7-branch. commit f80944837b4c21016d826bff5f497ceda85b9894 Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Apr 13 10:44:08 2018 +0100 Fix __iosfail_type_info hack to work on darwin * src/c++11/Makefile.am: Rewrite sed rule to be less fragile and to handle mangled names starting with double underscores on darwin. * src/c++11/Makefile.in: Regenerate. diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 8d524b67232..12bc004a2ea 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -128,10 +128,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc if ENABLE_DUAL_ABI # Rewrite the type info for __ios_failure. -rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \ - -e 'n' \ - -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \ - -e '}' +rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' cxx11-ios_failure-lt.s: cxx11-ios_failure.cc $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s
On Fri, Apr 13, 2018 at 11:19:35AM +0100, Jonathan Wakely wrote: > --- a/libstdc++-v3/src/c++11/Makefile.am > +++ b/libstdc++-v3/src/c++11/Makefile.am > @@ -128,10 +128,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc > > if ENABLE_DUAL_ABI > # Rewrite the type info for __ios_failure. > -rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \ > - -e 'n' \ > - -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \ > - -e '}' > +rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' I miss / in between , and _ZTVN10__cxxabiv120__si_class_type_infoE $ echo | sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_info_ZTVSt19__iosfail_type_info/' sed: -e expression #1, char 29: unexpected `,' $ echo | sed -e '/^_*_ZTISt13__ios_failure:/,/_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' Jakub
On 13 April 2018 at 11:22, Jakub Jelinek wrote: > On Fri, Apr 13, 2018 at 11:19:35AM +0100, Jonathan Wakely wrote: >> --- a/libstdc++-v3/src/c++11/Makefile.am >> +++ b/libstdc++-v3/src/c++11/Makefile.am >> @@ -128,10 +128,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc >> >> if ENABLE_DUAL_ABI >> # Rewrite the type info for __ios_failure. >> -rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \ >> - -e 'n' \ >> - -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \ >> - -e '}' >> +rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' > > I miss / in between , and _ZTVN10__cxxabiv120__si_class_type_infoE > > $ echo | sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_info_ZTVSt19__iosfail_type_info/' > sed: -e expression #1, char 29: unexpected `,' > $ echo | sed -e '/^_*_ZTISt13__ios_failure:/,/_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' > > Jakub Not sure how that got past my testing, so I've made sure to test with a clean build this time. Committed to trunk and gcc-7-branch. commit 6b12637ba78f29a2a697d3fb78e3e23076d8dee4 Author: Jonathan Wakely <jwakely@redhat.com> Date: Fri Apr 13 11:30:48 2018 +0100 Fix broken sed command from previous commit * src/c++11/Makefile.am: Fix sed command. * src/c++11/Makefile.in: Regenerate. diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index 12bc004a2ea..cdc49bb7f9b 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -128,7 +128,7 @@ hashtable_c++0x.o: hashtable_c++0x.cc if ENABLE_DUAL_ABI # Rewrite the type info for __ios_failure. -rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' +rewrite_ios_failure_typeinfo = sed -e '/^_*_ZTISt13__ios_failure:/,/_ZTVN10__cxxabiv120__si_class_type_infoE/s/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' cxx11-ios_failure-lt.s: cxx11-ios_failure.cc $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am index b0eaac2640a..6f49f0d55d3 100644 --- a/libstdc++-v3/src/c++11/Makefile.am +++ b/libstdc++-v3/src/c++11/Makefile.am @@ -126,6 +126,29 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -fimplicit-templates -c $< +if ENABLE_DUAL_ABI +# Rewrite the type info for __dual_abi_ios_failure. +rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \ + -e 'n' \ + -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \ + -e '}' + +cxx11-ios_failure-lt.s: cxx11-ios_failure.cc + $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s + -test -f tmp-cxx11-ios_failure-lt.o && mv -f tmp-cxx11-ios_failure-lt.o tmp-cxx11-ios_failure-lt.s + $(rewrite_ios_failure_typeinfo) tmp-$@ > $@ + -rm -f tmp-$@ +cxx11-ios_failure.s: cxx11-ios_failure.cc + $(CXXCOMPILE) -S $< -o tmp-$@ + $(rewrite_ios_failure_typeinfo) tmp-$@ > $@ + -rm -f tmp-$@ + +cxx11-ios_failure.lo: cxx11-ios_failure-lt.s + $(LTCXXCOMPILE) -c $< -o $@ +cxx11-ios_failure.o: cxx11-ios_failure.s + $(CXXCOMPILE) -c $< +endif + # AM_CXXFLAGS needs to be in each subdirectory so that it can be # modified in a per-library or per-sub-library way. Need to manually # set this option because CONFIG_CXXFLAGS has to be after diff --git a/libstdc++-v3/src/c++11/cxx11-ios_failure.cc b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc index 3820fcda67a..847b5946234 100644 --- a/libstdc++-v3/src/c++11/cxx11-ios_failure.cc +++ b/libstdc++-v3/src/c++11/cxx11-ios_failure.cc @@ -28,6 +28,15 @@ #define _GLIBCXX_USE_CXX11_ABI 1 #include <ios> +#include <bits/functexcept.h> +#include <cxxabi.h> + +#ifdef _GLIBCXX_USE_NLS +# include <libintl.h> +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif #if ! _GLIBCXX_USE_DUAL_ABI # error This file should not be compiled for this configuration. @@ -91,5 +100,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ios_base::failure::what() const throw() { return runtime_error::what(); } +#if __cpp_rtti + // These functions are defined in src/c++98/ios_failure.cc + extern void __construct_ios_failure(void*, const char*); + extern void __destroy_ios_failure(void*); + extern bool __is_ios_failure_handler(const __cxxabiv1::__class_type_info*); + + // The type thrown to report errors during stream buffer operations. + // In addition to the ios::failure[abi:cxx11] base class it also has a + // member of the gcc4-compatible ios::failure type (in an opaque buffer). + struct __ios_failure : std::ios::failure + { + __ios_failure(const char* s) : failure(s) + { __construct_ios_failure(buf, runtime_error::what()); } + + ~__ios_failure() + { __destroy_ios_failure(buf); } + + // Use std::runtime_error as a proxy for the gcc4-compatible ios::failure + // (which can't be declared here because _GLIBCXX_USE_CXX11_ABI == 1). + // There are assertions in src/c++98/ios_failure.cc to ensure the size + // and alignment assumptions are valid. + alignas(runtime_error) unsigned char buf[sizeof(runtime_error)]; + }; + + // Custom type info for __ios_failure. + class __iosfail_type_info : __cxxabiv1::__si_class_type_info + { + ~__iosfail_type_info(); + + bool + __do_upcast (const __class_type_info *dst_type, + void **obj_ptr) const override; + }; + + __iosfail_type_info::~__iosfail_type_info() = default; + + // This function gets called to see if an exception of type + // __ios_failure can be upcast to the type in a catch handler. + bool + __iosfail_type_info::__do_upcast(const __class_type_info *dst_type, + void **obj_ptr) const + { + // If the handler is for the gcc4-compatible ios::failure type then + // catch the object stored in __ios_failure::buf instead of + // the __ios_failure exception object itself. + if (__is_ios_failure_handler(dst_type)) + { + *obj_ptr = static_cast<__ios_failure*>(*obj_ptr)->buf; + return true; + } + // Otherwise proceeed as normal to see if the handler matches. + return __class_type_info::__do_upcast(dst_type, obj_ptr); + } +#else // ! __cpp_rtti + using __ios_failure = ios::failure; +#endif + + void + __throw_ios_failure(const char* __s __attribute__((unused))) + { _GLIBCXX_THROW_OR_ABORT(__ios_failure(_(__s))); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/src/c++11/ios.cc b/libstdc++-v3/src/c++11/ios.cc index 1b0e6a9b3f2..e928c594149 100644 --- a/libstdc++-v3/src/c++11/ios.cc +++ b/libstdc++-v3/src/c++11/ios.cc @@ -32,23 +32,11 @@ #include <ios> #include <limits> -#include <bits/functexcept.h> - -#ifdef _GLIBCXX_USE_NLS -# include <libintl.h> -# define _(msgid) gettext (msgid) -#else -# define _(msgid) (msgid) -#endif namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - void - __throw_ios_failure(const char* __s __attribute__((unused))) - { _GLIBCXX_THROW_OR_ABORT(ios_base::failure(_(__s))); } - // Definitions for static const members of ios_base. const ios_base::fmtflags ios_base::boolalpha; const ios_base::fmtflags ios_base::dec; diff --git a/libstdc++-v3/src/c++98/ios_failure.cc b/libstdc++-v3/src/c++98/ios_failure.cc index a453be3a0b3..a2fc5593e15 100644 --- a/libstdc++-v3/src/c++98/ios_failure.cc +++ b/libstdc++-v3/src/c++98/ios_failure.cc @@ -29,6 +29,18 @@ #define _GLIBCXX_USE_CXX11_ABI 0 #include <ios> +#if _GLIBCXX_USE_DUAL_ABI && __cpp_rtti +#include <cxxabi.h> +#include <typeinfo> +#endif + +#ifdef _GLIBCXX_USE_NLS +# include <libintl.h> +# define _(msgid) gettext (msgid) +#else +# define _(msgid) (msgid) +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -43,5 +55,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ios_base::failure::what() const throw() { return _M_msg.c_str(); } +#if _GLIBCXX_USE_DUAL_ABI + // When the dual ABI is enabled __throw_ios_failure() is defined in + // src/c++11/ios_failure.cc +#if __cpp_rtti + // If RTTI is enabled the exception type thrown will use these functions to + // construct/destroy a gcc4-compatible ios::failure object in a buffer, + // and to catch that object via a handler of the gcc4-compatible type. + void + __construct_ios_failure(void* buf, const char* msg) + { ::new(buf) ios_base::failure(msg); } + + void + __destroy_ios_failure(void* buf) + { static_cast<ios_base::failure*>(buf)->~failure(); } + + bool + __is_ios_failure_handler(const __cxxabiv1::__class_type_info* type) + { return *type == typeid(ios::failure); } + + namespace { + // C++98-style static assertions to ensure ios::failure fits in a buffer + // with the same size and alignment as runtime_error: + typedef char S[1 / (sizeof(ios::failure) <= sizeof(runtime_error))]; + typedef char A[1 / (__alignof(ios::failure) <= __alignof(runtime_error))]; + } +#endif // __cpp_rtti + +#else // ! _GLIBCXX_USE_DUAL_ABI + + void + __throw_ios_failure(const char* __s __attribute__((unused))) + { _GLIBCXX_THROW_OR_ABORT(ios::failure(_(__s))); } + +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/testsuite/27_io/basic_ios/copyfmt/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_ios/copyfmt/char/1.cc index ee28afaad43..8bcd875b563 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ios/copyfmt/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ios/copyfmt/char/1.cc @@ -46,13 +46,6 @@ void test02() } { - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - std::ios ios_01(0); std::ios ios_02(0); ios_01.clear(std::ios_base::eofbit); @@ -62,7 +55,7 @@ void test02() ios_01.copyfmt(ios_02); VERIFY( false ); } - catch(exception_type&) { + catch(std::ios_base::failure&) { VERIFY( true ); } catch(...) { diff --git a/libstdc++-v3/testsuite/27_io/basic_ios/exceptions/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_ios/exceptions/char/1.cc index bbe4bf91398..960ae2767b6 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ios/exceptions/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ios/exceptions/char/1.cc @@ -50,20 +50,13 @@ void test01() } { - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - std::ios ios_01(0); ios_01.clear(std::ios_base::eofbit); try { ios_01.exceptions(std::ios_base::eofbit); VERIFY( false ); } - catch(exception_type&) { + catch(std::ios_base::failure&) { iostate02 = ios_01.exceptions(); VERIFY( static_cast<bool>(iostate02 & std::ios_base::eofbit) ); } diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/exceptions_failbit.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/exceptions_failbit.cc index bf96bbaa038..584c278a47b 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/exceptions_failbit.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/exceptions_failbit.cc @@ -27,20 +27,13 @@ void test_failbit() istringstream stream("jaylib - champion sound"); stream.exceptions(ios_base::failbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { T i; stream >> i; VERIFY( false ); } - catch (const exception_type&) + catch (const std::ios_base::failure&) { // stream should set failbit and throw ios_base::failure. VERIFY( stream.fail() ); diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/exceptions_failbit.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/exceptions_failbit.cc index 4883d6347eb..ca0e8b1086e 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/exceptions_failbit.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/exceptions_failbit.cc @@ -27,20 +27,13 @@ void test_failbit() wistringstream stream(L"jaylib - champion sound"); stream.exceptions(ios_base::failbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { T i; stream >> i; VERIFY( false ); } - catch (const exception_type&) + catch (const std::ios_base::failure&) { // stream should set failbit and throw ios_base::failure. VERIFY( stream.fail() ); diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/exceptions_null.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/exceptions_null.cc index 5133b40daa2..498ab21b0e9 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/exceptions_null.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/exceptions_null.cc @@ -35,19 +35,12 @@ void test4() istringstream stream; stream.exceptions(ios_base::failbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { stream >> static_cast<streambuf*>(0); VERIFY(false); } - catch (exception_type&) + catch (std::ios_base::failure&) { } diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/exceptions_null.cc b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/exceptions_null.cc index 05fedd02419..0c10ec628aa 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/exceptions_null.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/exceptions_null.cc @@ -35,19 +35,12 @@ void test4() wistringstream stream; stream.exceptions(ios_base::failbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { stream >> static_cast<wstreambuf*>(0); VERIFY( false ); } - catch (exception_type&) + catch (std::ios_base::failure&) { } diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/12297.cc b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/12297.cc index a5a2dfbaeef..c808cb705ac 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/12297.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/12297.cc @@ -26,19 +26,12 @@ int main() istringstream stream; stream.exceptions(ios_base::eofbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { istream::sentry sentry(stream, false); VERIFY( false ); } - catch (exception_type&) + catch (std::ios_base::failure&) { VERIFY( stream.rdstate() == (ios_base::eofbit | ios_base::failbit) ); } diff --git a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc index ec7ed9aa3d6..a5e03ae5cda 100644 --- a/libstdc++-v3/testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc +++ b/libstdc++-v3/testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc @@ -26,19 +26,12 @@ int main() wistringstream stream; stream.exceptions(ios_base::eofbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { wistream::sentry sentry(stream, false); VERIFY( false ); } - catch (exception_type&) + catch (std::ios_base::failure&) { VERIFY( stream.rdstate() == (ios_base::eofbit | ios_base::failbit) ); } diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/exceptions_null.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/exceptions_null.cc index 4fc00edec0d..515c6beb04c 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/exceptions_null.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/exceptions_null.cc @@ -37,19 +37,12 @@ void test3() ostringstream stream; stream.exceptions(ios_base::badbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { stream << static_cast<streambuf*>(0); VERIFY( false ); } - catch (exception_type&) + catch (std::ios_base::failure&) { } diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/exceptions_null.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/exceptions_null.cc index 685e650be28..25dfa307e8b 100644 --- a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/exceptions_null.cc +++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/exceptions_null.cc @@ -37,19 +37,12 @@ void test3() wostringstream stream; stream.exceptions(ios_base::badbit); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { stream << static_cast<wstreambuf*>(0); VERIFY( false ); } - catch (exception_type&) + catch (std::ios_base::failure&) { } diff --git a/libstdc++-v3/testsuite/27_io/ios_base/failure/dual_abi.cc b/libstdc++-v3/testsuite/27_io/ios_base/failure/dual_abi.cc new file mode 100644 index 00000000000..9bd72a1baf9 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/ios_base/failure/dual_abi.cc @@ -0,0 +1,99 @@ +// Copyright (C) 2018 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/>. + +// { dg-options "-D_GLIBCXX_USE_CXX11_ABI=0" } +// { dg-do run { target c++11 } } + +#include <fstream> +#include <system_error> +#include <testsuite_hooks.h> + +void +test01() +{ + using std::ios; + bool caught_ios_failure = false; + bool rethrown = false; + bool caught_system_error = false; + try { + std::ifstream f; + f.exceptions(ios::failbit | ios::badbit | ios::eofbit); + try { + f.get(); + } + catch (const ios::failure&) // catch as old ABI type + { + caught_ios_failure = true; +#if _GLIBCXX_USE_DUAL_ABI || _GLIBCXX_USE_CXX11_ABI == 1 + rethrown = true; + throw; // re-throw, to catch as new ABI type +#endif + } + } + catch (const std::system_error& e) + { + caught_system_error = true; + } + + VERIFY( caught_ios_failure ); + if (rethrown) + VERIFY( caught_system_error ); +} + +void +test02() +{ + using std::ios; + const std::exception* p = nullptr; + bool caught_ios_failure = false; + bool caught_exception = false; + try { + std::ifstream f; + f.exceptions(ios::failbit | ios::badbit | ios::eofbit); + try { + f.get(); + } + catch (const std::exception& e1) + { + caught_exception = true; + p = &e1; + throw; + } + } + catch (const ios::failure& e2) + { + caught_ios_failure = true; +#if _GLIBCXX_USE_DUAL_ABI + // If the Dual ABI is active the library throws the new type, + // so e1 was an object of that new type and so &e1 != &e2. + VERIFY( p != &e2 ); +#else + // Otherwise there's only one type of ios::failure, so &e1 == &e2. + VERIFY( p == &e2 ); +#endif + } + + VERIFY( caught_exception ); + VERIFY( caught_ios_failure ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/27_io/ios_base/storage/2.cc b/libstdc++-v3/testsuite/27_io/ios_base/storage/2.cc index e0f783e6c33..6a064e26977 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base/storage/2.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base/storage/2.cc @@ -50,18 +50,11 @@ void test02() ios.pword(1) = v; VERIFY( ios.pword(1) == v ); - // The library throws the new definition of std::ios::failure -#if _GLIBCXX_USE_CXX11_ABI - typedef std::ios_base::failure exception_type; -#else - typedef std::exception exception_type; -#endif - try { v = ios.pword(max); } - catch(exception_type&) + catch(std::ios_base::failure&) { // Ok. VERIFY( ios.bad() ); @@ -80,7 +73,7 @@ void test02() { v = ios.pword(std::numeric_limits<int>::max()); } - catch(exception_type&) + catch(std::ios_base::failure&) { // Ok. VERIFY( ios.bad() ); @@ -99,7 +92,7 @@ void test02() { l = ios.iword(max); } - catch(exception_type&) + catch(std::ios_base::failure&) { // Ok. VERIFY( ios.bad() ); @@ -118,7 +111,7 @@ void test02() { l = ios.iword(std::numeric_limits<int>::max()); } - catch(exception_type&) + catch(std::ios_base::failure&) { // Ok. VERIFY( ios.bad() );