+1999-07-28 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (conditional_conversion): Don't build BASE_CONVs for
+ conversions between things that have the same type.
+ (build_conditional_expr): Tweak.
+ (convert_like): Some BASE_CONVs really do require the generation
+ of code.
+
+ * init.c (perform_member_init): Don't go through build_modify_expr
+ for simple initializations.
+
1999-07-27 Jason Merrill <jason@yorick.cygnus.com>
* cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
if (at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
- conv = build_conv (BASE_CONV, t2, conv);
+ if (!same_type_p (TYPE_MAIN_VARIANT (t1),
+ TYPE_MAIN_VARIANT (t2)))
+ conv = build_conv (BASE_CONV, t2, conv);
return conv;
}
else
else if (conv2 && !ICS_BAD_FLAG (conv2))
{
arg2 = convert_like (conv2, arg2);
+ /* That may not quite have done the trick. If the two types
+ are cv-qualified variants of one another, we will have
+ just used an IDENTITY_CONV. (There's no conversion from
+ an lvalue of one class type to an lvalue of another type,
+ even a cv-qualified variant, and we don't want to lose
+ lvalue-ness here.) So, we manually add a NOP_EXPR here
+ if necessary. */
+ if (!same_type_p (TREE_TYPE (arg2), arg3_type))
+ arg2 = build1 (NOP_EXPR, arg3_type, arg2);
arg2_type = TREE_TYPE (arg2);
}
else if (conv3 && !ICS_BAD_FLAG (conv3))
{
arg3 = convert_like (conv3, arg3);
+ if (!same_type_p (TREE_TYPE (arg3), arg2_type))
+ arg2 = build1 (NOP_EXPR, arg2_type, arg3);
arg3_type = TREE_TYPE (arg3);
}
}
return expr;
/* else fall through */
case BASE_CONV:
- if (TREE_CODE (convs) == BASE_CONV
- && !NEED_TEMPORARY_P (convs))
- /* We are going to bind a reference directly to a base-class
- subobject of EXPR. We don't have to generate any code
- here. */
- return expr;
+ if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))
+ {
+ /* We are going to bind a reference directly to a base-class
+ subobject of EXPR. */
+ tree base_ptr = build_pointer_type (TREE_TYPE (convs));
+
+ /* Build an expression for `*((base*) &expr)'. */
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = perform_implicit_conversion (base_ptr, expr);
+ expr = build_indirect_ref (expr, "implicit conversion");
+ return expr;
+ }
+
{
tree cvt_expr = build_user_type_conversion
(TREE_TYPE (convs), expr, LOOKUP_NORMAL);
{
/* default-initialization. */
if (AGGREGATE_TYPE_P (type))
- init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
- else if (TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error ("default-initialization of `%#D', which has reference type",
- member);
- init = error_mark_node;
+ /* This is a default initialization of an aggregate,
+ but not one of non-POD class type. We cleverly
+ notice that the initialization rules in such a
+ case are the same as for initialization with an
+ empty brace-initialization list. We don't want
+ to call build_modify_expr as that will go looking
+ for constructors and such. */
+ tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (e) = 1;
+ expand_expr_stmt (build (INIT_EXPR, type, decl, e));
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ cp_error ("default-initialization of `%#D', which has reference type",
+ member);
else
init = integer_zero_node;
}
init = TREE_VALUE (init);
}
- /* We only build this with a null init if we got it from the
- current_member_init_list. */
- if (init || explicit)
- {
- expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
- }
+ if (init)
+ expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
expand_end_target_temps ();