PR libstdc++/85222 allow catching iostream errors as gcc4-compatible ios::failure
authorJonathan Wakely <jwakely@redhat.com>
Tue, 10 Apr 2018 14:36:09 +0000 (15:36 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 10 Apr 2018 14:36:09 +0000 (15:36 +0100)
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.

From-SVN: r259281

18 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/src/c++11/Makefile.am
libstdc++-v3/src/c++11/Makefile.in
libstdc++-v3/src/c++11/cxx11-ios_failure.cc
libstdc++-v3/src/c++11/ios.cc
libstdc++-v3/src/c++98/ios_failure.cc
libstdc++-v3/testsuite/27_io/basic_ios/copyfmt/char/1.cc
libstdc++-v3/testsuite/27_io/basic_ios/exceptions/char/1.cc
libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/exceptions_failbit.cc
libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/wchar_t/exceptions_failbit.cc
libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/char/exceptions_null.cc
libstdc++-v3/testsuite/27_io/basic_istream/extractors_other/wchar_t/exceptions_null.cc
libstdc++-v3/testsuite/27_io/basic_istream/sentry/char/12297.cc
libstdc++-v3/testsuite/27_io/basic_istream/sentry/wchar_t/12297.cc
libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/char/exceptions_null.cc
libstdc++-v3/testsuite/27_io/basic_ostream/inserters_other/wchar_t/exceptions_null.cc
libstdc++-v3/testsuite/27_io/ios_base/failure/dual_abi.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/ios_base/storage/2.cc

index 1d6fd8948713dbac0a787d69468fddc8eea02456..d9e790da8992f5fefc557612005cac28b2dd254c 100644 (file)
@@ -1,3 +1,36 @@
+2018-04-10  Jonathan Wakely  <jwakely@redhat.com>
+
+       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.
+
 2018-04-05  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/std/variant (_VARIANT_RELATION_FUNCTION_TEMPLATE): Qualify
index b0eaac2640a0d3ebbdb2746a89f5ff80ae569af1..6f49f0d55d391acacc4e29ed6d1c349c0880160f 100644 (file)
@@ -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
index e7db8ae09c82a26a9ed3011268f1517d2429ae7f..26833b04b424638b8c301fd47bd2077ef7b6f156 100644 (file)
@@ -434,6 +434,13 @@ sources = \
 
 libc__11convenience_la_SOURCES = $(sources)  $(inst_sources)
 
+# Rewrite the type info for __dual_abi_ios_failure.
+@ENABLE_DUAL_ABI_TRUE@rewrite_ios_failure_typeinfo = sed -e '/^_ZTISt13__ios_failure:$$/{' \
+@ENABLE_DUAL_ABI_TRUE@ -e 'n' \
+@ENABLE_DUAL_ABI_TRUE@ -e 's/_ZTVN10__cxxabiv120__si_class_type_infoE/_ZTVSt19__iosfail_type_info/' \
+@ENABLE_DUAL_ABI_TRUE@ -e '}'
+
+
 # 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
@@ -749,6 +756,21 @@ hashtable_c++0x.lo: hashtable_c++0x.cc
 hashtable_c++0x.o: hashtable_c++0x.cc
        $(CXXCOMPILE) -fimplicit-templates -c $<
 
+@ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure-lt.s: cxx11-ios_failure.cc
+@ENABLE_DUAL_ABI_TRUE@ $(LTCXXCOMPILE) -S $< -o tmp-cxx11-ios_failure-lt.s
+@ENABLE_DUAL_ABI_TRUE@ -test -f tmp-cxx11-ios_failure-lt.o && mv -f tmp-cxx11-ios_failure-lt.o tmp-cxx11-ios_failure-lt.s
+@ENABLE_DUAL_ABI_TRUE@ $(rewrite_ios_failure_typeinfo) tmp-$@ > $@
+@ENABLE_DUAL_ABI_TRUE@ -rm -f tmp-$@
+@ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure.s: cxx11-ios_failure.cc
+@ENABLE_DUAL_ABI_TRUE@ $(CXXCOMPILE) -S $< -o tmp-$@
+@ENABLE_DUAL_ABI_TRUE@ $(rewrite_ios_failure_typeinfo) tmp-$@ > $@
+@ENABLE_DUAL_ABI_TRUE@ -rm -f tmp-$@
+
+@ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure.lo: cxx11-ios_failure-lt.s
+@ENABLE_DUAL_ABI_TRUE@ $(LTCXXCOMPILE) -c $< -o $@
+@ENABLE_DUAL_ABI_TRUE@cxx11-ios_failure.o: cxx11-ios_failure.s
+@ENABLE_DUAL_ABI_TRUE@ $(CXXCOMPILE) -c $<
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
index 3820fcda67a8f495f384a2f3c05911885e3de787..847b5946234b8ac9f106b73908a074b8953c7e08 100644 (file)
 
 #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
index 1b0e6a9b3f2f06fcb14e5cf28c00187703a9d4da..e928c5941496d75d7ea6ebea972b214bdc813040 100644 (file)
 
 #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;
index a453be3a0b3fb4ce039b96872336afde4a4bfe5f..a2fc5593e15ef94dc0fe2ee61d0c568e8bf0f016 100644 (file)
 #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
index ee28afaad43f41cca5966839c377cfc8accb4587..8bcd875b563ea027949fa704f65beea3c549d91d 100644 (file)
@@ -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(...) {
index bbe4bf913986dc897ac81b1e4fddda7840f75ea0..960ae2767b66715ce5492f49ba036af3cd3e9a32 100644 (file)
@@ -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) );
     }
index bf96bbaa038718bfdb3a9fa5ab20b92371452f7e..584c278a47b729b80641f65e17d646acbb449515 100644 (file)
@@ -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() );
index 4883d6347eba4b3ac742a5a78ee8b4345cd8420d..ca0e8b1086ed32c6341e76227b60bf36a4551923 100644 (file)
@@ -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() );
index 5133b40daa2505b99a0e9519e87a7abaf6630dbd..498ab21b0e9d2253878699f0b7f907fddd17ece7 100644 (file)
@@ -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&)
     {
     }
 
index 05fedd024198894a58917288f831c0cee47cc86a..0c10ec628aadc312a0283f211a0bc5d7dac5dcc2 100644 (file)
@@ -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&)
     {
     }
 
index a5a2dfbaeefdcf8a532a7823e29640d0c0fd2269..c808cb705ac621c7eda4939cfcb8808048124a35 100644 (file)
@@ -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) );
     }
index ec7ed9aa3d6bb8057be1ff8c866a237b610cff39..a5e03ae5cdaf246a6d457c2e9ef9cca62cab63f5 100644 (file)
@@ -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) );
     }
index 4fc00edec0dc261034529d3d7f026155432b4354..515c6beb04c05c66851e5b5bd652e0a70d4a5422 100644 (file)
@@ -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&)
     {
     }
 
index 685e650be286535763dabc062474ce8ee9e97e93..25dfa307e8b72b498c90c184694f7ec03ec40fdd 100644 (file)
@@ -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 (file)
index 0000000..9bd72a1
--- /dev/null
@@ -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();
+}
index e0f783e6c334c3e10599a46960854acf35019248..6a064e26977e05938064c587c3490f35face85b7 100644 (file)
@@ -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() );