From 625b0c5a103e6fc99972110325c473e0e56a58ef Mon Sep 17 00:00:00 2001 From: Jakub Labenski Date: Fri, 16 Oct 2026 14:41:19 +0200 Subject: [PATCH] fix(folding): correct unique object rep checks [GH #327] 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 in classes as padding, as the standard requires. Keep the old behavior only in Clang modes before 17 and g++ modes before 13.1 (except the 10.5, 11.4, and 12.3 backports). - Do not apply the unnamed bit-field rule to unions, where the bit-field overlaps the other members; the existing union size check decides. - In Microsoft mode, as in Clang mode, do not treat a union bit-field narrower than the union as padding, matching MSVC. - 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 tests has-unique-object-rep-inherited-base, has-unique-object-rep-bit-field, has-unique-object-rep-union-bit-field, and has-unique-object-rep-volatile, covering standard, g++, Clang, and Microsoft modes, and update expectations for imported Clang type-traits and g++ has-unique-obj-representations3 tests. --- src/Changes | 41 +++++++++++++++++ src/folding.c | 46 +++++++++++++++---- tests/expectations/edg_x86_64/imported.log | 1 - .../SemaCXX/.type-traits.rto/default.1.1.txt | 42 +---------------- .../.type-traits.rto/edg_x86_32.1.1.txt | 42 +---------------- .../.type-traits.rto/edg_x86_32_cp.1.1.txt | 42 +---------------- .../.type-traits.rto/edg_x86_64_cp.1.1.txt | 42 +---------------- .../default.1.1.txt | 15 ------ .../default.1.1.txt | 1 + .../default.10.1.txt | 1 + .../default.2.1.txt | 1 + .../default.3.1.txt | 1 + .../default.4.1.txt | 1 + .../default.5.1.txt | 1 + .../default.6.1.txt | 1 + .../default.7.1.txt | 1 + .../default.8.1.txt | 1 + .../default.9.1.txt | 1 + .../default.1.1.txt | 1 + .../default.2.1.txt | 1 + .../default.3.1.txt | 1 + .../default.4.1.txt | 1 + .../default.1.1.txt | 1 + .../default.2.1.txt | 1 + .../default.3.1.txt | 1 + .../default.4.1.txt | 1 + .../default.5.1.txt | 1 + .../default.6.1.txt | 1 + .../default.1.1.txt | 1 + .../default.2.1.txt | 1 + .../default.3.1.txt | 1 + .../default.4.1.txt | 1 + .../default.5.1.txt | 1 + .../default.6.1.txt | 1 + .../default.7.1.txt | 1 + .../has-unique-object-rep-bit-field.sft.cpp | 25 ++++++++++ ...s-unique-object-rep-inherited-base.sft.cpp | 24 ++++++++++ ...-unique-object-rep-union-bit-field.sft.cpp | 27 +++++++++++ .../has-unique-object-rep-volatile.sft.cpp | 19 ++++++++ 39 files changed, 205 insertions(+), 188 deletions(-) create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.10.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.5.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.6.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.7.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.8.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.9.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.5.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.6.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.5.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.6.1.txt create mode 100644 tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.7.1.txt create mode 100644 tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp create mode 100644 tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp create mode 100644 tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp create mode 100644 tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp diff --git a/src/Changes b/src/Changes index 0b18da167f..44d070f7bf 100644 --- a/src/Changes +++ b/src/Changes @@ -1,5 +1,46 @@ Version 7.1 +10/16/26 [GH #327] +__has_unique_object_representations fixes + +A base class that declares no nonstatic data members of its own but inherits +some (and is therefore not empty) was treated as an empty base class. Its +size was then counted as tail padding, so the trait was incorrectly FALSE for +classes derived from it. For example, with --c++11: + + struct A { char i; }; + struct B : A {}; + struct C : B {}; + static_assert(__has_unique_object_representations(C), ""); // Previously + // failed. + +This is now fixed. In addition: + + - An unnamed bit-field of nonzero width is now treated as padding (making + the result FALSE), as the standard requires. For example: + + struct S { char a; char : 8; char b; }; + // __has_unique_object_representations(S) is now FALSE. + + The previous behavior (TRUE) is retained in g++ modes before 13.1 + (except 10.5, 11.4, and 12.3) and in Clang modes before 17. + + - In a union, an unnamed bit-field overlaps the other members, so the + rule above does not apply; as before, a bit-field narrower than the + union is treated as padding, except in Clang modes. Microsoft mode now + also does not treat it as padding, matching MSVC. For example: + + union U { int x : 3; }; + // __has_unique_object_representations(U) is now TRUE with + // --microsoft. + + - Volatile-qualified non-class types (e.g., "volatile int") are treated as + not having unique object representations only in g++ modes before + version 10 (previously this was done for all g++ versions, including + Clang modes). In other modes the result is the same as for the + unqualified type, as the standard requires. + + 10/15/26 [GH #309] Position of (lowered) cleanups at the end of a function body diff --git a/src/folding.c b/src/folding.c index 221d60bf1f..4bf480dd39 100644 --- a/src/folding.c +++ b/src/folding.c @@ -8939,6 +8939,27 @@ with cssp are trivial. } /* all_copy_constructors_trivial */ +static a_boolean unnamed_bit_field_is_padding(void) +/* +Return TRUE if an unnamed bit-field of non-zero width is considered padding +by type_has_unique_object_representations. That is the standard behavior; +it is not done by Clang before version 17 or by g++ before 13.1 (except for +the backports to g++ 10.5, 11.4, and 12.3). +*/ +{ + a_boolean result = TRUE; + + if (clang_mode) { + result = clang_version >= 170000; + } else if (gpp_mode) { + result = gnu_version >= 120300 || + (gnu_version >= 110400 && gnu_version < 120000) || + (gnu_version >= 100500 && gnu_version < 110000); + } /* if */ + return result; +} /* unnamed_bit_field_is_padding */ + + static a_boolean type_has_unique_object_representations( a_type_ptr type, a_targ_size_t *after_base_members, @@ -8999,8 +9020,7 @@ architectures for which these assumptions are not valid. if (bcp->offset != end_of_last_subobject) { /* There's padding between base class subobjects. */ result = FALSE; - } else if (bcp->type->variant.class_struct_union.field_list == - NULL) { + } else if (is_empty_class_type(bcp->type)) { /* An empty base class: treat it as having size 0 and do not check type_has_unique_object_representation, since an empty class will consist of nothing but padding. If it was not @@ -9029,11 +9049,20 @@ architectures for which these assumptions are not valid. a_type_ptr field_type = skip_typerefs(field->type); if (type->kind == (a_type_kind)tk_union && ((prev_field != NULL && field_type->size != prev_field_size) || - (field->is_bit_field && !clang_mode && + (field->is_bit_field && !clang_mode && !microsoft_mode && field->bit_size < type->size * targ_char_bit))) { /* There will be padding in a union if not all fields are the - same size or (for g++, not clang) if a bit-field is shorter - than the size of the union. */ + same size or (except for Clang and Microsoft) if a bit-field + is shorter than the size of the union. */ + result = FALSE; + } else if (type->kind != tk_union && + field->is_bit_field && field->bit_size != 0 && + unnamed_bit_field_is_padding() && + field->source_corresp.assoc_info == + (char*)get_unnamed_field_symbol()) { + /* An unnamed bit-field of non-zero width is padding. (In a + union, an unnamed bit-field overlaps the other members, so + it is handled by the size test above instead.) */ result = FALSE; } else if (field->offset != end_of_last_subobject || field->offset_bit_remainder != bit_offset_of_end) { @@ -9078,9 +9107,10 @@ architectures for which these assumptions are not valid. } /* if */ } /* if */ } /* if */ - } else if (gpp_mode && is_volatile_qualified_type(orig_type)) { - /* g++ treats volatile-qualified types as not having unique object - representations. */ + } else if (gpp_version_is(< 100000) && + is_volatile_qualified_type(orig_type)) { + /* g++ before version 10 treats volatile-qualified non-class types as + not having unique object representations. */ result = FALSE; } else { /* A non-class type. */ diff --git a/tests/expectations/edg_x86_64/imported.log b/tests/expectations/edg_x86_64/imported.log index 12f913d087..c18eaad9ab 100644 --- a/tests/expectations/edg_x86_64/imported.log +++ b/tests/expectations/edg_x86_64/imported.log @@ -6872,7 +6872,6 @@ gnu/cpp/cpp1z/fold1/test.mft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL: gnu/cpp/cpp1z/fold5.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL: gnu/cpp/cpp1z/fold6.sft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL: gnu/cpp/cpp1z/has-unique-obj-representations1.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL: -gnu/cpp/cpp1z/has-unique-obj-representations3.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL: gnu/cpp/cpp1z/inh-ctor1.sft.cpp:fn:-DTEST_NUMBER=1 --c++11:FAIL: gnu/cpp/cpp1z/inh-ctor33.sft.cpp:lp:-DTEST_NUMBER=1 --c++11:FAIL: gnu/cpp/cpp1z/inh-ctor38.sft.cpp:rp:-DTEST_NUMBER=1 --c++11:FAIL: diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt index eb26fc2c03..ec879ba032 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/default.1.1.txt @@ -375,38 +375,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}} ^ -"Test_name.c", line 3482: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(volatile int), "integrals are"); - ^ - -"Test_name.c", line 3483: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(const volatile int), "integrals are"); - ^ - -"Test_name.c", line 3502: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3503: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(const volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3507: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3508: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3512: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members"); - ^ - -"Test_name.c", line 3513: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members"); - ^ - "Test_name.c", line 3544: error: an incomplete class type is not allowed static_assert(!__has_unique_object_representations(AnIncompleteType)); ^ @@ -431,14 +399,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers char d : 1; ^ -"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding"); - ^ - -"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding"); - ^ - "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 bool b : 16; ^ @@ -695,5 +655,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers #error Programming model currently unsupported; please add a new entry. ^ -124 errors and 1 catastrophic error detected in the compilation of "Test_name.c". +114 errors and 1 catastrophic error detected in the compilation of "Test_name.c". Compilation terminated. diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt index aceebd43b6..01377d3b3d 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32.1.1.txt @@ -379,38 +379,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}} ^ -"Test_name.c", line 3482: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(volatile int), "integrals are"); - ^ - -"Test_name.c", line 3483: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(const volatile int), "integrals are"); - ^ - -"Test_name.c", line 3502: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3503: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(const volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3507: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3508: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3512: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members"); - ^ - -"Test_name.c", line 3513: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members"); - ^ - "Test_name.c", line 3544: error: an incomplete class type is not allowed static_assert(!__has_unique_object_representations(AnIncompleteType)); ^ @@ -435,14 +403,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers char d : 1; ^ -"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding"); - ^ - -"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding"); - ^ - "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 bool b : 16; ^ @@ -695,5 +655,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers #error Programming model currently unsupported; please add a new entry. ^ -124 errors and 1 catastrophic error detected in the compilation of "Test_name.c". +114 errors and 1 catastrophic error detected in the compilation of "Test_name.c". Compilation terminated. diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt index cb066ca2d7..9142873062 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_32_cp.1.1.txt @@ -363,38 +363,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}} ^ -"Test_name.c", line 3482: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(volatile int), "integrals are"); - ^ - -"Test_name.c", line 3483: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(const volatile int), "integrals are"); - ^ - -"Test_name.c", line 3502: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3503: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(const volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3507: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3508: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3512: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members"); - ^ - -"Test_name.c", line 3513: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members"); - ^ - "Test_name.c", line 3544: error: an incomplete class type is not allowed static_assert(!__has_unique_object_representations(AnIncompleteType)); ^ @@ -419,14 +387,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers char d : 1; ^ -"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding"); - ^ - -"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding"); - ^ - "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 bool b : 16; ^ @@ -635,5 +595,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers #error Programming model currently unsupported; please add a new entry. ^ -124 errors and 1 catastrophic error detected in the compilation of "Test_name.c". +114 errors and 1 catastrophic error detected in the compilation of "Test_name.c". Compilation terminated. diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt index d4391885f2..5d28e8863c 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.type-traits.rto/edg_x86_64_cp.1.1.txt @@ -359,38 +359,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}} ^ -"Test_name.c", line 3482: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(volatile int), "integrals are"); - ^ - -"Test_name.c", line 3483: error: static assertion failed with "integrals are" - static_assert(__has_unique_object_representations(const volatile int), "integrals are"); - ^ - -"Test_name.c", line 3502: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3503: error: static assertion failed with "even function pointers" - static_assert(__has_unique_object_representations(const volatile FP), "even function pointers"); - ^ - -"Test_name.c", line 3507: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3508: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members"); - ^ - -"Test_name.c", line 3512: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members"); - ^ - -"Test_name.c", line 3513: error: static assertion failed with "and pointer to members" - static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members"); - ^ - "Test_name.c", line 3544: error: an incomplete class type is not allowed static_assert(!__has_unique_object_representations(AnIncompleteType)); ^ @@ -415,14 +383,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers char d : 1; ^ -"Test_name.c", line 3777: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding"); - ^ - -"Test_name.c", line 3778: error: static assertion failed with "Bitfield padding" - static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding"); - ^ - "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 bool b : 16; ^ @@ -635,5 +595,5 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers #error Programming model currently unsupported; please add a new entry. ^ -124 errors and 1 catastrophic error detected in the compilation of "Test_name.c". +114 errors and 1 catastrophic error detected in the compilation of "Test_name.c". Compilation terminated. diff --git a/tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt b/tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt index dedd201510..dcdf4c999a 100644 --- a/tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt +++ b/tests/tests/imported/gnu/cpp/cpp1z/.has-unique-obj-representations3.rto/default.1.1.txt @@ -1,16 +1 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics --c++11 Test_name.c -"Test_name.c", line 10: error: static assertion failed with "" - static_assert (__has_unique_object_representations (U) == false, ""); - ^ -"Test_name.c", line 10: note: the final comparison was 1 == 0 - static_assert (__has_unique_object_representations (U) == false, ""); - ^ - -"Test_name.c", line 11: error: static assertion failed with "" - static_assert (__has_unique_object_representations (V) == false, ""); - ^ -"Test_name.c", line 11: note: the final comparison was 1 == 0 - static_assert (__has_unique_object_representations (V) == false, ""); - ^ - -2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.1.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.1.1.txt new file mode 100644 index 0000000000..dbd2e6e9fb --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++11 -DSTD_MODE Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.10.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.10.1.txt new file mode 100644 index 0000000000..f81365ba08 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.10.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=10 --c++11 --microsoft Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.2.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.2.1.txt new file mode 100644 index 0000000000..14683cdbda --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 --c++11 --g++ --gnu_version=90400 -DOLD_PAD Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.3.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.3.1.txt new file mode 100644 index 0000000000..02a47a91fd --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 --c++11 --g++ --gnu_version=100400 -DOLD_PAD Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.4.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.4.1.txt new file mode 100644 index 0000000000..54bbbbc35c --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 --c++11 --g++ --gnu_version=100500 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.5.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.5.1.txt new file mode 100644 index 0000000000..80432f98ac --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 --c++11 --g++ --gnu_version=120200 -DOLD_PAD Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.6.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.6.1.txt new file mode 100644 index 0000000000..d6cfc5db1e --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 --c++11 --g++ --gnu_version=120300 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.7.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.7.1.txt new file mode 100644 index 0000000000..de5edc295a --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.7.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=7 --c++11 --g++ --gnu_version=150100 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.8.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.8.1.txt new file mode 100644 index 0000000000..dc5e2f0c38 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.8.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=8 --c++11 --clang --clang_version=160000 -DOLD_PAD Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.9.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.9.1.txt new file mode 100644 index 0000000000..9d3be5664f --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.9.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=9 --c++11 --clang --clang_version=170000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.1.1.txt b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.1.1.txt new file mode 100644 index 0000000000..4018012f7d --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++17 --g++ --gnu_version=150100 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.2.1.txt b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.2.1.txt new file mode 100644 index 0000000000..a2d2107875 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 --c++17 --clang --clang_version=190000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.3.1.txt b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.3.1.txt new file mode 100644 index 0000000000..7b2ce29244 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 --c++17 -DSTD_MODE Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.4.1.txt b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.4.1.txt new file mode 100644 index 0000000000..09c0269a52 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-inherited-base.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 --c++17 --microsoft Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.1.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.1.1.txt new file mode 100644 index 0000000000..dbd2e6e9fb --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++11 -DSTD_MODE Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.2.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.2.1.txt new file mode 100644 index 0000000000..cb11de8965 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 --c++11 --g++ --gnu_version=90400 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.3.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.3.1.txt new file mode 100644 index 0000000000..7ff502308c --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 --c++11 --g++ --gnu_version=150100 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.4.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.4.1.txt new file mode 100644 index 0000000000..d51608c0fc --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 --c++11 --clang --clang_version=160000 -DCLANG Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.5.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.5.1.txt new file mode 100644 index 0000000000..4de569fbf1 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 --c++11 --clang --clang_version=190000 -DCLANG Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.6.1.txt b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.6.1.txt new file mode 100644 index 0000000000..36e125d4d0 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-union-bit-field.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 --c++11 --microsoft -DCLANG Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.1.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.1.1.txt new file mode 100644 index 0000000000..dbd2e6e9fb --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++11 -DSTD_MODE Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.2.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.2.1.txt new file mode 100644 index 0000000000..edd040e5db --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 --c++11 --g++ --gnu_version=90400 -DOLD_GNU Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.3.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.3.1.txt new file mode 100644 index 0000000000..f22c509a0d --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 --c++11 --g++ --gnu_version=100100 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.4.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.4.1.txt new file mode 100644 index 0000000000..1e493b5953 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 --c++11 --g++ --gnu_version=150100 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.5.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.5.1.txt new file mode 100644 index 0000000000..6df43e0219 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 --c++11 --clang --clang_version=160000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.6.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.6.1.txt new file mode 100644 index 0000000000..bf794a10d9 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 --c++11 --clang --clang_version=190000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.7.1.txt b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.7.1.txt new file mode 100644 index 0000000000..905038b342 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-volatile.rto/default.7.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=7 --c++11 --microsoft Test_name.c diff --git a/tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp b/tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp new file mode 100644 index 0000000000..a597ac9f00 --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp @@ -0,0 +1,25 @@ +//remark:has_unique_object_representations with unnamed bit-fields +//type:fp +//options_all:--c++11 +//options:-DSTD_MODE:--g++ --gnu_version=90400 -DOLD_PAD:--g++ --gnu_version=100400 -DOLD_PAD:--g++ --gnu_version=100500:--g++ --gnu_version=120200 -DOLD_PAD:--g++ --gnu_version=120300:--g++ --gnu_version=150100:--clang --clang_version=160000 -DOLD_PAD:--clang --clang_version=170000:--microsoft + +// Standard behavior: an unnamed bit-field of nonzero width is padding. +// Older g++ and Clang versions did not treat it as padding. +struct S { char a; char : 8; char b; }; +struct T { char a; char b; char : 8; }; // Unnamed bit-field at the end. +struct U : S {}; // Via a base class. +struct V { S s; }; // Via a member. +struct N { char a; char x : 8; char b; }; // Named: not padding. + +#ifdef OLD_PAD +static_assert(__has_unique_object_representations(S), "S"); +static_assert(__has_unique_object_representations(T), "T"); +static_assert(__has_unique_object_representations(U), "U"); +static_assert(__has_unique_object_representations(V), "V"); +#else +static_assert(!__has_unique_object_representations(S), "S"); +static_assert(!__has_unique_object_representations(T), "T"); +static_assert(!__has_unique_object_representations(U), "U"); +static_assert(!__has_unique_object_representations(V), "V"); +#endif +static_assert(__has_unique_object_representations(N), "N"); diff --git a/tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp b/tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp new file mode 100644 index 0000000000..98da0e3e77 --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-inherited-base.sft.cpp @@ -0,0 +1,24 @@ +//remark:has_unique_object_representations with a base that has no direct fields +//type:fp +//options_all:--c++17 +//options:--g++ --gnu_version=150100:--clang --clang_version=190000:-DSTD_MODE:--microsoft + +// B declares no fields but is not empty (it inherits A::i), so it must not +// be skipped as an empty base when checking C. +struct A { char i; }; +struct B : A {}; +struct C : B {}; +struct D : C {}; +struct E {}; +struct F : E, B {}; // Real empty base is still skipped. +struct G : B { char j; }; +struct P { int i; char c; }; // Tail padding. +struct Q : P {}; + +static_assert(__has_unique_object_representations(B), "B"); +static_assert(__has_unique_object_representations(C), "C"); +static_assert(__has_unique_object_representations(D), "D"); +static_assert(__has_unique_object_representations(F), "F"); +static_assert(__has_unique_object_representations(G), "G"); +static_assert(!__has_unique_object_representations(P), "P"); +static_assert(!__has_unique_object_representations(Q), "Q"); diff --git a/tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp b/tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp new file mode 100644 index 0000000000..fa2c52c93a --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-union-bit-field.sft.cpp @@ -0,0 +1,27 @@ +//remark:has_unique_object_representations with bit-fields in unions +//type:fp +//options_all:--c++11 +//options:-DSTD_MODE:--g++ --gnu_version=90400:--g++ --gnu_version=150100:--clang --clang_version=160000 -DCLANG:--clang --clang_version=190000 -DCLANG:--microsoft -DCLANG + +// An unnamed bit-field in a union overlaps the other members; it must not be +// treated as padding by itself. A bit-field shorter than the union is +// padding except in Clang and Microsoft modes (they ignore that case). +union U1 { int x : 3; int y; }; // Short named bit-field. +union U2 { int x : 32; }; // Full-width named bit-field. +union U3 { int x; int : 32; }; // Full-width unnamed bit-field. +union U4 { int x; int : 8; }; // Short unnamed bit-field. +union U5 { int x : 3; }; // Only a short bit-field. +struct S6 { union { int x; int : 32; } u; }; + +#ifdef CLANG +static_assert(__has_unique_object_representations(U1), "U1"); +static_assert(__has_unique_object_representations(U4), "U4"); +static_assert(__has_unique_object_representations(U5), "U5"); +#else +static_assert(!__has_unique_object_representations(U1), "U1"); +static_assert(!__has_unique_object_representations(U4), "U4"); +static_assert(!__has_unique_object_representations(U5), "U5"); +#endif +static_assert(__has_unique_object_representations(U2), "U2"); +static_assert(__has_unique_object_representations(U3), "U3"); +static_assert(__has_unique_object_representations(S6), "S6"); diff --git a/tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp b/tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp new file mode 100644 index 0000000000..727ed59022 --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-volatile.sft.cpp @@ -0,0 +1,19 @@ +//remark:has_unique_object_representations with volatile-qualified types +//type:fp +//options_all:--c++11 +//options:-DSTD_MODE:--g++ --gnu_version=90400 -DOLD_GNU:--g++ --gnu_version=100100:--g++ --gnu_version=150100:--clang --clang_version=160000:--clang --clang_version=190000:--microsoft + +// Standard behavior: cv-qualification does not affect the result. g++ +// before version 10 treated volatile-qualified non-class types as not having +// unique object representations. +#ifdef OLD_GNU +static_assert(!__has_unique_object_representations(volatile int), "vi"); +static_assert(!__has_unique_object_representations(const volatile int), + "cvi"); +#else +static_assert(__has_unique_object_representations(volatile int), "vi"); +static_assert(__has_unique_object_representations(const volatile int), + "cvi"); +#endif +static_assert(__has_unique_object_representations(int), "i"); +static_assert(__has_unique_object_representations(const int), "ci");