From 4b5fe66b2ed0fa7a2d8f885311cda3d167d0e9e5 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 | 38 ++++++++++++++++ src/folding.c | 45 +++++++++++++++---- 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.1.1.txt | 1 + .../default.2.1.txt | 1 + .../default.3.1.txt | 1 + .../default.4.1.txt | 1 + .../default.5.1.txt | 1 + .../has-unique-object-rep-bit-field.sft.cpp | 32 +++++++++++++ ...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 ++++++++ 35 files changed, 204 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-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-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 eb76142282..4d7b7d4711 100644 --- a/src/Changes +++ b/src/Changes @@ -1,5 +1,43 @@ 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, as the + standard requires, except in g++ modes before 13.1 (other than 10.5, + 11.4, and 12.3) and in Clang modes before 17. For example: + + struct S { char a; char : 8; char b; }; + static_assert(!__has_unique_object_representations(S), ""); + + - 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, + with --microsoft: + + union U { int x : 3; }; + static_assert(__has_unique_object_representations(U), ""); + + - 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). + + 10/21/26 [GH #335] Type transformations of qualified function types diff --git a/src/folding.c b/src/folding.c index 221d60bf1f..16a69f91d1 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,19 @@ 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() && + symbol_for(field) == 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 +9106,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 036be42be2..2c384ac8c4 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..6cbd97ece6 --- /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 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..cb11de8965 --- /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 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..5adc48ac1b --- /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 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..36ff129ab0 --- /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 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..ff6ae5e2d9 --- /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 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..d5b7e2da21 --- /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 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..6cbd97ece6 --- /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 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..7970c7d9ab --- /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=150100 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..ea04864188 --- /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 --clang --clang_version=190000 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..fa0e0c6853 --- /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 --microsoft 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..6cbd97ece6 --- /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 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..cb11de8965 --- /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 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..c9020a62d9 --- /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 --clang --clang_version=190000 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..1c0333182b --- /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 --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..6b1313661c --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp @@ -0,0 +1,32 @@ +//remark:has_unique_object_representations with unnamed bit-fields +//type:fp +//options_all:--c++11 +//options::--g++ --gnu_version=90400:--g++ --gnu_version=100400:--g++ --gnu_version=100500:--g++ --gnu_version=120200:--g++ --gnu_version=120300:--g++ --gnu_version=150100:--clang --clang_version=160000:--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. + +#if defined(__GNUC__) && !defined(__clang__) +#define GNU_VER (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +#define GNU_VER 0 +#endif +#if (GNU_VER != 0 && (GNU_VER < 100500 || \ + (GNU_VER >= 120000 && GNU_VER < 120300))) || \ + (defined(__clang__) && __clang_major__ < 17) +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..640adde16d --- /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::--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..ca86ff74b8 --- /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::--g++ --gnu_version=150100:--clang --clang_version=190000:--microsoft + +// 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; }; + +#if defined(__clang__) || defined(_MSC_VER) +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..f04a815052 --- /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::--g++ --gnu_version=90400:--g++ --gnu_version=100100:--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. +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10 +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");