+2009-05-27 Jason Merrill <jason@redhat.com>
+
+ * call.c (implicit_conversion): Handle conversion from
+ initializer-list to scalar.
+ (convert_like_real): Likewise. Avoid crashing on list
+ initialization with bad conversions.
+ (can_convert): Use LOOKUP_EXPLICIT.
+ (can_convert_arg_bad): Add flags parm.
+ * cp-tree.h: Adjust.
+ * typeck.c (convert_for_assignment): Pass flags.
+
2009-05-27 Ian Lance Taylor <iant@google.com>
* Make-lang.in (g++$(exeext)): Change $(COMPILER) to $(LINKER).
if (conv)
return conv;
- if (is_std_init_list (to) && expr
- && BRACE_ENCLOSED_INITIALIZER_P (expr))
- return build_list_conv (to, expr, flags);
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ if (is_std_init_list (to))
+ return build_list_conv (to, expr, flags);
+
+ /* Allow conversion from an initializer-list with one element to a
+ scalar type if this is copy-initialization. Direct-initialization
+ would be something like int i({1}), which is invalid. */
+ if (SCALAR_TYPE_P (to) && CONSTRUCTOR_NELTS (expr) <= 1
+ && (flags & LOOKUP_ONLYCONVERTING))
+ {
+ tree elt;
+ if (CONSTRUCTOR_NELTS (expr) == 1)
+ elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ elt = integer_zero_node;
+ conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+ c_cast_p, flags);
+ if (conv)
+ {
+ conv->check_narrowing = true;
+ return conv;
+ }
+ }
+ }
if (expr != NULL_TREE
&& (MAYBE_CLASS_TYPE_P (from)
if (convs->bad_p
&& convs->kind != ck_user
+ && convs->kind != ck_list
&& convs->kind != ck_ambig
&& convs->kind != ck_ref_bind
&& convs->kind != ck_rvalue
return expr;
}
case ck_identity:
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ if (nelts == 0)
+ expr = integer_zero_node;
+ else if (nelts == 1)
+ expr = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ gcc_unreachable ();
+ }
+
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, complain);
/* Convert a constant to its underlying value, unless we are
bool
can_convert (tree to, tree from)
{
- return can_convert_arg (to, from, NULL_TREE, LOOKUP_NORMAL);
+ return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT);
}
/* Returns nonzero if ARG (of type FROM) can be converted to TO. */
/* Like can_convert_arg, but allows dubious conversions as well. */
bool
-can_convert_arg_bad (tree to, tree from, tree arg)
+can_convert_arg_bad (tree to, tree from, tree arg, int flags)
{
conversion *t;
void *p;
p = conversion_obstack_alloc (0);
/* Try to perform the conversion. */
t = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ flags);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree);
extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree, int);
-extern bool can_convert_arg_bad (tree, tree, tree);
+extern bool can_convert_arg_bad (tree, tree, tree, int);
extern bool enforce_access (tree, tree, tree);
extern tree convert_default_arg (tree, tree, tree, int);
extern tree convert_arg_to_ellipsis (tree);
We allow bad conversions here because by the time we get to this point
we are committed to doing the conversion. If we end up doing a bad
conversion, convert_like will complain. */
- if (!can_convert_arg_bad (type, rhstype, rhs))
+ if (!can_convert_arg_bad (type, rhstype, rhs, flags))
{
/* When -Wno-pmf-conversions is use, we just silently allow
conversions from pointers-to-members to plain pointers. If