On 28/11/18 11:46 +0100, Richard Biener wrote:
On Wed, Nov 28, 2018 at 12:26 AM Jonathan Wakely <jwak...@redhat.com> wrote:

This resolves a longstanding issue where the lock policy for shared_ptr
reference counting depends on compilation options when the header is
included, so that different -march options can cause ABI changes. For
example, objects compiled with -march=armv7 will use atomics to
synchronize reference counts, and objects compiled with -march=armv5t
will use a mutex. That means the shared_ptr control block will have a
different layout in different objects, causing ODR violations and
undefined behaviour. This was the root cause of PR libstdc++/42734 as
well as PR libstdc++/67843.

The solution is to decide on the lock policy at build time, when
libstdc++ is configured. The configure script checks for the
availability of the necessary atomic built-ins for the target and fixes
that choice permanently. Different -march flags used to compile user
code will not cause changes to the lock policy. This results in an ABI
change for certain compilations, but only where there was already an ABI
incompatibility between the libstdc++.so library and objects built with
an incompatible -march option. In general, this means a more stable ABI
that isn't silently altered when -march flags make addition atomic ops
available.

To force a target to use "atomic" or "mutex" the new configure option
--with-libstdcxx-lock-policy can be used.

In order to turn ODR violations into linker errors, the uses of
shared_ptr in filesystem directory iterators have been replaced
with __shared_ptr, and explicit instantiations are declared. This
ensures that object files using those types cannot link to libstdc++
libs unless they use the same lock policy.

Would it be possible to have both in libstdc++ and with differnet mangling of
different kind ensure compatibility between different user CUs?  Or is
that too awkward for the user to get right?

It would mean duplicating a lot more code, which is already duplicated
once for the std::string ABI, so we'd have four permuations!

It still wouldn't ensure compatibility between different user CUs,
only between any user CU and any build of libstdc++. Different user
CUs would still disagree on the ABI of the types, and so couldn't pass
them between CUs. I see no advantage to supporting that for the
std::filesystem library (unlike std::string and std::iostream, which
are probably used in the majority of CUs).

I do not want to get to the point where every type in libstdc++ exists
multiple times and you select some combination via command-line flags.
It's already becoming unmanageable with multiple std::string and long
double ABIs.


Reply via email to