Commit 8e956c22 by Nathan Sidwell Committed by Nathan Sidwell

method.c (synthesized_method_base_walk): New.

	* method.c (synthesized_method_base_walk): New.  Broken out of ...
	(synthesized_method_walk): ... here.  Call it.  Cleanup
	initializations.

From-SVN: r245250
parent e5f234b2
2017-02-07 Nathan Sidwell <nathan@acm.org>
* method.c (synthesized_method_base_walk): New. Broken out of ...
(synthesized_method_walk): ... here. Call it. Cleanup
initializations.
2017-02-07 Patrick Palka <ppalka@gcc.gnu.org> 2017-02-07 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/79360 PR c++/79360
......
...@@ -1416,6 +1416,61 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, ...@@ -1416,6 +1416,61 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
} }
} }
// Base walker helper for synthesized_method_walk. Inspect a direct
// or virtual base. BINFO is the parent type's binfo. BASE_BINFO is
// the base binfo of interests. All other parms are as for
// 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,
tree inheriting_ctor, tree inherited_parms,
tree fnname, int flags, bool diag,
tree *spec_p, bool *trivial_p,
bool *deleted_p, bool *constexpr_p)
{
bool inherited_binfo = false;
tree argtype = NULL_TREE;
if (copy_arg_p)
argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p);
else if ((inherited_binfo
= binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
{
argtype = inherited_parms;
/* Don't check access on the inherited constructor. */
if (flag_new_inheriting_ctors)
push_deferring_access_checks (dk_deferred);
}
tree rval = locate_fn_flags (base_binfo, fnname, argtype, flags,
diag ? tf_warning_or_error : tf_none);
if (inherited_binfo && flag_new_inheriting_ctors)
pop_deferring_access_checks ();
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, BINFO_TYPE (base_binfo));
if (ctor_p &&
(!BINFO_VIRTUAL_P (base_binfo)
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))))
{
/* In a constructor we also need to check the subobject
destructors for cleanup of partially constructed objects. */
tree dtor = locate_fn_flags (base_binfo, complete_dtor_identifier,
NULL_TREE, flags,
diag ? tf_warning_or_error : tf_none);
/* Note that we don't pass down trivial_p; the subobject
destructors don't affect triviality of the constructor. Nor
do they affect constexpr-ness (a constant expression doesn't
throw) or exception-specification (a throw from one of the
dtors would be a double-fault). */
process_subob_fn (dtor, NULL, NULL, deleted_p, NULL, false,
BINFO_TYPE (base_binfo), /*dtor_from_ctor*/true);
}
return rval;
}
/* The caller wants to generate an implicit declaration of SFK for /* The caller wants to generate an implicit declaration of SFK for
CTYPE which is const if relevant and CONST_P is set. If SPEC_P, CTYPE which is const if relevant and CONST_P is set. If SPEC_P,
TRIVIAL_P, DELETED_P or CONSTEXPR_P are non-null, set their TRIVIAL_P, DELETED_P or CONSTEXPR_P are non-null, set their
...@@ -1429,12 +1484,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1429,12 +1484,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
bool *constexpr_p, bool diag, bool *constexpr_p, bool diag,
tree inheriting_ctor, tree inherited_parms) tree inheriting_ctor, tree inherited_parms)
{ {
tree binfo, base_binfo, scope, fnname, rval, argtype; tree binfo, base_binfo, fnname;
bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor; int i;
vec<tree, va_gc> *vbases;
int i, quals, flags;
tsubst_flags_t complain;
bool ctor_p;
if (spec_p) if (spec_p)
*spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec); *spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec);
...@@ -1455,9 +1506,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1455,9 +1506,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
*deleted_p = false; *deleted_p = false;
} }
ctor_p = false; bool ctor_p = false;
assign_p = false; bool assign_p = false;
check_vdtor = false; bool check_vdtor = false;
switch (sfk) switch (sfk)
{ {
case sfk_move_assignment: case sfk_move_assignment:
...@@ -1497,19 +1548,18 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1497,19 +1548,18 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
- the assignment operator selected to copy/move each direct base class - the assignment operator selected to copy/move each direct base class
subobject is a constexpr function, and subobject is a constexpr function, and
- for each non-static data member of X that is of class type (or array - for each non-static data member of X that is of class type (or array
thereof), the assignment operator selected to copy/move that member is a thereof), the assignment operator selected to copy/move that
constexpr function. */ member is a constexpr function. */
if (constexpr_p) if (constexpr_p)
*constexpr_p = ctor_p *constexpr_p = ctor_p || (assign_p && cxx_dialect >= cxx14);
|| (assign_p && cxx_dialect >= cxx14);
move_p = false; bool move_p = false;
bool copy_arg_p = false;
switch (sfk) switch (sfk)
{ {
case sfk_constructor: case sfk_constructor:
case sfk_destructor: case sfk_destructor:
case sfk_inheriting_constructor: case sfk_inheriting_constructor:
copy_arg_p = false;
break; break;
case sfk_move_constructor: case sfk_move_constructor:
...@@ -1525,7 +1575,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1525,7 +1575,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
gcc_unreachable (); gcc_unreachable ();
} }
expected_trivial = type_has_trivial_fn (ctype, sfk); bool expected_trivial = type_has_trivial_fn (ctype, sfk);
if (trivial_p) if (trivial_p)
*trivial_p = expected_trivial; *trivial_p = expected_trivial;
...@@ -1559,92 +1609,55 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1559,92 +1609,55 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
++c_inhibit_evaluation_warnings; ++c_inhibit_evaluation_warnings;
push_deferring_access_checks (dk_no_deferred); push_deferring_access_checks (dk_no_deferred);
scope = push_scope (ctype); tree scope = push_scope (ctype);
flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE; int flags = LOOKUP_NORMAL | LOOKUP_SPECULATIVE;
if (!inheriting_ctor) if (!inheriting_ctor)
flags |= LOOKUP_DEFAULTED; flags |= LOOKUP_DEFAULTED;
complain = diag ? tf_warning_or_error : tf_none; tsubst_flags_t complain = diag ? tf_warning_or_error : tf_none;
int quals = const_p ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED;
if (const_p)
quals = TYPE_QUAL_CONST;
else
quals = TYPE_UNQUALIFIED;
argtype = NULL_TREE;
for (binfo = TYPE_BINFO (ctype), i = 0; for (binfo = TYPE_BINFO (ctype), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{ {
tree basetype = BINFO_TYPE (base_binfo);
if (!assign_p && BINFO_VIRTUAL_P (base_binfo)) if (!assign_p && BINFO_VIRTUAL_P (base_binfo))
/* We'll handle virtual bases below. */ /* We'll handle virtual bases below. */
continue; continue;
bool inherited_binfo = false; tree fn = synthesized_method_base_walk (binfo, base_binfo, quals,
copy_arg_p, move_p, ctor_p,
if (copy_arg_p) inheriting_ctor,
argtype = build_stub_type (basetype, quals, move_p); inherited_parms,
else if ((inherited_binfo fnname, flags, diag,
= binfo_inherited_from (binfo, base_binfo, inheriting_ctor))) spec_p, trivial_p,
{ deleted_p, constexpr_p);
/* Don't check access on the inherited constructor. */
argtype = inherited_parms;
if (flag_new_inheriting_ctors)
push_deferring_access_checks (dk_deferred);
}
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
if (inherited_binfo)
{
if (flag_new_inheriting_ctors)
pop_deferring_access_checks ();
argtype = NULL_TREE;
}
process_subob_fn (rval, spec_p, trivial_p, deleted_p, if (diag && assign_p && move_p
constexpr_p, diag, basetype); && BINFO_VIRTUAL_P (base_binfo)
if (ctor_p) && fn && TREE_CODE (fn) == FUNCTION_DECL
{ && move_fn_p (fn) && !trivial_fn_p (fn)
/* In a constructor we also need to check the subobject && vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo)))
destructors for cleanup of partially constructed objects. */ warning (OPT_Wvirtual_move_assign,
rval = locate_fn_flags (base_binfo, complete_dtor_identifier, "defaulted move assignment for %qT calls a non-trivial "
NULL_TREE, flags, complain); "move assignment operator for virtual base %qT",
/* Note that we don't pass down trivial_p; the subobject ctype, BINFO_TYPE (base_binfo));
destructors don't affect triviality of the constructor. Nor
do they affect constexpr-ness (a constant expression doesn't
throw) or exception-specification (a throw from one of the
dtors would be a double-fault). */
process_subob_fn (rval, NULL, NULL,
deleted_p, NULL, false,
basetype, /*dtor_from_ctor*/true);
}
if (check_vdtor && type_has_virtual_destructor (basetype)) if (check_vdtor && type_has_virtual_destructor (BINFO_TYPE (base_binfo)))
{ {
rval = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR), fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
ptr_type_node, flags, complain); ptr_type_node, flags, complain);
/* Unlike for base ctor/op=/dtor, for operator delete it's fine /* Unlike for base ctor/op=/dtor, for operator delete it's fine
to have a null rval (no class-specific op delete). */ to have a null fn (no class-specific op delete). */
if (rval && rval == error_mark_node && deleted_p) if (fn && fn == error_mark_node && deleted_p)
*deleted_p = true; *deleted_p = true;
check_vdtor = false; check_vdtor = false;
} }
if (diag && assign_p && move_p
&& BINFO_VIRTUAL_P (base_binfo)
&& rval && TREE_CODE (rval) == FUNCTION_DECL
&& move_fn_p (rval) && !trivial_fn_p (rval)
&& vbase_has_user_provided_move_assign (basetype))
warning (OPT_Wvirtual_move_assign,
"defaulted move assignment for %qT calls a non-trivial "
"move assignment operator for virtual base %qT",
ctype, basetype);
} }
vbases = CLASSTYPE_VBASECLASSES (ctype); vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (ctype);
if (assign_p) if (assign_p)
/* No need to examine vbases here. */; /* Already examined vbases above. */;
else if (vec_safe_is_empty (vbases)) else if (vec_safe_is_empty (vbases))
/* No virtual bases to worry about. */; /* No virtual bases to worry about. */;
else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14) else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14)
...@@ -1654,38 +1667,12 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1654,38 +1667,12 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
if (constexpr_p) if (constexpr_p)
*constexpr_p = false; *constexpr_p = false;
FOR_EACH_VEC_ELT (*vbases, i, base_binfo) FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
{ synthesized_method_base_walk (binfo, base_binfo, quals,
tree basetype = BINFO_TYPE (base_binfo); copy_arg_p, move_p, ctor_p,
bool inherited_binfo = false; inheriting_ctor, inherited_parms,
fnname, flags, diag,
if (copy_arg_p) spec_p, trivial_p,
argtype = build_stub_type (basetype, quals, move_p); deleted_p, constexpr_p);
else if ((inherited_binfo
= binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
{
argtype = inherited_parms;
if (flag_new_inheriting_ctors)
push_deferring_access_checks (dk_deferred);
}
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
if (inherited_binfo)
{
if (flag_new_inheriting_ctors)
pop_deferring_access_checks ();
argtype = NULL_TREE;
}
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, basetype);
if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype))
{
rval = locate_fn_flags (base_binfo, complete_dtor_identifier,
NULL_TREE, flags, complain);
process_subob_fn (rval, NULL, NULL,
deleted_p, NULL, false,
basetype, /*dtor_from_ctor*/true);
}
}
} }
/* Now handle the non-static data members. */ /* Now handle the non-static data members. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment