https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123405
Bug ID: 123405
Summary: LTO removes explicit section attribute from localized
COMDAT symbols
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: loki at loki dot codes
Target Milestone: ---
When a COMDAT symbol with an explicit [[gnu::section()]] attribute is localized
during LTO's visibility pass, the section is incorrectly removed.
In gcc/ipa-visibility.cc, localize_node() unconditionally clears the
section for COMDAT symbols:
if (DECL_COMDAT (node->decl) && !node->alias)
node->set_section (NULL);
This does not check implicit_section, so user-specified sections are lost.
ICF already handles this case correctly:
if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
|| (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
Reproducer:
Template class with two static member functions, both with
[[gnu::section(".root_section")]]:
- Function A: referenced externally (e.g., vector table)
-> stays externally_visible -> section preserved
- Function B: only referenced internally
-> localized -> section lost
Expected: Both functions land in .root_section, OR a warning is emitted
indicating that the section attribute will be ignored.
Actual: Only the externally-visible function keeps the section;
the localized function ends up in .text. No warning is issued.
Proposed fix:
if (DECL_COMDAT (node->decl) && !node->alias && node->implicit_section)
node->set_section (NULL);
Notes:
The same issue was discussed in PR 65262 and closed as WONTFIX. The reasoning,
as I understand it, is that LTO is free to privatize symbols. That may be
correct, but in this case a GCC feature does not work as documented:
- [[gnu::section()]] is a documented feature of GCC
- No limitations are documented for the section attribute
- No limitations regarding attributes are documented for LTO
Additionally, the [[gnu::noinline]] attribute has no effect on this behavior.
Only applying [[gnu::noipa]] prevents explicit sections from being lost, but
this has other implications: even functions residing in the same section can
no longer be optimized at link time.