On 7/20/26 2:25 PM, Oleg Tolmatcev wrote:
Constructor decloning can turn the C1/C2 entry points into thunks
that call the unified primary constructor, C4.

Yes.

That works only if C4 remains a usable external interface.

Or if we avoid external references to C4.

For libstdc++ explicit instantiations on MinGW, that is not the case:
libstdc++ exports the complete and base constructor entry points, but
not the unified C4 symbol.  With -Os this could leave user code with
references to an undefined C4 constructor, as in PR libstdc++/125359.
Avoid the thunking path for constructors in maybe_clone_body.  Keep
constructor clones as real bodies so callers continue to target C1/C2
instead of the unified primary constructor.

This is just breaking -fdeclone-ctor-dtor, which is not generally desirable.

But why are we getting external references to C4 instead of to C1?

I can see the same failure on x86_64-pc-linux-gnu if I change can_alias_cdtor to always return false.

I suspect the problem is that we instantiate the constructor for inlining, and we inline the C1 thunk, but then decide not to inline the C4 constructor, and don't realize that this means we can't inline C1 either. This is particularly broken on targets with COMDAT groups, as then the C4 function is an internal symbol.

gcc/cp/ChangeLog:

        PR libstdc++/125359
        * optimize.cc (maybe_clone_body): Do not thunk constructor clones
        through the unified primary constructor.

  gcc/testsuite/ChangeLog:

        PR libstdc++/125359
        * g++.dg/ext/pr125359.C: New test.

This seems more like a library test; for a compiler test it needs to be reduced to not depend so much on the library headers.

Jason

Reply via email to