aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/ext
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-07-10 23:14:19 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2024-08-23 13:39:36 +0100
commit8cf51d7516b92b352c358c14ab4e456ae53c3371 (patch)
treef1f88a471ea22c4d2f272bc02cae91bc59feccba /libstdc++-v3/testsuite/ext
parent43b8153c26655a7a00f1584fcb4f511dc5e45fab (diff)
downloadgcc-8cf51d7516b92b352c358c14ab4e456ae53c3371.zip
gcc-8cf51d7516b92b352c358c14ab4e456ae53c3371.tar.gz
gcc-8cf51d7516b92b352c358c14ab4e456ae53c3371.tar.bz2
libstdc++: Fix std::allocator_traits::construct constraints [PR108619]
Using std::is_constructible in the constraints introduces a spurious dependency on the type being destructible, which should not be required for constructing with an allocator. The test case shows a case where the type has a private destructor, which can be destroyed by the allocator, but std::is_destructible and std::is_constructible are false. Similarly, using is_nothrow_constructible in the noexcept-specifiers for the construct members of allocator_traits and std::allocator, __gnu_cxx::__new_allocator, and __gnu_cxx::__malloc_allocator gives the wrong answer if the type isn't destructible. We need a new type trait to define those correctly, so that we only check if the placement new-expression is nothrow after using is_constructible to check that it would be well-formed. Instead of just fixing the overly restrictive constraint to check for placement new, rewrite allocator_traits in terms of 'if constexpr' using variable templates and the detection idiom. Although we can use 'if constexpr' and variable templates in C++11 with appropriate uses of diagnostic pragmas, we can't have constexpr functions with multiple return statements. This means that in C++11 mode the _S_nothrow_construct and _S_nothrow_destroy helpers used for noexcept-specifiers still need to be overlaods using enable_if. Nearly everything else can be simplified to reduce overload resolution and enable_if checks. libstdc++-v3/ChangeLog: PR libstdc++/108619 * include/bits/alloc_traits.h (__allocator_traits_base): Add variable templates for detecting which allocator operations are supported. (allocator_traits): Use 'if constexpr' instead of dispatching to overloads constrained with enable_if. (allocator_traits<allocator<T>>::construct): Use Construct if construct_at is not supported. Use __is_nothrow_new_constructible for noexcept-specifier. (allocator_traits<allocator<void>>::construct): Use __is_nothrow_new_constructible for noexcept-specifier. * include/bits/new_allocator.h (construct): Likewise. * include/ext/malloc_allocator.h (construct): Likewise. * include/std/type_traits (__is_nothrow_new_constructible): New variable template. * testsuite/20_util/allocator/89510.cc: Adjust expected results. * testsuite/ext/malloc_allocator/89510.cc: Likewise. * testsuite/ext/new_allocator/89510.cc: Likewise. * testsuite/20_util/allocator_traits/members/108619.cc: New test.
Diffstat (limited to 'libstdc++-v3/testsuite/ext')
-rw-r--r--libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc14
-rw-r--r--libstdc++-v3/testsuite/ext/new_allocator/89510.cc14
2 files changed, 12 insertions, 16 deletions
diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc
index 1889c88..771facb 100644
--- a/libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc
+++ b/libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc
@@ -137,13 +137,11 @@ struct Z
};
Z* zp;
-// These construct calls should be noexcept, but they are false because
-// they use is_nothrow_constructible which depends on is_nothrow_destructible.
#if __cplusplus <= 201703L
-static_assert( ! noexcept(a.construct(zp)), "wrong" );
-static_assert( ! noexcept(a.construct(zp, 1)), "wrong" );
-static_assert( ! noexcept(a.destroy(zp)), "" );
+static_assert( noexcept(a.construct(zp)), "" );
+static_assert( noexcept(a.construct(zp, 1)), "" );
+static_assert( ! noexcept(a.destroy(zp)), "~Z is noexcept(false)" );
#endif
-static_assert( ! noexcept(AT::construct(a, zp)), "" );
-static_assert( ! noexcept(AT::construct(a, zp, 1)), "" );
-static_assert( ! noexcept(AT::destroy(a, zp)), "" );
+static_assert( noexcept(AT::construct(a, zp)), "" );
+static_assert( noexcept(AT::construct(a, zp, 1)), "" );
+static_assert( ! noexcept(AT::destroy(a, zp)), "~Z is noexcept(false)" );
diff --git a/libstdc++-v3/testsuite/ext/new_allocator/89510.cc b/libstdc++-v3/testsuite/ext/new_allocator/89510.cc
index 06384ae..7fc4438 100644
--- a/libstdc++-v3/testsuite/ext/new_allocator/89510.cc
+++ b/libstdc++-v3/testsuite/ext/new_allocator/89510.cc
@@ -137,13 +137,11 @@ struct Z
};
Z* zp;
-// These construct calls should be noexcept, but they are false because
-// they use is_nothrow_constructible which depends on is_nothrow_destructible.
#if __cplusplus <= 201703L
-static_assert( ! noexcept(a.construct(zp)), "wrong" );
-static_assert( ! noexcept(a.construct(zp, 1)), "wrong" );
-static_assert( ! noexcept(a.destroy(zp)), "" );
+static_assert( noexcept(a.construct(zp)), "" );
+static_assert( noexcept(a.construct(zp, 1)), "" );
+static_assert( ! noexcept(a.destroy(zp)), "~Z is noexcept(false)" );
#endif
-static_assert( ! noexcept(AT::construct(a, zp)), "" );
-static_assert( ! noexcept(AT::construct(a, zp, 1)), "" );
-static_assert( ! noexcept(AT::destroy(a, zp)), "" );
+static_assert( noexcept(AT::construct(a, zp)), "" );
+static_assert( noexcept(AT::construct(a, zp, 1)), "" );
+static_assert( ! noexcept(AT::destroy(a, zp)), "~Z is noexcept(false)" );