aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/method.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/method.cc')
-rw-r--r--gcc/cp/method.cc64
1 files changed, 61 insertions, 3 deletions
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index 05c19cf..a4089c5 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2251,6 +2251,8 @@ constructible_expr (tree to, tree from)
const int len = TREE_VEC_LENGTH (from);
if (CLASS_TYPE_P (to))
{
+ if (ABSTRACT_CLASS_TYPE_P (to))
+ return error_mark_node;
tree ctype = to;
vec<tree, va_gc> *args = NULL;
if (!TYPE_REF_P (to))
@@ -2330,6 +2332,37 @@ constructible_expr (tree to, tree from)
return expr;
}
+/* Valid if "Either T is a reference type, or T is a complete object type for
+ which the expression declval<U&>().~U() is well-formed when treated as an
+ unevaluated operand ([expr.context]), where U is remove_all_extents_t<T>."
+
+ For a class U, return the destructor call; otherwise return void_node if
+ valid or error_mark_node if not. */
+
+static tree
+destructible_expr (tree to)
+{
+ cp_unevaluated cp_uneval_guard;
+ int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
+ if (TYPE_REF_P (to))
+ return void_node;
+ if (!COMPLETE_TYPE_P (complete_type (to)))
+ return error_mark_node;
+ to = strip_array_types (to);
+ if (CLASS_TYPE_P (to))
+ {
+ to = build_trait_object (to);
+ return build_delete (input_location, TREE_TYPE (to), to,
+ sfk_complete_destructor, flags, 0, tf_none);
+ }
+ /* [expr.prim.id.dtor] If the id-expression names a pseudo-destructor, T
+ shall be a scalar type.... */
+ else if (scalarish_type_p (to))
+ return void_node;
+ else
+ return error_mark_node;
+}
+
/* Returns a tree iff TO is assignable (if CODE is MODIFY_EXPR) or
constructible (otherwise) from FROM, which is a single type for
assignment or a list of types for construction. */
@@ -2339,13 +2372,15 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
{
to = complete_type (to);
deferring_access_check_sentinel acs (dk_no_deferred);
- if (VOID_TYPE_P (to) || ABSTRACT_CLASS_TYPE_P (to)
+ if (VOID_TYPE_P (to)
|| (from && FUNC_OR_METHOD_TYPE_P (from)
&& (TYPE_READONLY (from) || FUNCTION_REF_QUALIFIED (from))))
return error_mark_node;
tree expr;
if (code == MODIFY_EXPR)
expr = assignable_expr (to, from);
+ else if (code == BIT_NOT_EXPR)
+ expr = destructible_expr (to);
else if (trivial && TREE_VEC_LENGTH (from) > 1
&& cxx_dialect < cxx20)
return error_mark_node; // only 0- and 1-argument ctors can be trivial
@@ -2949,7 +2984,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
&& BINFO_VIRTUAL_P (base_binfo)
&& fn && TREE_CODE (fn) == FUNCTION_DECL
&& move_fn_p (fn) && !trivial_fn_p (fn)
- && vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo)))
+ && vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo))
+ && warning_enabled_at (DECL_SOURCE_LOCATION (fn),
+ OPT_Wvirtual_move_assign))
warning (OPT_Wvirtual_move_assign,
"defaulted move assignment for %qT calls a non-trivial "
"move assignment operator for virtual base %qT",
@@ -2987,7 +3024,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
/* Vbase cdtors are not relevant. */;
else
{
- if (constexpr_p)
+ if (constexpr_p && cxx_dialect < cxx26)
*constexpr_p = false;
FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
@@ -3914,5 +3951,26 @@ num_artificial_parms_for (const_tree fn)
return count;
}
+/* Return value of the __builtin_type_order trait. */
+
+tree
+type_order_value (tree type1, tree type2)
+{
+ tree rettype = lookup_comparison_category (cc_strong_ordering);
+ if (rettype == error_mark_node)
+ return rettype;
+ int ret;
+ if (type1 == type2)
+ ret = 0;
+ else
+ {
+ const char *name1 = ASTRDUP (mangle_type_string (type1));
+ const char *name2 = mangle_type_string (type2);
+ ret = strcmp (name1, name2);
+ }
+ return lookup_comparison_result (cc_strong_ordering, rettype,
+ ret == 0 ? 0 : ret > 0 ? 1 : 2);
+}
+
#include "gt-cp-method.h"