On 12/1/25 5:19 AM, Jakub Jelinek wrote:
Hi!
The following testcase fails due to ODR warnings starting with the
r16-3233 change (P2115R0 PR120503 implementation).
The problem is that for C++20 we mangle differently the anonymous
union at the class scope from C++17, in C++17 the
unnamed enumeration that has an enumerator as a name for linkage purposes
before it is counted as TYPE_UNNAMED_P in nested_anon_class_index,
but for C++20 it is not, therefore the ODR warning.
While the term defined in https://eel.is/c++draft/dcl.enum#12.sentence-2
is defined for all enum types, its only use in
https://eel.is/c++draft/basic.link#4.5 is solely for enumeration types at
namespace scope, changing anything for those at class scope or block scope
has undesirable ABI consequences.
Fixed thusly, bootstrapped/regtested on x86_64-linux, ok for trunk?
Or shall I change the function name too or add TYPE_NAMESPACE_SCOPE_P
checks next to the enum_with_enumerator_for_linkage_p calls?
No, but let's clarify in the comment that the term is defined for all
enums, but for backward ABI compatibility class-scope unnamed enums are
still mangled based on their position within the class. OK with that
addition.
2025-12-01 Jakub Jelinek <[email protected]>
PR c++/122905
* decl.cc (enum_with_enumerator_for_linkage_p): Only return true
for namespace scope types.
* g++.dg/lto/pr122905.h: New file.
* g++.dg/lto/pr122905_0.C: New test.
* g++.dg/lto/pr122905_1.C: New test.
--- gcc/cp/decl.cc.jj 2025-11-29 12:40:36.124343863 +0100
+++ gcc/cp/decl.cc 2025-11-29 13:26:00.076837722 +0100
@@ -18754,7 +18754,7 @@ start_enum (tree name, tree enumtype, tr
}
/* Returns true if TYPE is an enum that uses an enumerator name for
- linkage purposes. */
+ linkage purposes at namespace scope. */
bool
enum_with_enumerator_for_linkage_p (tree type)
@@ -18762,7 +18762,8 @@ enum_with_enumerator_for_linkage_p (tree
return (cxx_dialect >= cxx20
&& UNSCOPED_ENUM_P (type)
&& TYPE_ANON_P (type)
- && TYPE_VALUES (type));
+ && TYPE_VALUES (type)
+ && TYPE_NAMESPACE_SCOPE_P (type));
}
/* After processing and defining all the values of an enumeration type,
--- gcc/testsuite/g++.dg/lto/pr122905.h.jj 2025-11-29 13:21:33.734480975
+0100
+++ gcc/testsuite/g++.dg/lto/pr122905.h 2025-11-29 13:19:27.037689730 +0100
@@ -0,0 +1,9 @@
+struct A {
+ typedef char *B;
+ struct C { C (B x) {} };
+ C c;
+ enum { D = 15 };
+ union { char e[16]; };
+ A (const char *x) : c {e} {}
+};
+A foo ();
--- gcc/testsuite/g++.dg/lto/pr122905_0.C.jj 2025-11-29 13:21:36.455433539
+0100
+++ gcc/testsuite/g++.dg/lto/pr122905_0.C 2025-11-29 13:25:05.606787318
+0100
@@ -0,0 +1,16 @@
+/* PR c++/122905 */
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -O2 -flto -std=c++20 } } } */
+
+#include "pr122905.h"
+
+A
+foo ()
+{
+ return "foo";
+}
+
+int
+main ()
+{
+}
--- gcc/testsuite/g++.dg/lto/pr122905_1.C.jj 2025-11-29 13:21:39.259384657
+0100
+++ gcc/testsuite/g++.dg/lto/pr122905_1.C 2025-11-29 13:25:20.765523054
+0100
@@ -0,0 +1,5 @@
+// { dg-options "-O2 -flto -std=c++17" }
+
+#include "pr122905.h"
+
+volatile auto v = foo ();
Jakub