@@ -6267,7 +6267,7 @@ extern void finish_struct_1 (tree);
extern int resolves_to_fixed_type_p (tree, int *);
extern void init_class_processing (void);
extern int is_empty_class (tree);
-extern bool is_really_empty_class (tree);
+extern bool is_really_empty_class (tree, bool);
extern void pushclass (tree);
extern void popclass (void);
extern void push_nested_class (tree);
@@ -8566,7 +8566,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
tree arg = argarray[1];
location_t loc = cp_expr_loc_or_loc (arg, input_location);
- if (is_really_empty_class (type))
+ if (is_really_empty_class (type, /*ignore_vptr*/true))
{
/* Avoid copying empty classes. */
val = build2 (COMPOUND_EXPR, type, arg, to);
@@ -5137,7 +5137,8 @@ trivial_default_constructor_is_constexpr (tree t)
/* A defaulted trivial default constructor is constexpr
if there is nothing to initialize. */
gcc_assert (!TYPE_HAS_COMPLEX_DFLT (t));
- return is_really_empty_class (t);
+ /* A class with a vptr doesn't have a trivial default ctor. */
+ return is_really_empty_class (t, /*ignore_vptr*/true);
}
/* Returns true iff class T has a constexpr default constructor. */
@@ -8310,10 +8311,12 @@ is_empty_class (tree type)
}
/* Returns true if TYPE contains no actual data, just various
- possible combinations of empty classes and possibly a vptr. */
+ possible combinations of empty classes. If IGNORE_VPTR is true,
+ a vptr doesn't prevent the class from being considered empty. Typically
+ we want to ignore the vptr on assignment, and not on initialization. */
bool
-is_really_empty_class (tree type)
+is_really_empty_class (tree type, bool ignore_vptr)
{
if (CLASS_TYPE_P (type))
{
@@ -8327,22 +8330,25 @@ is_really_empty_class (tree type)
if (COMPLETE_TYPE_P (type) && is_empty_class (type))
return true;
+ if (!ignore_vptr && TYPE_CONTAINS_VPTR_P (type))
+ return false;
+
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
- if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
+ if (!is_really_empty_class (BINFO_TYPE (base_binfo), ignore_vptr))
return false;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
&& !DECL_ARTIFICIAL (field)
/* An unnamed bit-field is not a data member. */
&& !DECL_UNNAMED_BIT_FIELD (field)
- && !is_really_empty_class (TREE_TYPE (field)))
+ && !is_really_empty_class (TREE_TYPE (field), ignore_vptr))
return false;
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
return (integer_zerop (array_type_nelts_top (type))
- || is_really_empty_class (TREE_TYPE (type)));
+ || is_really_empty_class (TREE_TYPE (type), ignore_vptr));
return false;
}
@@ -2714,7 +2714,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
/* We only create a CONSTRUCTOR for a subobject when we modify it, so empty
classes never get represented; throw together a value now. */
- if (is_really_empty_class (TREE_TYPE (t)))
+ if (is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
return build_constructor (TREE_TYPE (t), NULL);
gcc_assert (DECL_CONTEXT (part) == TYPE_MAIN_VARIANT (TREE_TYPE (whole)));
@@ -4427,12 +4427,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
CONST_DECL for aggregate constants. */
if (lval)
return t;
- /* is_really_empty_class doesn't take into account _vptr, so initializing
- otherwise empty class with { } would overwrite the initializer that
- initialize_vtable created for us. */
if (COMPLETE_TYPE_P (TREE_TYPE (t))
- && !TYPE_POLYMORPHIC_P (TREE_TYPE (t))
- && is_really_empty_class (TREE_TYPE (t)))
+ && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
/* If the class is empty, we aren't actually loading anything. */
r = build_constructor (TREE_TYPE (t), NULL);
@@ -4480,7 +4476,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
else if (TYPE_REF_P (TREE_TYPE (t)))
/* Defer, there's no lvalue->rvalue conversion. */;
else if (COMPLETE_TYPE_P (TREE_TYPE (t))
- && is_really_empty_class (TREE_TYPE (t)))
+ && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
/* If the class is empty, we aren't actually loading anything. */
r = build_constructor (TREE_TYPE (t), NULL);
@@ -5956,7 +5952,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
|| (DECL_INITIAL (t)
&& !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)))
&& COMPLETE_TYPE_P (TREE_TYPE (t))
- && !is_really_empty_class (TREE_TYPE (t)))
+ && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
if (flags & tf_error)
non_const_var_error (t);
@@ -584,7 +584,7 @@ simple_empty_class_p (tree type, tree op)
&& !TREE_CLOBBER_P (op))
|| (TREE_CODE (op) == CALL_EXPR
&& !CALL_EXPR_RETURN_SLOT_OPT (op)))
- && is_really_empty_class (type);
+ && is_really_empty_class (type, /*ignore_vptr*/true);
}
/* Returns true if evaluating E as an lvalue has side-effects;
@@ -2058,7 +2058,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
/* If the type has data but no user-provided ctor, we need to zero
out the object. */
if (!type_has_user_provided_constructor (type)
- && !is_really_empty_class (type))
+ && !is_really_empty_class (type, /*ignore_vptr*/true))
{
tree field_size = NULL_TREE;
if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type)
@@ -1,3 +1,15 @@
+2019-03-05 Jason Merrill <jason@redhat.com>
+
+ * class.c (is_really_empty_class): Add ignore_vptr parm.
+ (trivial_default_constructor_is_constexpr): Pass it.
+ * call.c (build_over_call): Pass it.
+ * constexpr.c (cxx_eval_constant_expression): Pass it instead of
+ checking TYPE_POLYMORPHIC_P.
+ (cxx_eval_component_reference, potential_constant_expression_1):
+ Pass it.
+ * cp-gimplify.c (simple_empty_class_p): Pass it.
+ * init.c (expand_aggr_init_1): Pass it.
+
2019-03-04 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/84605