diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-07-10 23:14:19 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2024-08-23 13:39:36 +0100 |
commit | 8cf51d7516b92b352c358c14ab4e456ae53c3371 (patch) | |
tree | f1f88a471ea22c4d2f272bc02cae91bc59feccba /gcc | |
parent | 43b8153c26655a7a00f1584fcb4f511dc5e45fab (diff) | |
download | gcc-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 'gcc')
0 files changed, 0 insertions, 0 deletions