libstdc++: Avoid errors in allocator's noexcept-specifier (PR 89510)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 30 Apr 2020 14:47:52 +0000 (15:47 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 30 Apr 2020 15:01:43 +0000 (16:01 +0100)
commitb1983f4582bbe060b7da83578acb9ed653681fc8
treeee0a4badb32338e9f157a7241a365acc588cff26
parent448c89d590455ed4ab7abc40309b5cf8ec52d13d
libstdc++: Avoid errors in allocator's noexcept-specifier (PR 89510)

This fixes a regression due to the conditional noexcept-specifier on
std::allocator::construct and std::allocator::destroy, as well as the
corresponding members of new_allocator, malloc_allocator, and
allocator_traits. Those noexcept-specifiers were using expressions which
might be ill-formed, which caused errors outside the immediate context
when checking for the presence of construct and destroy in SFINAE
contexts.

The fix is to use the is_nothrow_constructible and
is_nothrow_destructible type traits instead, because those traits are
safe to use even when the construction/destruction itself is not valid.

The is_nothrow_constructible trait will be false for a type that is not
also nothrow-destructible, even if the new-expression used in the
construct function body is actually noexcept. That's not the correct
answer, but isn't a problem because providing a noexcept-specifier on
these functions is not required by the standard anyway. If the answer is
false when it should be true, that's suboptimal but OK (unlike giving
errors for valid code, or giving a true answer when it should be false).

PR libstdc++/89510
* include/bits/alloc_traits.h (allocator_traits::_S_construct)
(allocator_traits::_S_destroy)
(allocator_traits<allocator<T>>::construct): Use traits in
noexcept-specifiers.
* include/bits/allocator.h (allocator<void>::construct)
(allocator<void>::destroy): Likewise.
* include/ext/malloc_allocator.h (malloc_allocator::construct)
(malloc_allocator::destroy): Likewise.
* include/ext/new_allocator.h (new_allocator::construct)
(new_allocator::destroy): Likewise.
* testsuite/20_util/allocator/89510.cc: New test.
* testsuite/ext/malloc_allocator/89510.cc: New test.
* testsuite/ext/new_allocator/89510.cc: New test.
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/alloc_traits.h
libstdc++-v3/include/bits/allocator.h
libstdc++-v3/include/ext/malloc_allocator.h
libstdc++-v3/include/ext/new_allocator.h
libstdc++-v3/testsuite/20_util/allocator/89510.cc [new file with mode: 0644]
libstdc++-v3/testsuite/ext/malloc_allocator/89510.cc [new file with mode: 0644]
libstdc++-v3/testsuite/ext/new_allocator/89510.cc [new file with mode: 0644]