Skip to content

Commit c05bcb2

Browse files
fix(folding): correct unique object rep checks []
Fix __has_unique_object_representations for several cases: - A base class with no direct nonstatic data members that inherits some (and is thus not empty) was treated as an empty base. Its size was counted as tail padding, making the trait incorrectly FALSE for derived classes. Use is_empty_class_type instead of checking for an empty field list. - Treat unnamed bit-fields of nonzero width as padding in Clang 17+ and g++ 13.1+ (also g++ 10.5, 11.4, 12.3 backports). - Restrict treating volatile-qualified non-class types as lacking unique object representations to g++ modes before version 10, and no longer apply it in Clang modes. Add regression test has-unique-object-rep-inherited-base and update expectations for imported Clang type-traits and g++ has-unique-obj-representations3 tests.
1 parent 3c62b61 commit c05bcb2

11 files changed

Lines changed: 91 additions & 185 deletions

File tree

‎src/Changes‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
Version 7.1
22

3+
10/16/26
4+
__has_unique_object_representations fixes
5+
6+
A base class that declares no nonstatic data members of its own but inherits
7+
some (and is therefore not empty) was treated as an empty base class. Its
8+
size was then counted as tail padding, so the trait was incorrectly FALSE for
9+
classes derived from it. For example, with --g++:
10+
11+
struct A { char i; };
12+
struct B : A {};
13+
struct C : B {};
14+
static_assert(__has_unique_object_representations(C)); // Previously
15+
// failed.
16+
17+
This is now fixed. In addition, the following version-dependent behaviors
18+
of g++ and Clang are now emulated:
19+
20+
- An unnamed bit-field of nonzero width is treated as padding (making the
21+
result FALSE) in g++ 10.5, 11.4, 12.3, 13.1 and later, and in Clang 17
22+
and later. For example:
23+
24+
struct S { char a; char : 8; char b; };
25+
// __has_unique_object_representations(S) is now FALSE in those modes.
26+
27+
- Volatile-qualified non-class types (e.g., "volatile int") are treated as
28+
not having unique object representations only in g++ modes before
29+
version 10 (previously this was done for all g++ versions, including
30+
Clang modes).
31+
32+
333
10/16/26 [GH #229]
434
Improper handling of "if constexpr" substatements
535

‎src/folding.c‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8939,6 +8939,26 @@ with cssp are trivial.
89398939
} /* all_copy_constructors_trivial */
89408940

89418941

8942+
static a_boolean unnamed_bit_field_is_padding(void)
8943+
/*
8944+
Return TRUE if an unnamed bit-field of non-zero width is considered padding
8945+
by type_has_unique_object_representations. That is the case for Clang 17
8946+
and later and for g++ 13.1 and later (the change was also backported to
8947+
g++ 10.5, 11.4, and 12.3).
8948+
*/
8949+
{
8950+
a_boolean result = FALSE;
8951+
8952+
if (clang_mode) {
8953+
result = clang_version >= 170000;
8954+
} else if (gpp_mode) {
8955+
result = gnu_version >= 120300 ||
8956+
(gnu_version >= 110400 && gnu_version < 120000) ||
8957+
(gnu_version >= 100500 && gnu_version < 110000);
8958+
} /* if */
8959+
return result;
8960+
} /* unnamed_bit_field_is_padding */
8961+
89428962
static a_boolean type_has_unique_object_representations(
89438963
a_type_ptr type,
89448964
a_targ_size_t *after_base_members,
@@ -8999,8 +9019,7 @@ architectures for which these assumptions are not valid.
89999019
if (bcp->offset != end_of_last_subobject) {
90009020
/* There's padding between base class subobjects. */
90019021
result = FALSE;
9002-
} else if (bcp->type->variant.class_struct_union.field_list ==
9003-
NULL) {
9022+
} else if (is_empty_class_type(bcp->type)) {
90049023
/* An empty base class: treat it as having size 0 and do not
90059024
check type_has_unique_object_representation, since an empty
90069025
class will consist of nothing but padding. If it was not
@@ -9035,6 +9054,12 @@ architectures for which these assumptions are not valid.
90359054
same size or (for g++, not clang) if a bit-field is shorter
90369055
than the size of the union. */
90379056
result = FALSE;
9057+
} else if (field->is_bit_field && field->bit_size != 0 &&
9058+
unnamed_bit_field_is_padding() &&
9059+
field->source_corresp.assoc_info ==
9060+
(char *)get_unnamed_field_symbol()) {
9061+
/* An unnamed bit-field of non-zero width is padding. */
9062+
result = FALSE;
90389063
} else if (field->offset != end_of_last_subobject ||
90399064
field->offset_bit_remainder != bit_offset_of_end) {
90409065
/* There's padding between nonstatic data members. */
@@ -9078,9 +9103,10 @@ architectures for which these assumptions are not valid.
90789103
} /* if */
90799104
} /* if */
90809105
} /* if */
9081-
} else if (gpp_mode && is_volatile_qualified_type(orig_type)) {
9082-
/* g++ treats volatile-qualified types as not having unique object
9083-
representations. */
9106+
} else if (gpp_mode && !clang_mode && gnu_version < 100000 &&
9107+
is_volatile_qualified_type(orig_type)) {
9108+
/* g++ before version 10 treats volatile-qualified non-class types as
9109+
not having unique object representations. */
90849110
result = FALSE;
90859111
} else {
90869112
/* A non-class type. */

‎tests/expectations/edg_x86_64/imported.log‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6872,7 +6872,6 @@ gnu/cpp/cpp1z/fold1/test.mft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL:
68726872
gnu/cpp/cpp1z/fold5.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
68736873
gnu/cpp/cpp1z/fold6.sft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL:
68746874
gnu/cpp/cpp1z/has-unique-obj-representations1.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
6875-
gnu/cpp/cpp1z/has-unique-obj-representations3.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
68766875
gnu/cpp/cpp1z/inh-ctor1.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL:
68776876
gnu/cpp/cpp1z/inh-ctor33.sft.cpp:lp:-DTEST_NUMBER=1 --c++11:FAIL:
68786877
gnu/cpp/cpp1z/inh-ctor38.sft.cpp:rp:-DTEST_NUMBER=1 --c++11:FAIL:

‎tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt‎

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -375,38 +375,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
375375
static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
376376
^
377377

378-
"Test_name.c", line 3482: error: static assertion failed with "integrals are"
379-
static_assert(__has_unique_object_representations(volatile int), "integrals are");
380-
^
381-
382-
"Test_name.c", line 3483: error: static assertion failed with "integrals are"
383-
static_assert(__has_unique_object_representations(const volatile int), "integrals are");
384-
^
385-
386-
"Test_name.c", line 3502: error: static assertion failed with "even function pointers"
387-
static_assert(__has_unique_object_representations(volatile FP), "even function pointers");
388-
^
389-
390-
"Test_name.c", line 3503: error: static assertion failed with "even function pointers"
391-
static_assert(__has_unique_object_representations(const volatile FP), "even function pointers");
392-
^
393-
394-
"Test_name.c", line 3507: error: static assertion failed with "and pointer to members"
395-
static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members");
396-
^
397-
398-
"Test_name.c", line 3508: error: static assertion failed with "and pointer to members"
399-
static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members");
400-
^
401-
402-
"Test_name.c", line 3512: error: static assertion failed with "and pointer to members"
403-
static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members");
404-
^
405-
406-
"Test_name.c", line 3513: error: static assertion failed with "and pointer to members"
407-
static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members");
408-
^
409-
410378
"Test_name.c", line 3544: error: an incomplete class type is not allowed
411379
static_assert(!__has_unique_object_representations(AnIncompleteType));
412380
^
@@ -431,14 +399,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
431399
char d : 1;
432400
^
433401

434-
"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding"
435-
static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding");
436-
^
437-
438-
"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding"
439-
static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding");
440-
^
441-
442402
"Test_name.c", line 3790: warning: declared size for bit field is larger than the size of the bit field type; truncated to 8 bits
443403
bool b : 16;
444404
^
@@ -695,5 +655,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
695655
#error Programming model currently unsupported; please add a new entry.
696656
^
697657

698-
124 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
658+
114 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
699659
Compilation terminated.

‎tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt‎

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -379,38 +379,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
379379
static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
380380
^
381381

382-
"Test_name.c", line 3482: error: static assertion failed with "integrals are"
383-
static_assert(__has_unique_object_representations(volatile int), "integrals are");
384-
^
385-
386-
"Test_name.c", line 3483: error: static assertion failed with "integrals are"
387-
static_assert(__has_unique_object_representations(const volatile int), "integrals are");
388-
^
389-
390-
"Test_name.c", line 3502: error: static assertion failed with "even function pointers"
391-
static_assert(__has_unique_object_representations(volatile FP), "even function pointers");
392-
^
393-
394-
"Test_name.c", line 3503: error: static assertion failed with "even function pointers"
395-
static_assert(__has_unique_object_representations(const volatile FP), "even function pointers");
396-
^
397-
398-
"Test_name.c", line 3507: error: static assertion failed with "and pointer to members"
399-
static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members");
400-
^
401-
402-
"Test_name.c", line 3508: error: static assertion failed with "and pointer to members"
403-
static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members");
404-
^
405-
406-
"Test_name.c", line 3512: error: static assertion failed with "and pointer to members"
407-
static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members");
408-
^
409-
410-
"Test_name.c", line 3513: error: static assertion failed with "and pointer to members"
411-
static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members");
412-
^
413-
414382
"Test_name.c", line 3544: error: an incomplete class type is not allowed
415383
static_assert(!__has_unique_object_representations(AnIncompleteType));
416384
^
@@ -435,14 +403,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
435403
char d : 1;
436404
^
437405

438-
"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding"
439-
static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding");
440-
^
441-
442-
"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding"
443-
static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding");
444-
^
445-
446406
"Test_name.c", line 3790: warning: declared size for bit field is larger than the size of the bit field type; truncated to 8 bits
447407
bool b : 16;
448408
^
@@ -695,5 +655,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
695655
#error Programming model currently unsupported; please add a new entry.
696656
^
697657

698-
124 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
658+
114 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
699659
Compilation terminated.

‎tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt‎

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -363,38 +363,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
363363
static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
364364
^
365365

366-
"Test_name.c", line 3482: error: static assertion failed with "integrals are"
367-
static_assert(__has_unique_object_representations(volatile int), "integrals are");
368-
^
369-
370-
"Test_name.c", line 3483: error: static assertion failed with "integrals are"
371-
static_assert(__has_unique_object_representations(const volatile int), "integrals are");
372-
^
373-
374-
"Test_name.c", line 3502: error: static assertion failed with "even function pointers"
375-
static_assert(__has_unique_object_representations(volatile FP), "even function pointers");
376-
^
377-
378-
"Test_name.c", line 3503: error: static assertion failed with "even function pointers"
379-
static_assert(__has_unique_object_representations(const volatile FP), "even function pointers");
380-
^
381-
382-
"Test_name.c", line 3507: error: static assertion failed with "and pointer to members"
383-
static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members");
384-
^
385-
386-
"Test_name.c", line 3508: error: static assertion failed with "and pointer to members"
387-
static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members");
388-
^
389-
390-
"Test_name.c", line 3512: error: static assertion failed with "and pointer to members"
391-
static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members");
392-
^
393-
394-
"Test_name.c", line 3513: error: static assertion failed with "and pointer to members"
395-
static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members");
396-
^
397-
398366
"Test_name.c", line 3544: error: an incomplete class type is not allowed
399367
static_assert(!__has_unique_object_representations(AnIncompleteType));
400368
^
@@ -419,14 +387,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
419387
char d : 1;
420388
^
421389

422-
"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding"
423-
static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding");
424-
^
425-
426-
"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding"
427-
static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding");
428-
^
429-
430390
"Test_name.c", line 3790: warning: declared size for bit field is larger than the size of the bit field type; truncated to 8 bits
431391
bool b : 16;
432392
^
@@ -635,5 +595,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
635595
#error Programming model currently unsupported; please add a new entry.
636596
^
637597

638-
124 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
598+
114 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
639599
Compilation terminated.

‎tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt‎

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -359,38 +359,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
359359
static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
360360
^
361361

362-
"Test_name.c", line 3482: error: static assertion failed with "integrals are"
363-
static_assert(__has_unique_object_representations(volatile int), "integrals are");
364-
^
365-
366-
"Test_name.c", line 3483: error: static assertion failed with "integrals are"
367-
static_assert(__has_unique_object_representations(const volatile int), "integrals are");
368-
^
369-
370-
"Test_name.c", line 3502: error: static assertion failed with "even function pointers"
371-
static_assert(__has_unique_object_representations(volatile FP), "even function pointers");
372-
^
373-
374-
"Test_name.c", line 3503: error: static assertion failed with "even function pointers"
375-
static_assert(__has_unique_object_representations(const volatile FP), "even function pointers");
376-
^
377-
378-
"Test_name.c", line 3507: error: static assertion failed with "and pointer to members"
379-
static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members");
380-
^
381-
382-
"Test_name.c", line 3508: error: static assertion failed with "and pointer to members"
383-
static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members");
384-
^
385-
386-
"Test_name.c", line 3512: error: static assertion failed with "and pointer to members"
387-
static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members");
388-
^
389-
390-
"Test_name.c", line 3513: error: static assertion failed with "and pointer to members"
391-
static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members");
392-
^
393-
394362
"Test_name.c", line 3544: error: an incomplete class type is not allowed
395363
static_assert(!__has_unique_object_representations(AnIncompleteType));
396364
^
@@ -415,14 +383,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
415383
char d : 1;
416384
^
417385

418-
"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding"
419-
static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding");
420-
^
421-
422-
"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding"
423-
static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding");
424-
^
425-
426386
"Test_name.c", line 3790: warning: declared size for bit field is larger than the size of the bit field type; truncated to 8 bits
427387
bool b : 16;
428388
^
@@ -635,5 +595,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
635595
#error Programming model currently unsupported; please add a new entry.
636596
^
637597

638-
124 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
598+
114 errors and 1 catastrophic error detected in the compilation of "Test_name.c".
639599
Compilation terminated.
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
11
fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics --c++11 Test_name.c
2-
"Test_name.c", line 10: error: static assertion failed with ""
3-
static_assert (__has_unique_object_representations (U) == false, "");
4-
^
5-
"Test_name.c", line 10: note: the final comparison was 1 == 0
6-
static_assert (__has_unique_object_representations (U) == false, "");
7-
^
8-
9-
"Test_name.c", line 11: error: static assertion failed with ""
10-
static_assert (__has_unique_object_representations (V) == false, "");
11-
^
12-
"Test_name.c", line 11: note: the final comparison was 1 == 0
13-
static_assert (__has_unique_object_representations (V) == false, "");
14-
^
15-
16-
2 errors detected in the compilation of "Test_name.c".
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fe_only -DTEST_NUMBER=1 --c++17 --g++ --gnu_version=150100 Test_name.c
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fe_only -DTEST_NUMBER=2 --c++17 --clang --clang_version=190000 Test_name.c

0 commit comments

Comments
 (0)