https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85222
--- Comment #5 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 5 Apr 2018, redi at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85222 > > --- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> --- > (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.