c++: fix triviality of class with unsatisfied op=
cxx20_pair is trivially copyable because it has a trivial copy constructor and only a deleted copy assignment operator; the non-triviality of the unsatisfied copy assignment overload is not considered. gcc/cp/ChangeLog: * class.cc (check_methods): Call constraints_satisfied_p. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/cond-triv3.C: New test.
This commit is contained in:
parent
13337ea9a1
commit
04d54b70fe
2 changed files with 55 additions and 2 deletions
|
@ -4795,8 +4795,9 @@ check_methods (tree t)
|
|||
|
||||
/* Check whether the eligible special member functions (P0848) are
|
||||
user-provided. add_method arranged that the CLASSTYPE_MEMBER_VEC only
|
||||
has the eligible ones; TYPE_FIELDS also contains ineligible overloads,
|
||||
which is why this needs to be separate from the loop above. */
|
||||
has the eligible ones, unless none are eligible; TYPE_FIELDS also contains
|
||||
ineligible overloads, which is why this needs to be separate from the loop
|
||||
above. */
|
||||
|
||||
if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
|
||||
{
|
||||
|
@ -4819,6 +4820,10 @@ check_methods (tree t)
|
|||
{
|
||||
if (!user_provided_p (fn))
|
||||
/* Might be trivial. */;
|
||||
else if (TREE_CODE (fn) == TEMPLATE_DECL)
|
||||
/* Templates are never special members. */;
|
||||
else if (!constraints_satisfied_p (fn))
|
||||
/* Not eligible. */;
|
||||
else if (copy_fn_p (fn))
|
||||
TYPE_HAS_COMPLEX_COPY_CTOR (t) = true;
|
||||
else if (move_fn_p (fn))
|
||||
|
@ -4829,6 +4834,10 @@ check_methods (tree t)
|
|||
{
|
||||
if (!user_provided_p (fn))
|
||||
/* Might be trivial. */;
|
||||
else if (TREE_CODE (fn) == TEMPLATE_DECL)
|
||||
/* Templates are never special members. */;
|
||||
else if (!constraints_satisfied_p (fn))
|
||||
/* Not eligible. */;
|
||||
else if (copy_fn_p (fn))
|
||||
TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = true;
|
||||
else if (move_fn_p (fn))
|
||||
|
|
44
gcc/testsuite/g++.dg/cpp2a/cond-triv3.C
Normal file
44
gcc/testsuite/g++.dg/cpp2a/cond-triv3.C
Normal file
|
@ -0,0 +1,44 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template<class T>
|
||||
struct X
|
||||
{
|
||||
T first{};
|
||||
|
||||
X& operator=(const X&) = delete;
|
||||
X& operator=(const X&) requires requires (T& t) { t = t; } { return *this; }
|
||||
};
|
||||
|
||||
// C++20 std::pair<const int, int>:
|
||||
using cxx20_pair = X<const int>;
|
||||
static_assert( __is_trivially_constructible(cxx20_pair, const cxx20_pair&), "" );
|
||||
static_assert( !__is_assignable(cxx20_pair&, const cxx20_pair&), "" );
|
||||
static_assert( __is_trivially_copyable(cxx20_pair), "" );
|
||||
|
||||
template<bool, typename, typename F> struct conditional { using type = F; };
|
||||
template<typename T, typename F> struct conditional<true, T, F> { using type = T; };
|
||||
|
||||
struct base
|
||||
{
|
||||
base() = default;
|
||||
~base() = default;
|
||||
base(const base&) = default;
|
||||
base& operator=(const base&) = delete;
|
||||
};
|
||||
|
||||
struct nope;
|
||||
|
||||
template<class T>
|
||||
struct Y : base
|
||||
{
|
||||
T first{};
|
||||
|
||||
Y& operator=(typename conditional<__is_assignable(T&, const T&), const Y&, const nope&>::type)
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
// C++17 std::pair<const int, int>:
|
||||
using cxx17_pair = Y<const int>;
|
||||
static_assert( __is_trivially_constructible(cxx17_pair, const cxx17_pair&), "" );
|
||||
static_assert( ! __is_assignable(cxx17_pair&, const cxx17_pair&), "" );
|
||||
static_assert( __is_trivially_copyable(cxx17_pair), "???" );
|
Loading…
Add table
Reference in a new issue