[clang] [clang] Fix behavior of `__is_trivially_relocatable(volatile int)` (PR #77092)
Amirreza Ashouri via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 10 13:12:32 PDT 2024
https://github.com/AMP999 updated https://github.com/llvm/llvm-project/pull/77092
>From ed94371b8e2293642731b72948883c2ec20bd09d Mon Sep 17 00:00:00 2001
From: Amirreza Ashouri <ar.ashouri999 at gmail.com>
Date: Wed, 3 Jan 2024 23:23:14 +0330
Subject: [PATCH 1/3] [clang] Fix behavior of
__is_trivially_relocatable(volatile int)
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 https://github.com/llvm/llvm-project/issues/77091
[clang] [test] New tests for __is_trivially_relocatable(cv-qualified type)
---
clang/docs/ReleaseNotes.rst | 5 +++++
clang/lib/AST/Type.cpp | 2 ++
clang/test/SemaCXX/type-traits.cpp | 31 ++++++++++++++++++++++++++++++
3 files changed, 38 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 402a2f8687386c..d1e0fec9862d8f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -175,6 +175,11 @@ Bug Fixes in This Version
- Clang now doesn't produce false-positive warning `-Wconstant-logical-operand`
for logical operators in C23.
Fixes (`#64356 <https://github.com/llvm/llvm-project/issues/64356>`_).
+- ``__is_trivially_relocatable`` no longer returns ``true`` for non-object types
+ such as references and functions, and no longer returns ``false`` for volatile-qualified types.
+ Fixes (`#67498 <https://github.com/llvm/llvm-project/issues/67498>`_) and
+ (`#77091 <https://github.com/llvm/llvm-project/issues/77091>`_)
+
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 78dcd3f4007a5a..22666184c56ccf 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2682,6 +2682,8 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
return false;
} else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
return RD->canPassInRegisters();
+ } else if (BaseElementType.isTriviallyCopyableType(Context)) {
+ return true;
} else {
switch (isNonTrivialToPrimitiveDestructiveMove()) {
case PCK_Trivial:
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..d4f26adfc04147 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -3104,6 +3104,8 @@ namespace is_trivially_relocatable {
static_assert(!__is_trivially_relocatable(void), "");
static_assert(__is_trivially_relocatable(int), "");
static_assert(__is_trivially_relocatable(int[]), "");
+static_assert(__is_trivially_relocatable(const int), "");
+static_assert(__is_trivially_relocatable(volatile int), "");
enum Enum {};
static_assert(__is_trivially_relocatable(Enum), "");
@@ -3115,7 +3117,28 @@ static_assert(__is_trivially_relocatable(Union[]), "");
struct Trivial {};
static_assert(__is_trivially_relocatable(Trivial), "");
+static_assert(__is_trivially_relocatable(const Trivial), "");
+static_assert(__is_trivially_relocatable(volatile Trivial), "");
+
static_assert(__is_trivially_relocatable(Trivial[]), "");
+static_assert(__is_trivially_relocatable(const Trivial[]), "");
+static_assert(__is_trivially_relocatable(volatile Trivial[]), "");
+
+static_assert(__is_trivially_relocatable(int[10]), "");
+static_assert(__is_trivially_relocatable(const int[10]), "");
+static_assert(__is_trivially_relocatable(volatile int[10]), "");
+
+static_assert(__is_trivially_relocatable(int[10][10]), "");
+static_assert(__is_trivially_relocatable(const int[10][10]), "");
+static_assert(__is_trivially_relocatable(volatile int[10][10]), "");
+
+static_assert(__is_trivially_relocatable(int[]), "");
+static_assert(__is_trivially_relocatable(const int[]), "");
+static_assert(__is_trivially_relocatable(volatile int[]), "");
+
+static_assert(__is_trivially_relocatable(int[][10]), "");
+static_assert(__is_trivially_relocatable(const int[][10]), "");
+static_assert(__is_trivially_relocatable(volatile int[][10]), "");
struct Incomplete; // expected-note {{forward declaration of 'is_trivially_relocatable::Incomplete'}}
bool unused = __is_trivially_relocatable(Incomplete); // expected-error {{incomplete type}}
@@ -3125,6 +3148,8 @@ struct NontrivialDtor {
};
static_assert(!__is_trivially_relocatable(NontrivialDtor), "");
static_assert(!__is_trivially_relocatable(NontrivialDtor[]), "");
+static_assert(!__is_trivially_relocatable(const NontrivialDtor), "");
+static_assert(!__is_trivially_relocatable(volatile NontrivialDtor), "");
struct NontrivialCopyCtor {
NontrivialCopyCtor(const NontrivialCopyCtor&) {}
@@ -3143,12 +3168,16 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialDtor {
};
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor), "");
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[]), "");
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialDtor), "");
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialDtor), "");
struct [[clang::trivial_abi]] TrivialAbiNontrivialCopyCtor {
TrivialAbiNontrivialCopyCtor(const TrivialAbiNontrivialCopyCtor&) {}
};
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor), "");
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[]), "");
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialCopyCtor), "");
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialCopyCtor), "");
// A more complete set of tests for the behavior of trivial_abi can be found in
// clang/test/SemaCXX/attr-trivial-abi.cpp
@@ -3157,6 +3186,8 @@ struct [[clang::trivial_abi]] TrivialAbiNontrivialMoveCtor {
};
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor), "");
static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]), "");
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialMoveCtor), "");
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialMoveCtor), "");
} // namespace is_trivially_relocatable
>From 67e69addb2297de0c54370ffb9fb77330ce5d111 Mon Sep 17 00:00:00 2001
From: Amirreza Ashouri <ar.ashouri999 at gmail.com>
Date: Sat, 9 Mar 2024 16:59:46 +0330
Subject: [PATCH 2/3] [NFC] Eliminate empty messages in `static_assert`s
---
clang/test/SemaCXX/type-traits.cpp | 150 ++++++++++++++---------------
1 file changed, 75 insertions(+), 75 deletions(-)
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 8d433099c2683d..14ec17989ec7c7 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1722,91 +1722,91 @@ struct StructWithAnonUnion3 {
void is_layout_compatible(int n)
{
- static_assert(__is_layout_compatible(void, void), "");
- static_assert(!__is_layout_compatible(void, int), "");
- static_assert(__is_layout_compatible(void, const void), "");
- static_assert(__is_layout_compatible(void, volatile void), "");
- static_assert(__is_layout_compatible(const int, volatile int), "");
- static_assert(__is_layout_compatible(int, int), "");
- static_assert(__is_layout_compatible(int, const int), "");
- static_assert(__is_layout_compatible(int, volatile int), "");
- static_assert(__is_layout_compatible(const int, volatile int), "");
- static_assert(__is_layout_compatible(int *, int * __restrict), "");
+ static_assert(__is_layout_compatible(void, void));
+ static_assert(!__is_layout_compatible(void, int));
+ static_assert(__is_layout_compatible(void, const void));
+ static_assert(__is_layout_compatible(void, volatile void));
+ static_assert(__is_layout_compatible(const int, volatile int));
+ static_assert(__is_layout_compatible(int, int));
+ static_assert(__is_layout_compatible(int, const int));
+ static_assert(__is_layout_compatible(int, volatile int));
+ static_assert(__is_layout_compatible(const int, volatile int));
+ static_assert(__is_layout_compatible(int *, int * __restrict));
// Note: atomic qualification matters for layout compatibility.
- static_assert(!__is_layout_compatible(int, _Atomic int), "");
- static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), "");
- static_assert(!__is_layout_compatible(int, unsigned int), "");
- static_assert(!__is_layout_compatible(char, unsigned char), "");
- static_assert(!__is_layout_compatible(char, signed char), "");
- static_assert(!__is_layout_compatible(unsigned char, signed char), "");
- static_assert(__is_layout_compatible(int[], int[]), "");
- static_assert(__is_layout_compatible(int[2], int[2]), "");
- static_assert(!__is_layout_compatible(int[n], int[2]), ""); // FIXME: VLAs should be rejected
- static_assert(!__is_layout_compatible(int[n], int[n]), ""); // FIXME: VLAs should be rejected
- static_assert(__is_layout_compatible(int&, int&), "");
- static_assert(!__is_layout_compatible(int&, char&), "");
- static_assert(__is_layout_compatible(void(int), void(int)), "");
- static_assert(!__is_layout_compatible(void(int), void(char)), "");
- static_assert(__is_layout_compatible(void(&)(int), void(&)(int)), "");
- static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)), "");
- static_assert(__is_layout_compatible(void(*)(int), void(*)(int)), "");
- static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)), "");
+ static_assert(!__is_layout_compatible(int, _Atomic int));
+ static_assert(__is_layout_compatible(_Atomic(int), _Atomic int));
+ static_assert(!__is_layout_compatible(int, unsigned int));
+ static_assert(!__is_layout_compatible(char, unsigned char));
+ static_assert(!__is_layout_compatible(char, signed char));
+ static_assert(!__is_layout_compatible(unsigned char, signed char));
+ static_assert(__is_layout_compatible(int[], int[]));
+ static_assert(__is_layout_compatible(int[2], int[2]));
+ static_assert(!__is_layout_compatible(int[n], int[2])); // FIXME: VLAs should be rejected
+ static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs should be rejected
+ static_assert(__is_layout_compatible(int&, int&));
+ static_assert(!__is_layout_compatible(int&, char&));
+ static_assert(__is_layout_compatible(void(int), void(int)));
+ static_assert(!__is_layout_compatible(void(int), void(char)));
+ static_assert(__is_layout_compatible(void(&)(int), void(&)(int)));
+ static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)));
+ static_assert(__is_layout_compatible(void(*)(int), void(*)(int)));
+ static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)));
using function_type = void();
using function_type2 = void(char);
- static_assert(__is_layout_compatible(const function_type, const function_type), "");
+ static_assert(__is_layout_compatible(const function_type, const function_type));
// expected-warning at -1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
// expected-warning at -2 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
- static_assert(__is_layout_compatible(function_type, const function_type), "");
+ static_assert(__is_layout_compatible(function_type, const function_type));
// expected-warning at -1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
- static_assert(!__is_layout_compatible(const function_type, const function_type2), "");
+ static_assert(!__is_layout_compatible(const function_type, const function_type2));
// expected-warning at -1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
// expected-warning at -2 {{'const' qualifier on function type 'function_type2' (aka 'void (char)') has no effect}}
- static_assert(__is_layout_compatible(CStruct, CStruct2), "");
- static_assert(__is_layout_compatible(CStruct, const CStruct2), "");
- static_assert(__is_layout_compatible(CStruct, volatile CStruct2), "");
- static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), "");
- static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
- static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
- static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
- static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
- static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
- static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
- static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
- static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
- static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers), "");
- static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers), "");
- static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
- static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2), "");
- static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3), "");
- static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4), "");
- static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*), "");
- static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*), "");
- static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)), "");
- static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), "");
- static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
- static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
- static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
- static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
- static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
- static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
- static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
- static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
- static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");
+ static_assert(__is_layout_compatible(CStruct, CStruct2));
+ static_assert(__is_layout_compatible(CStruct, const CStruct2));
+ static_assert(__is_layout_compatible(CStruct, volatile CStruct2));
+ static_assert(__is_layout_compatible(const CStruct, volatile CStruct2));
+ static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2));
+ static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2));
+ static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2));
+ static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2));
+ static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers));
+ static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)));
+ static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)));
+ static_assert(__is_layout_compatible(CStruct, CStructAlignment));
+ static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers));
+ static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers));
+ static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds));
+ static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2));
+ static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3));
+ static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4));
+ static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*));
+ static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*));
+ static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)));
+ static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)));
+ static_assert(__is_layout_compatible(CStructNested, CStructNested2));
+ static_assert(__is_layout_compatible(UnionLayout, UnionLayout));
+ static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2));
+ static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3));
+ static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2));
+ static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3));
+ static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout));
+ static_assert(__is_layout_compatible(EnumForward, EnumForward));
+ static_assert(__is_layout_compatible(EnumForward, EnumClassForward));
// Layout compatibility for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
- static_assert(!__is_layout_compatible(EnumLayout, int), "");
- static_assert(!__is_layout_compatible(EnumClassLayout, int), "");
- static_assert(!__is_layout_compatible(EnumForward, int), "");
- static_assert(!__is_layout_compatible(EnumClassForward, int), "");
+ static_assert(!__is_layout_compatible(EnumLayout, int));
+ static_assert(!__is_layout_compatible(EnumClassLayout, int));
+ static_assert(!__is_layout_compatible(EnumForward, int));
+ static_assert(!__is_layout_compatible(EnumClassForward, int));
// FIXME: the following should be rejected (array of unknown bound and void are the only allowed incomplete types)
- static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete), "");
- static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
- static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]), "");
+ static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete));
+ static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
+ static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]));
}
void is_signed()
>From d8f6fd452fc7a8d96bae22c0d70032b7a0fd4581 Mon Sep 17 00:00:00 2001
From: Amirreza Ashouri <ar.ashouri999 at gmail.com>
Date: Sun, 10 Mar 2024 23:40:30 +0330
Subject: [PATCH 3/3] Fix the code style in `ReleaseNotes.rst`
---
clang/docs/ReleaseNotes.rst | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index be12ef46669563..0a3c8bdb683b51 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -249,14 +249,12 @@ Bug Fixes in This Version
- Clang now doesn't produce false-positive warning `-Wconstant-logical-operand`
for logical operators in C23.
- Fixes (`#64356 <https://github.com/llvm/llvm-project/issues/64356>`_).
-- ``__is_trivially_relocatable`` no longer returns ``true`` for non-object types
- such as references and functions, and no longer returns ``false`` for volatile-qualified types.
- Fixes (`#67498 <https://github.com/llvm/llvm-project/issues/67498>`_) and
- (`#77091 <https://github.com/llvm/llvm-project/issues/77091>`_)
-
Fixes (#GH64356).
+- ``__is_trivially_relocatable`` no longer returns ``true`` for non-object types
+ such as references and functions, and no longer returns ``false`` for volatile-qualified types.
+ Fixes (#GH67498) and (#GH77091).
+
- Clang no longer produces a false-positive `-Wunused-variable` warning
for variables created through copy initialization having side-effects in C++17 and later.
Fixes (#GH64356) (#GH79518).
More information about the cfe-commits
mailing list