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