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.

Reply via email to