* [PATCH] libstdc++: Fix std::to_array for trivial-ish types [PR115522]
@ 2024-06-19 16:37 Jonathan Wakely
2024-06-21 9:15 ` Jonathan Wakely
0 siblings, 1 reply; 2+ messages in thread
From: Jonathan Wakely @ 2024-06-19 16:37 UTC (permalink / raw)
To: gcc-patches, libstdc++
Tested x86_64-linux. Not pushed yet. backports will be needed too.
-- >8 --
Due to PR c++/85723 the std::is_trivial trait is true for types with a
deleted default constructor, so the use of std::is_trivial in
std::to_array is not sufficient to ensure the type can be trivially
default constructed then filled using memcpy.
I also forgot that a type with a deleted assignment operator can still
be trivial, so we also need to check that it's assignable because the
is_constant_evaluated() path can't use memcpy.
Replace the uses of std::is_trivial with std::is_trivially_copyable
(needed for memcpy), std::is_trivially_default_constructible (needed so
that the default construction is valid and does no work) and
std::is_copy_assignable (needed for the constant evaluation case).
libstdc++-v3/ChangeLog:
PR libstdc++/115522
* include/std/array (to_array): Workaround the fact that
std::is_trivial is not sufficient to check that a type is
trivially default constructible and assignable.
* testsuite/23_containers/array/creation/115522.cc: New test.
---
libstdc++-v3/include/std/array | 8 +++--
.../23_containers/array/creation/115522.cc | 33 +++++++++++++++++++
2 files changed, 39 insertions(+), 2 deletions(-)
create mode 100644 libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index 39695471e24..8710bf75924 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -431,7 +431,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_constructible_v<_Tp, _Tp&>);
if constexpr (is_constructible_v<_Tp, _Tp&>)
{
- if constexpr (is_trivial_v<_Tp>)
+ if constexpr (is_trivially_copyable_v<_Tp>
+ && is_trivially_default_constructible_v<_Tp>
+ && is_copy_assignable_v<_Tp>)
{
array<remove_cv_t<_Tp>, _Nm> __arr;
if (!__is_constant_evaluated() && _Nm != 0)
@@ -460,7 +462,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_move_constructible_v<_Tp>);
if constexpr (is_move_constructible_v<_Tp>)
{
- if constexpr (is_trivial_v<_Tp>)
+ if constexpr (is_trivially_copyable_v<_Tp>
+ && is_trivially_default_constructible_v<_Tp>
+ && is_copy_assignable_v<_Tp>)
{
array<remove_cv_t<_Tp>, _Nm> __arr;
if (!__is_constant_evaluated() && _Nm != 0)
diff --git a/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
new file mode 100644
index 00000000000..37073e002bd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++20 } }
+
+// PR libstdc++/115522 std::to_array no longer works for struct which is
+// trivial but not default constructible
+
+#include <array>
+
+void
+test_deleted_ctor()
+{
+ struct S
+ {
+ S() = delete;
+ S(int) { }
+ };
+
+ S arr[1] = {{1}};
+ auto arr1 = std::to_array(arr);
+ auto arr2 = std::to_array(std::move(arr));
+}
+
+void
+test_deleted_assignment()
+{
+ struct S
+ {
+ void operator=(const S&) = delete;
+ };
+
+ S arr[1] = {};
+ auto a1 = std::to_array(arr);
+ auto a2 = std::to_array(std::move(arr));
+}
--
2.45.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] libstdc++: Fix std::to_array for trivial-ish types [PR115522]
2024-06-19 16:37 [PATCH] libstdc++: Fix std::to_array for trivial-ish types [PR115522] Jonathan Wakely
@ 2024-06-21 9:15 ` Jonathan Wakely
0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2024-06-21 9:15 UTC (permalink / raw)
To: gcc-patches, libstdc++
Pushed to trunk now.
On Wed, 19 Jun 2024 at 17:38, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> Tested x86_64-linux. Not pushed yet. backports will be needed too.
>
> -- >8 --
>
> Due to PR c++/85723 the std::is_trivial trait is true for types with a
> deleted default constructor, so the use of std::is_trivial in
> std::to_array is not sufficient to ensure the type can be trivially
> default constructed then filled using memcpy.
>
> I also forgot that a type with a deleted assignment operator can still
> be trivial, so we also need to check that it's assignable because the
> is_constant_evaluated() path can't use memcpy.
>
> Replace the uses of std::is_trivial with std::is_trivially_copyable
> (needed for memcpy), std::is_trivially_default_constructible (needed so
> that the default construction is valid and does no work) and
> std::is_copy_assignable (needed for the constant evaluation case).
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/115522
> * include/std/array (to_array): Workaround the fact that
> std::is_trivial is not sufficient to check that a type is
> trivially default constructible and assignable.
> * testsuite/23_containers/array/creation/115522.cc: New test.
> ---
> libstdc++-v3/include/std/array | 8 +++--
> .../23_containers/array/creation/115522.cc | 33 +++++++++++++++++++
> 2 files changed, 39 insertions(+), 2 deletions(-)
> create mode 100644 libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
>
> diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
> index 39695471e24..8710bf75924 100644
> --- a/libstdc++-v3/include/std/array
> +++ b/libstdc++-v3/include/std/array
> @@ -431,7 +431,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> static_assert(is_constructible_v<_Tp, _Tp&>);
> if constexpr (is_constructible_v<_Tp, _Tp&>)
> {
> - if constexpr (is_trivial_v<_Tp>)
> + if constexpr (is_trivially_copyable_v<_Tp>
> + && is_trivially_default_constructible_v<_Tp>
> + && is_copy_assignable_v<_Tp>)
> {
> array<remove_cv_t<_Tp>, _Nm> __arr;
> if (!__is_constant_evaluated() && _Nm != 0)
> @@ -460,7 +462,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> static_assert(is_move_constructible_v<_Tp>);
> if constexpr (is_move_constructible_v<_Tp>)
> {
> - if constexpr (is_trivial_v<_Tp>)
> + if constexpr (is_trivially_copyable_v<_Tp>
> + && is_trivially_default_constructible_v<_Tp>
> + && is_copy_assignable_v<_Tp>)
> {
> array<remove_cv_t<_Tp>, _Nm> __arr;
> if (!__is_constant_evaluated() && _Nm != 0)
> diff --git a/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
> new file mode 100644
> index 00000000000..37073e002bd
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/array/creation/115522.cc
> @@ -0,0 +1,33 @@
> +// { dg-do compile { target c++20 } }
> +
> +// PR libstdc++/115522 std::to_array no longer works for struct which is
> +// trivial but not default constructible
> +
> +#include <array>
> +
> +void
> +test_deleted_ctor()
> +{
> + struct S
> + {
> + S() = delete;
> + S(int) { }
> + };
> +
> + S arr[1] = {{1}};
> + auto arr1 = std::to_array(arr);
> + auto arr2 = std::to_array(std::move(arr));
> +}
> +
> +void
> +test_deleted_assignment()
> +{
> + struct S
> + {
> + void operator=(const S&) = delete;
> + };
> +
> + S arr[1] = {};
> + auto a1 = std::to_array(arr);
> + auto a2 = std::to_array(std::move(arr));
> +}
> --
> 2.45.1
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-06-21 9:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-19 16:37 [PATCH] libstdc++: Fix std::to_array for trivial-ish types [PR115522] Jonathan Wakely
2024-06-21 9:15 ` Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).