Skip to content

Commit 7dfa839

Browse files
authored
[clang] Fix behavior of __is_trivially_relocatable(volatile int) (#77092)
Consistent with `__is_trivially_copyable(volatile int) == true` and `__is_trivially_relocatable(volatile Trivial) == true`, `__is_trivially_relocatable(volatile int)` should also be `true`. Fixes #77091 [clang] [test] New tests for __is_trivially_relocatable(cv-qualified type)
1 parent fab2bb8 commit 7dfa839

File tree

3 files changed

+111
-75
lines changed

3 files changed

+111
-75
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,9 @@ Bug Fixes in This Version
251251
for logical operators in C23.
252252
Fixes (#GH64356).
253253

254+
- ``__is_trivially_relocatable`` no longer returns ``false`` for volatile-qualified types.
255+
Fixes (#GH77091).
256+
254257
- Clang no longer produces a false-positive `-Wunused-variable` warning
255258
for variables created through copy initialization having side-effects in C++17 and later.
256259
Fixes (#GH64356) (#GH79518).

clang/lib/AST/Type.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,6 +2682,8 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
26822682
return false;
26832683
} else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
26842684
return RD->canPassInRegisters();
2685+
} else if (BaseElementType.isTriviallyCopyableType(Context)) {
2686+
return true;
26852687
} else {
26862688
switch (isNonTrivialToPrimitiveDestructiveMove()) {
26872689
case PCK_Trivial:

clang/test/SemaCXX/type-traits.cpp

Lines changed: 106 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,91 +1722,91 @@ struct StructWithAnonUnion3 {
17221722

17231723
void is_layout_compatible(int n)
17241724
{
1725-
static_assert(__is_layout_compatible(void, void), "");
1726-
static_assert(!__is_layout_compatible(void, int), "");
1727-
static_assert(__is_layout_compatible(void, const void), "");
1728-
static_assert(__is_layout_compatible(void, volatile void), "");
1729-
static_assert(__is_layout_compatible(const int, volatile int), "");
1730-
static_assert(__is_layout_compatible(int, int), "");
1731-
static_assert(__is_layout_compatible(int, const int), "");
1732-
static_assert(__is_layout_compatible(int, volatile int), "");
1733-
static_assert(__is_layout_compatible(const int, volatile int), "");
1734-
static_assert(__is_layout_compatible(int *, int * __restrict), "");
1725+
static_assert(__is_layout_compatible(void, void));
1726+
static_assert(!__is_layout_compatible(void, int));
1727+
static_assert(__is_layout_compatible(void, const void));
1728+
static_assert(__is_layout_compatible(void, volatile void));
1729+
static_assert(__is_layout_compatible(const int, volatile int));
1730+
static_assert(__is_layout_compatible(int, int));
1731+
static_assert(__is_layout_compatible(int, const int));
1732+
static_assert(__is_layout_compatible(int, volatile int));
1733+
static_assert(__is_layout_compatible(const int, volatile int));
1734+
static_assert(__is_layout_compatible(int *, int * __restrict));
17351735
// Note: atomic qualification matters for layout compatibility.
1736-
static_assert(!__is_layout_compatible(int, _Atomic int), "");
1737-
static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), "");
1738-
static_assert(!__is_layout_compatible(int, unsigned int), "");
1739-
static_assert(!__is_layout_compatible(char, unsigned char), "");
1740-
static_assert(!__is_layout_compatible(char, signed char), "");
1741-
static_assert(!__is_layout_compatible(unsigned char, signed char), "");
1742-
static_assert(__is_layout_compatible(int[], int[]), "");
1743-
static_assert(__is_layout_compatible(int[2], int[2]), "");
1744-
static_assert(!__is_layout_compatible(int[n], int[2]), ""); // FIXME: VLAs should be rejected
1745-
static_assert(!__is_layout_compatible(int[n], int[n]), ""); // FIXME: VLAs should be rejected
1746-
static_assert(__is_layout_compatible(int&, int&), "");
1747-
static_assert(!__is_layout_compatible(int&, char&), "");
1748-
static_assert(__is_layout_compatible(void(int), void(int)), "");
1749-
static_assert(!__is_layout_compatible(void(int), void(char)), "");
1750-
static_assert(__is_layout_compatible(void(&)(int), void(&)(int)), "");
1751-
static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)), "");
1752-
static_assert(__is_layout_compatible(void(*)(int), void(*)(int)), "");
1753-
static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)), "");
1736+
static_assert(!__is_layout_compatible(int, _Atomic int));
1737+
static_assert(__is_layout_compatible(_Atomic(int), _Atomic int));
1738+
static_assert(!__is_layout_compatible(int, unsigned int));
1739+
static_assert(!__is_layout_compatible(char, unsigned char));
1740+
static_assert(!__is_layout_compatible(char, signed char));
1741+
static_assert(!__is_layout_compatible(unsigned char, signed char));
1742+
static_assert(__is_layout_compatible(int[], int[]));
1743+
static_assert(__is_layout_compatible(int[2], int[2]));
1744+
static_assert(!__is_layout_compatible(int[n], int[2])); // FIXME: VLAs should be rejected
1745+
static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs should be rejected
1746+
static_assert(__is_layout_compatible(int&, int&));
1747+
static_assert(!__is_layout_compatible(int&, char&));
1748+
static_assert(__is_layout_compatible(void(int), void(int)));
1749+
static_assert(!__is_layout_compatible(void(int), void(char)));
1750+
static_assert(__is_layout_compatible(void(&)(int), void(&)(int)));
1751+
static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)));
1752+
static_assert(__is_layout_compatible(void(*)(int), void(*)(int)));
1753+
static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)));
17541754
using function_type = void();
17551755
using function_type2 = void(char);
1756-
static_assert(__is_layout_compatible(const function_type, const function_type), "");
1756+
static_assert(__is_layout_compatible(const function_type, const function_type));
17571757
// expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
17581758
// expected-warning@-2 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
1759-
static_assert(__is_layout_compatible(function_type, const function_type), "");
1759+
static_assert(__is_layout_compatible(function_type, const function_type));
17601760
// expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
1761-
static_assert(!__is_layout_compatible(const function_type, const function_type2), "");
1761+
static_assert(!__is_layout_compatible(const function_type, const function_type2));
17621762
// expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
17631763
// expected-warning@-2 {{'const' qualifier on function type 'function_type2' (aka 'void (char)') has no effect}}
1764-
static_assert(__is_layout_compatible(CStruct, CStruct2), "");
1765-
static_assert(__is_layout_compatible(CStruct, const CStruct2), "");
1766-
static_assert(__is_layout_compatible(CStruct, volatile CStruct2), "");
1767-
static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), "");
1768-
static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
1769-
static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
1770-
static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), "");
1771-
static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2), "");
1772-
static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2), "");
1773-
static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2), "");
1774-
static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2), "");
1775-
static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2), "");
1776-
static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
1777-
static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
1778-
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
1779-
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
1780-
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
1781-
static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
1782-
static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers), "");
1783-
static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers), "");
1784-
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
1785-
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2), "");
1786-
static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3), "");
1787-
static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4), "");
1788-
static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*), "");
1789-
static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*), "");
1790-
static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)), "");
1791-
static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), "");
1792-
static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
1793-
static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
1794-
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
1795-
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
1796-
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
1797-
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
1798-
static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
1799-
static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
1800-
static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");
1764+
static_assert(__is_layout_compatible(CStruct, CStruct2));
1765+
static_assert(__is_layout_compatible(CStruct, const CStruct2));
1766+
static_assert(__is_layout_compatible(CStruct, volatile CStruct2));
1767+
static_assert(__is_layout_compatible(const CStruct, volatile CStruct2));
1768+
static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2));
1769+
static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2));
1770+
static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2));
1771+
static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2));
1772+
static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2));
1773+
static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2));
1774+
static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2));
1775+
static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2));
1776+
static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2));
1777+
static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2));
1778+
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers));
1779+
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)));
1780+
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)));
1781+
static_assert(__is_layout_compatible(CStruct, CStructAlignment));
1782+
static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers));
1783+
static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers));
1784+
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds));
1785+
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2));
1786+
static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3));
1787+
static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4));
1788+
static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*));
1789+
static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*));
1790+
static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)));
1791+
static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)));
1792+
static_assert(__is_layout_compatible(CStructNested, CStructNested2));
1793+
static_assert(__is_layout_compatible(UnionLayout, UnionLayout));
1794+
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2));
1795+
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3));
1796+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2));
1797+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3));
1798+
static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout));
1799+
static_assert(__is_layout_compatible(EnumForward, EnumForward));
1800+
static_assert(__is_layout_compatible(EnumForward, EnumClassForward));
18011801
// Layout compatibility for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
1802-
static_assert(!__is_layout_compatible(EnumLayout, int), "");
1803-
static_assert(!__is_layout_compatible(EnumClassLayout, int), "");
1804-
static_assert(!__is_layout_compatible(EnumForward, int), "");
1805-
static_assert(!__is_layout_compatible(EnumClassForward, int), "");
1802+
static_assert(!__is_layout_compatible(EnumLayout, int));
1803+
static_assert(!__is_layout_compatible(EnumClassLayout, int));
1804+
static_assert(!__is_layout_compatible(EnumForward, int));
1805+
static_assert(!__is_layout_compatible(EnumClassForward, int));
18061806
// FIXME: the following should be rejected (array of unknown bound and void are the only allowed incomplete types)
1807-
static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete), "");
1808-
static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
1809-
static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]), "");
1807+
static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete));
1808+
static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
1809+
static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]));
18101810
}
18111811

18121812
void is_signed()
@@ -3340,6 +3340,8 @@ namespace is_trivially_relocatable {
33403340
static_assert(!__is_trivially_relocatable(void));
33413341
static_assert(__is_trivially_relocatable(int));
33423342
static_assert(__is_trivially_relocatable(int[]));
3343+
static_assert(__is_trivially_relocatable(const int));
3344+
static_assert(__is_trivially_relocatable(volatile int));
33433345

33443346
enum Enum {};
33453347
static_assert(__is_trivially_relocatable(Enum));
@@ -3351,7 +3353,28 @@ static_assert(__is_trivially_relocatable(Union[]));
33513353

33523354
struct Trivial {};
33533355
static_assert(__is_trivially_relocatable(Trivial));
3356+
static_assert(__is_trivially_relocatable(const Trivial));
3357+
static_assert(__is_trivially_relocatable(volatile Trivial));
3358+
33543359
static_assert(__is_trivially_relocatable(Trivial[]));
3360+
static_assert(__is_trivially_relocatable(const Trivial[]));
3361+
static_assert(__is_trivially_relocatable(volatile Trivial[]));
3362+
3363+
static_assert(__is_trivially_relocatable(int[10]));
3364+
static_assert(__is_trivially_relocatable(const int[10]));
3365+
static_assert(__is_trivially_relocatable(volatile int[10]));
3366+
3367+
static_assert(__is_trivially_relocatable(int[10][10]));
3368+
static_assert(__is_trivially_relocatable(const int[10][10]));
3369+
static_assert(__is_trivially_relocatable(volatile int[10][10]));
3370+
3371+
static_assert(__is_trivially_relocatable(int[]));
3372+
static_assert(__is_trivially_relocatable(const int[]));
3373+
static_assert(__is_trivially_relocatable(volatile int[]));
3374+
3375+
static_assert(__is_trivially_relocatable(int[][10]));
3376+
static_assert(__is_trivially_relocatable(const int[][10]));
3377+
static_assert(__is_trivially_relocatable(volatile int[][10]));
33553378

33563379
struct Incomplete; // expected-note {{forward declaration of 'is_trivially_relocatable::Incomplete'}}
33573380
bool unused = __is_trivially_relocatable(Incomplete); // expected-error {{incomplete type}}
@@ -3361,6 +3384,8 @@ struct NontrivialDtor {
33613384
};
33623385
static_assert(!__is_trivially_relocatable(NontrivialDtor));
33633386
static_assert(!__is_trivially_relocatable(NontrivialDtor[]));
3387+
static_assert(!__is_trivially_relocatable(const NontrivialDtor));
3388+
static_assert(!__is_trivially_relocatable(volatile NontrivialDtor));
33643389

33653390
struct NontrivialCopyCtor {
33663391
NontrivialCopyCtor(const NontrivialCopyCtor&) {}
@@ -3379,12 +3404,16 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialDtor {
33793404
};
33803405
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor));
33813406
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[]));
3407+
static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialDtor));
3408+
static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialDtor));
33823409

33833410
struct [[clang::trivial_abi]] TrivialAbiNontrivialCopyCtor {
33843411
TrivialAbiNontrivialCopyCtor(const TrivialAbiNontrivialCopyCtor&) {}
33853412
};
33863413
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor));
33873414
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[]));
3415+
static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialCopyCtor));
3416+
static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialCopyCtor));
33883417

33893418
// A more complete set of tests for the behavior of trivial_abi can be found in
33903419
// clang/test/SemaCXX/attr-trivial-abi.cpp
@@ -3393,6 +3422,8 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialMoveCtor {
33933422
};
33943423
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor));
33953424
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]));
3425+
static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialMoveCtor));
3426+
static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialMoveCtor));
33963427

33973428
} // namespace is_trivially_relocatable
33983429

0 commit comments

Comments
 (0)