https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145
--- Comment #34 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Richard Biener from comment #33) > Probably impossible to fix without breaking the ABI again, but there should > have been two __throw_ios_failure entries (and callers be "versioned" as > well). I considered that, but for 99.99% of cases the caller is inside libstdc++.so not in user code (because the iostream classes are explicitly instantiated in the library), so there's no much point. The library is still only going to call one symbol, either the old one or the new one. For the other 0.01% of calls, having two versions of the function would be an ODR violation, which in practice would mean that non-inlined calls from different translation units have vague linkage and the linker discards all but one copy, which you'd have no control over whether it keeps a copy calling the new version or the old. To version the calls would have required either versioning the entire iostream hierarchy (and having two or each of std::cout, std::cin, std::cerr, and std::clog) or some nasty hack like every iostreams operation setting a thread-local variable to note whether the caller was new code or old code, and check that flag when throwing to decide which type to throw. But even that wouldn't be right, because the caller might be using one ABI and the location of the catch be using the other one. There's no good solution. > At least the old symbol should have been preserved as backward compatible > and a new with a new version be added ... should have been ... Maybe, but again, since the caller is (almost always) in the library not in user code, the old symbol would never be called. Although __throw_ios_failure() is visible to user code, they shouldn't ever be calling it directly. It's not a public API.