}
}
+/* Categorize various special_function_kinds. */
+#define SFK_CTOR_P(sfk) \
+ ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor)
+#define SFK_DTOR_P(sfk) \
+ ((sfk) == sfk_destructor)
+#define SFK_ASSIGN_P(sfk) \
+ ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment)
+#define SFK_COPY_P(sfk) \
+ ((sfk) == sfk_copy_constructor || (sfk) == sfk_copy_assignment)
+#define SFK_MOVE_P(sfk) \
+ ((sfk) == sfk_move_constructor || (sfk) == sfk_move_assignment)
+
/* Subroutine of synthesized_method_walk to allow recursion into anonymous
aggregates. If DTOR_FROM_CTOR is true, we're walking subobject destructors
called from a synthesized constructor, in which case we don't consider
the triviality of the subobject destructor. */
static void
-walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
- int quals, bool copy_arg_p, bool move_p,
- bool assign_p, tree *spec_p, bool *trivial_p,
+walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
+ int quals, tree *spec_p, bool *trivial_p,
bool *deleted_p, bool *constexpr_p,
bool diag, int flags, tsubst_flags_t complain,
bool dtor_from_ctor)
break;
mem_type = strip_array_types (TREE_TYPE (field));
- if (assign_p)
+ if (SFK_ASSIGN_P (sfk))
{
bool bad = true;
if (CP_TYPE_CONST_P (mem_type) && !CLASS_TYPE_P (mem_type))
if (ANON_AGGR_TYPE_P (mem_type))
{
- walk_field_subobs (TYPE_FIELDS (mem_type), fnname, sfk, quals,
- copy_arg_p, move_p, assign_p, spec_p, trivial_p,
- deleted_p, constexpr_p,
+ walk_field_subobs (TYPE_FIELDS (mem_type), sfk, fnname, quals,
+ spec_p, trivial_p, deleted_p, constexpr_p,
diag, flags, complain, dtor_from_ctor);
continue;
}
- if (copy_arg_p)
+ if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk))
{
int mem_quals = cp_type_quals (mem_type) | quals;
if (DECL_MUTABLE_P (field))
mem_quals &= ~TYPE_QUAL_CONST;
- argtype = build_stub_type (mem_type, mem_quals, move_p);
+ argtype = build_stub_type (mem_type, mem_quals, SFK_MOVE_P (sfk));
}
else
argtype = NULL_TREE;
synthesized_method_walk, or its local vars. */
static tree
-synthesized_method_base_walk (tree binfo, tree base_binfo,
- int quals, bool copy_arg_p,
- bool move_p, bool ctor_p,
+synthesized_method_base_walk (tree binfo, tree base_binfo,
+ special_function_kind sfk, tree fnname, int quals,
tree *inheriting_ctor, tree inherited_parms,
- tree fnname, int flags, bool diag,
+ int flags, bool diag,
tree *spec_p, bool *trivial_p,
bool *deleted_p, bool *constexpr_p)
{
tree argtype = NULL_TREE;
deferring_kind defer = dk_no_deferred;
- if (copy_arg_p)
- argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p);
+ if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk))
+ argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, SFK_MOVE_P (sfk));
else if (inheriting_ctor
&& (inherited_binfo
= binfo_inherited_from (binfo, base_binfo, *inheriting_ctor)))
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, BINFO_TYPE (base_binfo));
- if (ctor_p &&
+ if (SFK_CTOR_P (sfk) &&
(!BINFO_VIRTUAL_P (base_binfo)
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))))
{
bool *constexpr_p, bool diag,
tree *inheriting_ctor, tree inherited_parms)
{
- tree binfo, base_binfo, fnname;
+ tree binfo, base_binfo;
int i;
+ /* SFK must be exactly one category. */
+ gcc_checking_assert (SFK_DTOR_P(sfk) + SFK_CTOR_P(sfk)
+ + SFK_ASSIGN_P(sfk) == 1);
+
if (spec_p)
*spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec);
*deleted_p = false;
}
- bool ctor_p = false;
- bool assign_p = false;
bool check_vdtor = false;
- switch (sfk)
- {
- case sfk_move_assignment:
- case sfk_copy_assignment:
- assign_p = true;
- fnname = assign_op_identifier;
- break;
+ tree fnname;
- case sfk_destructor:
+if (SFK_DTOR_P (sfk))
+ {
check_vdtor = true;
/* The synthesized method will call base dtors, but check complete
here to avoid having to deal with VTT. */
fnname = complete_dtor_identifier;
- break;
-
- case sfk_constructor:
- case sfk_move_constructor:
- case sfk_copy_constructor:
- case sfk_inheriting_constructor:
- ctor_p = true;
- fnname = complete_ctor_identifier;
- break;
-
- default:
- gcc_unreachable ();
}
+ else if (SFK_ASSIGN_P (sfk))
+ fnname = assign_op_identifier;
+ else
+ fnname = complete_ctor_identifier;
gcc_assert ((sfk == sfk_inheriting_constructor)
== (inheriting_ctor && *inheriting_ctor != NULL_TREE));
thereof), the assignment operator selected to copy/move that
member is a constexpr function. */
if (constexpr_p)
- *constexpr_p = ctor_p || (assign_p && cxx_dialect >= cxx14);
-
- bool move_p = false;
- bool copy_arg_p = false;
- switch (sfk)
- {
- case sfk_constructor:
- case sfk_destructor:
- case sfk_inheriting_constructor:
- break;
-
- case sfk_move_constructor:
- case sfk_move_assignment:
- move_p = true;
- /* FALLTHRU */
- case sfk_copy_constructor:
- case sfk_copy_assignment:
- copy_arg_p = true;
- break;
-
- default:
- gcc_unreachable ();
- }
+ *constexpr_p = (SFK_CTOR_P (sfk)
+ || (SFK_ASSIGN_P (sfk) && cxx_dialect >= cxx14));
bool expected_trivial = type_has_trivial_fn (ctype, sfk);
if (trivial_p)
resolution, so a constructor can be trivial even if it would otherwise
call a non-trivial constructor. */
if (expected_trivial
- && (!copy_arg_p || cxx_dialect < cxx11))
+ && (!(SFK_COPY_P (sfk) || SFK_MOVE_P (sfk)) || cxx_dialect < cxx11))
{
if (constexpr_p && sfk == sfk_constructor)
{
for (binfo = TYPE_BINFO (ctype), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
- if (!assign_p && BINFO_VIRTUAL_P (base_binfo))
+ if (!SFK_ASSIGN_P (sfk) && BINFO_VIRTUAL_P (base_binfo))
/* We'll handle virtual bases below. */
continue;
- tree fn = synthesized_method_base_walk (binfo, base_binfo, quals,
- copy_arg_p, move_p, ctor_p,
- inheriting_ctor,
- inherited_parms,
- fnname, flags, diag,
- spec_p, trivial_p,
+ tree fn = synthesized_method_base_walk (binfo, base_binfo,
+ sfk, fnname, quals,
+ inheriting_ctor, inherited_parms,
+ flags, diag, spec_p, trivial_p,
deleted_p, constexpr_p);
- if (diag && assign_p && move_p
+ if (diag && SFK_ASSIGN_P (sfk) && SFK_MOVE_P (sfk)
&& BINFO_VIRTUAL_P (base_binfo)
&& fn && TREE_CODE (fn) == FUNCTION_DECL
&& move_fn_p (fn) && !trivial_fn_p (fn)
}
vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (ctype);
- if (assign_p)
+ if (SFK_ASSIGN_P (sfk))
/* Already examined vbases above. */;
else if (vec_safe_is_empty (vbases))
/* No virtual bases to worry about. */;
*constexpr_p = false;
FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
- synthesized_method_base_walk (binfo, base_binfo, quals,
- copy_arg_p, move_p, ctor_p,
+ synthesized_method_base_walk (binfo, base_binfo, sfk, fnname, quals,
inheriting_ctor, inherited_parms,
- fnname, flags, diag,
- spec_p, trivial_p,
- deleted_p, constexpr_p);
+ flags, diag,
+ spec_p, trivial_p, deleted_p, constexpr_p);
}
/* Now handle the non-static data members. */
- walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals,
- copy_arg_p, move_p, assign_p, spec_p, trivial_p,
- deleted_p, constexpr_p,
+ walk_field_subobs (TYPE_FIELDS (ctype), sfk, fnname, quals,
+ spec_p, trivial_p, deleted_p, constexpr_p,
diag, flags, complain, /*dtor_from_ctor*/false);
- if (ctor_p)
- walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier,
- sfk_destructor, TYPE_UNQUALIFIED, false,
- false, false, NULL, NULL,
- deleted_p, NULL,
+ if (SFK_CTOR_P (sfk))
+ walk_field_subobs (TYPE_FIELDS (ctype), sfk_destructor,
+ complete_dtor_identifier, TYPE_UNQUALIFIED,
+ NULL, NULL, deleted_p, NULL,
false, flags, complain, /*dtor_from_ctor*/true);
pop_scope (scope);