On 9/27/26 6:02 PM, Iain Sandoe wrote:
On 27 Sep 2026, at 21:13, Jason Merrill <[email protected]> wrote:
On 9/27/26 1:12 PM, Iain Sandoe wrote:
Hi Jason,
On 27 Sep 2026, at 17:59, Jason Merrill <[email protected]> wrote:
On 9/27/26 11:01 AM, Iain Sandoe wrote:
While chasing two testsuite fails for -Os this wrong-code bug surfaced.
Fix tested on x86_64-linux/darwin. OK for trunk / backports?
thanks
Iain
--- 8< ---
For Darwin, at least, when -Os is selected we attempt to declone cdtors
since the platform does not support strong symbol aliases the clones
are emitted verbatim, leading to larger binaries.
The unified cdtor is a private implementational detail local to a TU
and so we should not emit a thunk if that will not be emitted.
Hmm, isn't the unified ctor linkonce when the separate ctors are?
The bug I was seeing was that the thunk got inlined leaving a reference to
a C4 that was not emitted; It is quite hard to reproduce since it requires the
right combination of sizes - but the libstdc++ testsuite triggers it reliably
(was
just not able to simplify that). Maybe your comment means that there’s
another issue (although the prohibition of the vague-linkage solves it, perhaps
that’s a side-effect).
Likewise, a thunk and the unified body must be selected together at
link time; for a vague-linkage cdtor COMDAT groups support this but,
without COMDAT, there is no guarantee and so we have to decline the
declone and emit ordinary clones instead.
It's desirable that they are selected together, but is it really necessary? As
long as one is selected, I'd think they should work interchangeably.
In principle, I suppose so - they are all supposed to be token-identical (let’s
not get into the ‘different TUs with different opts’).
So long as the call to the thunkee is properly indirected (either through the
GOT [64b] or a machopic indirect symbol [32b]), the static linker should be ok.
If the call goes directly we would get a warning.
Not sure exactly what avenue to explore on this - it’s a real end-user issue
since -Os is a “recommended setting” on the platform.
This sounds like a duplicate of 125359. As I wrote in response to a patch a
few months ago which would have similarly disabled -fdeclone-ctor-dtor:
--
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.
--
I imagine this breaks with libstdc++ specifically because the extern template
causes us to avoid emitting an out-of-line copy of the C4, and instead
referring to the one in the library...but there isn't one, because the library
wasn't built with -fdeclone-ctor-dtor. Or, on a platform with COMDAT groups,
because it's an internal symbol anyway.
Yes that all stacks up with what I’m seeing.
It seems that what’s needed is a statement of dependency - if the thunk is
built then
- either c4 must be emitted (private to the TU)
- or the thunk must not be inlined without also inlining c4.
So it seems that we should never be refusing to emit a c4 if a thunk refers to
it?
- one strategy would be to mark the c4 at the point we decide to have the
thunk (mark_needed, maybe?)
This sounds like ignoring the extern template declaration, which seems
wrong.
- another strategy would be to teach the middle end that it cannot inline a
thunk to a c4 if the c4 is not also inlinable (if the cicumstance is
recognisable).
I think this is a better direction. Really, we shouldn't inline any
thunk if we can't inline its target
Although that still needs an emitted local c4 to work,
I don't see why; if we don't inline the c4, and therefore don't inline
c1, we refer to the c1 in the library however it's implemented and no c4
needs to be emitted anywhere.
I will continue in the PR, for now - but welcome any guidance about viability
of those two approaches (or suggested alternates).
thanks
Iain
Jason