Bug 116184 - section attributes in COMDAT groups use wrong group name for multiple instances in same TU
Summary: section attributes in COMDAT groups use wrong group name for multiple instanc...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 122480 (view as bug list)
Depends on:
Blocks:
 
Reported: 2024-08-01 23:42 UTC by Roland McGrath
Modified: 2025-10-30 00:28 UTC (History)
9 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2025-10-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Roland McGrath 2024-08-01 23:42:47 UTC
This might belong in a different component.  The test case here is in C++ but the same thing probably arises with C(>=99) `extern inline` functions (and static variables inside them) too.  It might be specific to ELF targets, but might also manifest the same way on any non-ELF targets that support the section attributes.  It doesn't seem to be specific to any particular subset of ELF targets AFAICT.

Previously bug 94342 prevented `[[gnu::section("name")]]` (and other spellings) in COMDAT group contexts (C `extern inline`, C++ `inline` and templates, etc.) from honoring the named-section attribute.  That's now been fixed, but this exposed a new bug.  Things work correctly when there is only one instance of an entity in a named section in some COMDAT group in the TU.  But when there are multiple entities in one TU, they all wind up in the same COMDAT group instead of the proper group for each entity.

This is currently observed using commit 973097d801a30385cd39a570624eefa7547f8ff3 from the 14 branch.

```
template<char... C>                                                             
struct Chars {                                                                  
  static inline const char storage[] = {C..., '\0'};                            
  static inline const char* const string [[gnu::section("strings")]] {storage}; 
};                                                                              
                                                                                
const char* const* foo_string = &Chars<'f','o','o'>::string;                    
const char* const* bar_string = &Chars<'b','a','r'>::string;                    
```

Compiled with `g++ -std=c++17 -S` shows the issue straightforwardly:
```
...
	.section	strings,"aG",@progbits,_ZN5CharsIJLc102ELc111ELc111EEE6stringE,comdat
	.align 8
	.type	_ZN5CharsIJLc102ELc111ELc111EEE6stringE, @object
	.size	_ZN5CharsIJLc102ELc111ELc111EEE6stringE, 8
_ZN5CharsIJLc102ELc111ELc111EEE6stringE:
...
	.section	strings,"aG",@progbits,_ZN5CharsIJLc102ELc111ELc111EEE6stringE,comdat
	.align 8
	.type	_ZN5CharsIJLc98ELc97ELc114EEE6stringE, @object
	.size	_ZN5CharsIJLc98ELc97ELc114EEE6stringE, 8
_ZN5CharsIJLc98ELc97ELc114EEE6stringE:
...
```

Everything is right about both definitions, except that the group name in the second `.section` directive matches the first symbol rather than the second.
Comment 1 Patrick Palka 2024-08-02 00:59:47 UTC
The underlying issue can be demonstrated with non-template inlines as well:

  inline const char* foo [[gnu::section("strings"), gnu::used]] = "foo";
  inline const char* bar [[gnu::section("strings"), gnu::used]] = "bar";

gives

        .section        strings,"awG",@progbits,foo,comdat
...
        .section        strings,"awG",@progbits,foo,comdat


I'm afraid I don't know how to fix this, hopefully someone else can look into it though.
Comment 2 Drea Pinski 2024-08-02 01:15:06 UTC
Dup. There is no way to fix it.

*** This bug has been marked as a duplicate of bug 87178 ***
Comment 3 Roland McGrath 2024-08-02 01:22:52 UTC
This is not unfixable.  It may be true that the assembler doesn't support emitting a non-COMDAT / non-group section and a section of the same name that's in a COMDAT group.  But that's not the case that I reported.  If I take the .s file from my case and edit the second `.section` directive to be correct, then the assembler generates a correct ELF file containing two separate `strings` sections, each in the correct COMDAT group.
Comment 4 Drea Pinski 2024-08-02 01:23:42 UTC
Still a dup though.

*** This bug has been marked as a duplicate of bug 87178 ***
Comment 5 Roland McGrath 2024-08-02 01:33:46 UTC
Andrew, this is NOT a duplicate of any bug that should be marked INVALID.
This is a different case for which the rationale given in the bug 87178 comments DOES NOT APPLY.
Comment 6 Drea Pinski 2025-10-29 18:03:18 UTC
*** Bug 122480 has been marked as a duplicate of this bug. ***
Comment 7 Patrick Palka 2025-10-30 00:28:27 UTC
Probably related:

void f() {
  [[gnu::used, gnu::section(".test")]] static int p;
}

inline void g() {
  [[gnu::used, gnu::section(".test")]] static int p;
}

int main() {
  f();
  g();
}

is rejected with

<stdin>:6:51: error: ‘p’ causes a section type conflict with ‘p’
<stdin>:2:51: note: ‘p’ was declared here

Jason hinted at a solution back in 2019: https://gcc.gnu.org/legacy-ml/gcc-patches/2019-12/msg01152.html