--- Comment #5 from rguenther at suse dot de <rguenther at suse dot de> ---
On Thu, 5 Apr 2018, redi at gcc dot wrote:

> --- Comment #4 from Jonathan Wakely <redi at gcc dot> ---
> (In reply to Richard Biener from comment #3)
> > Do you know of any other exception type affected by the c++11 vs. old ABI
> > issue or does the entire I/O hierarchy only ever throw exactly
> > ios_base::failure?
> That's the only one.
> > So a workaround would be to marshal these somehow in the C++ EH personality
> > routine?  The c++11 variant seems to be a superset feature-wise (apart from
> > the changed inheritance), so constructing (in-place?!) the c++98 variant
> > once we hit a filter for c++98 ios_base::failure with an EH object of
> > type ios_base::failure[c++11] would "work"?
> Until you try to rethrow it and catch it as the new type again.

Ok, but that would be an even more weird case of an intermediate
old-ABI object sitting inbetween the c++11 throwing libstdc++ and
a c++11 object.

> This approach was considered, and deemed not worth the complexity (and
> additional performance hit that would affect every 'catch' in every program
> that has to check if the catch handler is for ios::failure).

True.  But given we have broken things fixing it either requires
breaking the ABI for c++11 objects compiled with gcc 7 or leaving
things broken for objects compiled with gcc 3.4 to gcc 6.  Or
doing a hack like that.

My main concern is that the dual-ABI story breaks down in the current
situation where there isn't a single libstdc++ that makes both
situations work (catch c++11 ios_base::failure and c++98 
ios_base::failure).  So there's no way you can deploy the dual-ABI
libstdc++ on an existing system without possibly breaking old
programs (or not providing the C++11 ABI at all).  In fact
there isn't a good workaround forward to have both apart from
changing the SONAME for the C++11 ABI library or playing other
tricks via LD_LIBRARY_PATH or so.

> It would be possible to make __throw_ios_failure() throw:
> struct enhanced_failure : std::ios::failure {
>   unsigned char buf[sizeof old ios::failure];
> };
> This can be caught as the new type, and when there's an attempt to catch it as
> the old type, construct it in the buffer and catch the object in the buffer.
> Constructing it lazily can introduce a race condition, so it might be better 
> to
> always pre-propulate the buffer, just in case anybody wants to catch the old
> type.

So the old std::ios::failure doesn't fit in the new one?  As said
above I consider the re-throwing and catching as c++11 a situation
that shouldn't be required for fixing the "legacy" binary case.

Reply via email to