diff --git a/src/folding.c b/src/folding.c index 221d60bf1f..2a40aa2923 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 @@ -9027,13 +9047,21 @@ architectures for which these assumptions are not valid. for (field = type->variant.class_struct_union.field_list; result && field != NULL; field = field->next) { a_type_ptr field_type = skip_typerefs(field->type); - if (type->kind == (a_type_kind)tk_union && + if (type_is(type, 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_is(type, 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) { @@ -9043,7 +9071,7 @@ architectures for which these assumptions are not valid. if (!type_has_unique_object_representations(field_type, NULL)) { result = FALSE; } /* if */ - if (type->kind == (a_type_kind)tk_union) { + if (type_is(type, tk_union)) { /* Do not update end_of_last_subobject: each subobject begins at offset 0. The previous field size is the same as that of the union; otherwise, it would have failed the bit_size @@ -9061,7 +9089,7 @@ architectures for which these assumptions are not valid. } /* if */ } /* for */ /* Finally, check for tail padding. */ - if (type->kind == (a_type_kind)tk_union) { + if (type_is(type, tk_union)) { if (type->variant.class_struct_union.field_list == NULL) { /* An empty union still has has a non-zero size, which counts as padding. */ @@ -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/src/pending_changes/gh-327-has-unique-object-representations.txt b/src/pending_changes/gh-327-has-unique-object-representations.txt new file mode 100644 index 0000000000..b0484264db --- /dev/null +++ b/src/pending_changes/gh-327-has-unique-object-representations.txt @@ -0,0 +1,36 @@ +[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). 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..72f407799a --- /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 --clang --clang_version=160000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.11.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.11.1.txt new file mode 100644 index 0000000000..213d5b4058 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.11.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=11 --c++11 --clang --clang_version=170000 Test_name.c diff --git a/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.12.1.txt b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.12.1.txt new file mode 100644 index 0000000000..75a47e7507 --- /dev/null +++ b/tests/tests/regressions/.has-unique-object-rep-bit-field.rto/default.12.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=12 --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..965ed15000 --- /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=110300 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..513802f4cb --- /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=110400 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..118ae7060d --- /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=120200 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..e438313c0d --- /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 --g++ --gnu_version=120300 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..edc5d5f984 --- /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 --g++ --gnu_version=150100 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..8887d632c0 --- /dev/null +++ b/tests/tests/regressions/has-unique-object-rep-bit-field.sft.cpp @@ -0,0 +1,35 @@ +//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=110300:--g++ --gnu_version=110400:--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. +struct Z { char a; char : 0; char b; }; // Zero-width: 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 >= 110000 && GNU_VER < 110400) || \ + (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"); +static_assert(__has_unique_object_representations(Z), "Z"); 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");