diff mbox series

PR libstdc++/85222 allow catching iostream errors as gcc4-compatible ios::failure

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

Commit Message

Jonathan Wakely April 9, 2018, 11:36 p.m. UTC
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.
commit bdcc071eaa58aa07824b01a6da64662787abece7
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Apr 10 00:19:25 2018 +0100

    PR libstdc++/85222 allow catching iostream errors as gcc4-compatible ios::failure
    
    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.

Comments

Richard Biener April 10, 2018, 7:42 a.m. UTC | #1
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.
Jonathan Wakely April 12, 2018, 4:04 p.m. UTC | #2
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>
Jonathan Wakely April 12, 2018, 8:55 p.m. UTC | #3
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,
Jonathan Wakely April 13, 2018, 10:19 a.m. UTC | #4
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
Jakub Jelinek April 13, 2018, 10:22 a.m. UTC | #5
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
Jonathan Wakely April 13, 2018, 10:55 a.m. UTC | #6
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 mbox series

Patch

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() );