mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 03:20:27 +08:00
libstdc++: Fix is_trivially_constructible (PR 94033)
This attempts to make is_nothrow_constructible more robust (and efficient to compile) by not depending on is_constructible. Instead the __is_constructible intrinsic is used directly. The helper class __is_nt_constructible_impl which checks whether the construction is non-throwing now takes a bool template parameter that is substituted by the result of the instrinsic. This fixes the reported bug by not using the already-instantiated (and incorrect) value of std::is_constructible. I don't think it really fixes the problem in general, because std::is_nothrow_constructible itself could already have been instantiated in a context where it gives the wrong result. A proper fix needs to be done in the compiler. PR libstdc++/94033 * include/std/type_traits (__is_nt_default_constructible_atom): Remove. (__is_nt_default_constructible_impl): Remove. (__is_nothrow_default_constructible_impl): Remove. (__is_nt_constructible_impl): Add bool template parameter. Adjust partial specializations. (__is_nothrow_constructible_impl): Replace class template with alias template. (is_nothrow_default_constructible): Derive from alias template __is_nothrow_constructible_impl instead of __is_nothrow_default_constructible_impl. * testsuite/20_util/is_nothrow_constructible/94003.cc: New test.
This commit is contained in:
parent
07fe4af4d5
commit
b334182653
libstdc++-v3
@ -1,5 +1,18 @@
|
||||
2020-03-18 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/94033
|
||||
* include/std/type_traits (__is_nt_default_constructible_atom): Remove.
|
||||
(__is_nt_default_constructible_impl): Remove.
|
||||
(__is_nothrow_default_constructible_impl): Remove.
|
||||
(__is_nt_constructible_impl): Add bool template parameter. Adjust
|
||||
partial specializations.
|
||||
(__is_nothrow_constructible_impl): Replace class template with alias
|
||||
template.
|
||||
(is_nothrow_default_constructible): Derive from alias template
|
||||
__is_nothrow_constructible_impl instead of
|
||||
__is_nothrow_default_constructible_impl.
|
||||
* testsuite/20_util/is_nothrow_constructible/94003.cc: New test.
|
||||
|
||||
* include/std/stop_token (stop_token::_Stop_state_ref): Define
|
||||
comparison operators explicitly if the compiler won't synthesize them.
|
||||
|
||||
|
@ -961,61 +961,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_default_constructible_atom
|
||||
: public integral_constant<bool, noexcept(_Tp())>
|
||||
template<bool, typename _Tp, typename... _Args>
|
||||
struct __is_nt_constructible_impl
|
||||
: public false_type
|
||||
{ };
|
||||
|
||||
template<typename _Tp, bool = is_array<_Tp>::value>
|
||||
struct __is_nt_default_constructible_impl;
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_default_constructible_impl<_Tp, true>
|
||||
: public __and_<__is_array_known_bounds<_Tp>,
|
||||
__is_nt_default_constructible_atom<typename
|
||||
remove_all_extents<_Tp>::type>>
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_default_constructible_impl<_Tp, false>
|
||||
: public __is_nt_default_constructible_atom<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
using __is_nothrow_default_constructible_impl
|
||||
= __and_<__is_constructible_impl<_Tp>,
|
||||
__is_nt_default_constructible_impl<_Tp>>;
|
||||
|
||||
/// is_nothrow_default_constructible
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_default_constructible
|
||||
: public __is_nothrow_default_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __is_nt_constructible_impl
|
||||
: public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))>
|
||||
struct __is_nt_constructible_impl<true, _Tp, _Args...>
|
||||
: public __bool_constant<noexcept(_Tp(std::declval<_Args>()...))>
|
||||
{ };
|
||||
|
||||
template<typename _Tp, typename _Arg>
|
||||
struct __is_nt_constructible_impl<_Tp, _Arg>
|
||||
: public integral_constant<bool,
|
||||
noexcept(static_cast<_Tp>(declval<_Arg>()))>
|
||||
struct __is_nt_constructible_impl<true, _Tp, _Arg>
|
||||
: public __bool_constant<noexcept(static_cast<_Tp>(std::declval<_Arg>()))>
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_constructible_impl<_Tp>
|
||||
: public __is_nothrow_default_constructible_impl<_Tp>
|
||||
struct __is_nt_constructible_impl<true, _Tp>
|
||||
: public __bool_constant<noexcept(_Tp())>
|
||||
{ };
|
||||
|
||||
template<typename _Tp, size_t _Num>
|
||||
struct __is_nt_constructible_impl<true, _Tp[_Num]>
|
||||
: public __bool_constant<noexcept(typename remove_all_extents<_Tp>::type())>
|
||||
{ };
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __is_nothrow_constructible_impl
|
||||
: public __and_<__is_constructible_impl<_Tp, _Args...>,
|
||||
__is_nt_constructible_impl<_Tp, _Args...>>
|
||||
{ };
|
||||
using __is_nothrow_constructible_impl
|
||||
= __is_nt_constructible_impl<__is_constructible(_Tp, _Args...),
|
||||
_Tp, _Args...>;
|
||||
|
||||
/// is_nothrow_constructible
|
||||
template<typename _Tp, typename... _Args>
|
||||
@ -1026,6 +1000,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_nothrow_default_constructible
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_default_constructible
|
||||
: public __is_nothrow_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_nothrow_copy_constructible_impl;
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
template <bool B> struct abc {};
|
||||
|
||||
template <typename T>
|
||||
|
||||
struct future : public abc<std::is_trivially_constructible_v<std::tuple<T>>> {};
|
||||
|
||||
class mutation {
|
||||
mutation();
|
||||
friend class std::optional<mutation>;
|
||||
};
|
||||
|
||||
using mutation_opt = std::optional<mutation>;
|
||||
|
||||
future<mutation_opt> foo();
|
||||
|
||||
template <typename Consumer> future<mutation_opt> consume_partitions() {
|
||||
return foo();
|
||||
}
|
||||
|
||||
future<mutation_opt> bar() { return consume_partitions<int>(); }
|
||||
|
||||
future<mutation> zed();
|
||||
future<mutation> apply_counter_update() { return zed(); }
|
Loading…
x
Reference in New Issue
Block a user