static tree convert_like_real (conversion *, tree, tree, int, int, bool,
bool, tsubst_flags_t);
static void op_error (enum tree_code, enum tree_code, tree, tree,
- tree, const char *);
+ tree, bool);
static VEC(tree,gc) *resolve_args (VEC(tree,gc) *);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
static void print_z_candidate (const char *, struct z_candidate *);
{
unsigned HOST_WIDE_INT i = 0;
conversion *c;
- tree field = TYPE_FIELDS (type);
+ tree field = next_initializable_field (TYPE_FIELDS (type));
- for (; field; field = TREE_CHAIN (field), ++i)
+ for (; field; field = next_initializable_field (TREE_CHAIN (field)))
{
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
if (i < CONSTRUCTOR_NELTS (ctor))
{
constructor_elt *ce = CONSTRUCTOR_ELT (ctor, i);
if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (ce->value),
ce->value, flags))
return NULL;
+ ++i;
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
}
else if (build_value_init (TREE_TYPE (field)) == error_mark_node)
return NULL;
}
+ if (i < CONSTRUCTOR_NELTS (ctor))
+ return NULL;
+
c = alloc_conversion (ck_aggr);
c->type = type;
c->rank = cr_exact;
struct z_candidate *cand;
bool any_viable_p;
- conversions = lookup_conversions (s);
+ conversions = lookup_conversions (s, /*lookup_template_convs_p=*/true);
if (!conversions)
return NULL;
return build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (type) == FUNCTION_TYPE)
return build_pointer_type (type);
+ if (!MAYBE_CLASS_TYPE_P (type))
+ type = cv_unqualified (type);
return type;
}
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return;
- convs = lookup_conversions (argtypes[i]);
+ convs = lookup_conversions (argtypes[i],
+ /*lookup_template_convs_p=*/false);
if (code == COND_EXPR)
{
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
- unsigned int nargs;
- int skip_without_in_chrg;
- tree first_arg_without_in_chrg;
+ unsigned int len = VEC_length (tree, arglist);
+ unsigned int nargs = (first_arg == NULL_TREE ? 0 : 1) + len;
+ unsigned int skip_without_in_chrg = 0;
+ tree first_arg_without_in_chrg = first_arg;
tree *args_without_in_chrg;
unsigned int nargs_without_in_chrg;
unsigned int ia, ix;
int i;
tree fn;
- nargs = (first_arg == NULL_TREE ? 0 : 1) + VEC_length (tree, arglist);
-
- skip_without_in_chrg = 0;
-
- first_arg_without_in_chrg = first_arg;
-
/* We don't do deduction on the in-charge parameter, the VTT
parameter or 'this'. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
++skip_without_in_chrg;
}
+ if (len < skip_without_in_chrg)
+ return NULL;
+
nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
- + (VEC_length (tree, arglist)
- - skip_without_in_chrg));
+ + (len - skip_without_in_chrg));
args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
ia = 0;
if (first_arg_without_in_chrg != NULL_TREE)
for this will point at template <class T> template <> S<T>::f(int),
so that we can find the definition. For the purposes of
overload resolution, however, we want the original TMPL. */
- cand->template_decl = tree_cons (tmpl, targs, NULL_TREE);
+ cand->template_decl = build_template_info (tmpl, targs);
else
cand->template_decl = DECL_TEMPLATE_INFO (fn);
const char *str;
struct z_candidate *cand1;
struct z_candidate **cand2;
+ char *spaces;
if (!candidates)
return;
}
}
- str = _("candidates are:");
- print_z_candidate (str, candidates);
- if (candidates->next)
+ str = candidates->next ? _("candidates are:") : _("candidate is:");
+ spaces = NULL;
+ for (; candidates; candidates = candidates->next)
{
- /* Indent successive candidates by the width of the translation
- of the above string. */
- size_t len = gcc_gettext_width (str) + 1;
- char *spaces = (char *) alloca (len);
- memset (spaces, ' ', len-1);
- spaces[len - 1] = '\0';
-
- candidates = candidates->next;
- do
- {
- print_z_candidate (spaces, candidates);
- candidates = candidates->next;
- }
- while (candidates);
+ print_z_candidate (spaces ? spaces : str, candidates);
+ spaces = spaces ? spaces : get_spaces (str);
}
+ free (spaces);
}
/* USER_SEQ is a user-defined conversion sequence, beginning with a
reference to it)... */
}
else
- conv_fns = lookup_conversions (fromtype);
+ conv_fns = lookup_conversions (fromtype,
+ /*lookup_template_convs_p=*/true);
}
candidates = 0;
for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
- tree first = first_arg;
if (DECL_NONCONVERTING_P (fn)
&& (flags & LOOKUP_ONLYCONVERTING))
continue;
- /* Lambdas have a static conversion op. */
- if (DECL_STATIC_FUNCTION_P (fn))
- first = NULL_TREE;
-
/* [over.match.funcs] For conversion functions, the function
is considered to be a member of the class of the implicit
object argument for the purpose of defining the type of
if (TREE_CODE (fn) == TEMPLATE_DECL)
cand = add_template_candidate (&candidates, fn, fromtype,
NULL_TREE,
- first, NULL, totype,
+ first_arg, NULL, totype,
TYPE_BINFO (fromtype),
conversion_path,
flags,
DEDUCE_CONV);
else
cand = add_function_candidate (&candidates, fn, fromtype,
- first, NULL,
+ first_arg, NULL,
TYPE_BINFO (fromtype),
conversion_path,
flags);
{
tree fn = OVL_CURRENT (fns);
- tree lfirst = first_mem_arg;
- if (DECL_STATIC_FUNCTION_P (fn))
- lfirst = NULL_TREE;
-
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (&candidates, fn, base, NULL_TREE,
- lfirst, *args, NULL_TREE,
+ first_mem_arg, *args, NULL_TREE,
TYPE_BINFO (type),
TYPE_BINFO (type),
LOOKUP_NORMAL, DEDUCE_CALL);
else
add_function_candidate
- (&candidates, fn, base, lfirst, *args, TYPE_BINFO (type),
+ (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
- /* Rather than mess with handling static conversion ops here, just don't
- look at conversions in lambdas. */
- if (LAMBDA_TYPE_P (type))
- convs = NULL_TREE;
- else
- convs = lookup_conversions (type);
+ convs = lookup_conversions (type, /*lookup_template_convs_p=*/true);
for (; convs; convs = TREE_CHAIN (convs))
{
static void
op_error (enum tree_code code, enum tree_code code2,
- tree arg1, tree arg2, tree arg3, const char *problem)
+ tree arg1, tree arg2, tree arg3, bool match)
{
const char *opname;
switch (code)
{
case COND_EXPR:
- error ("%s for ternary %<operator?:%> in %<%E ? %E : %E%>",
- problem, arg1, arg2, arg3);
+ if (match)
+ error ("ambiguous overload for ternary %<operator?:%> "
+ "in %<%E ? %E : %E%>", arg1, arg2, arg3);
+ else
+ error ("no match for ternary %<operator?:%> "
+ "in %<%E ? %E : %E%>", arg1, arg2, arg3);
break;
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- error ("%s for %<operator%s%> in %<%E%s%>", problem, opname, arg1, opname);
+ if (match)
+ error ("ambiguous overload for %<operator%s%> in %<%E%s%>",
+ opname, arg1, opname);
+ else
+ error ("no match for %<operator%s%> in %<%E%s%>",
+ opname, arg1, opname);
break;
case ARRAY_REF:
- error ("%s for %<operator[]%> in %<%E[%E]%>", problem, arg1, arg2);
+ if (match)
+ error ("ambiguous overload for %<operator[]%> in %<%E[%E]%>",
+ arg1, arg2);
+ else
+ error ("no match for %<operator[]%> in %<%E[%E]%>",
+ arg1, arg2);
break;
case REALPART_EXPR:
case IMAGPART_EXPR:
- error ("%s for %qs in %<%s %E%>", problem, opname, opname, arg1);
+ if (match)
+ error ("ambiguous overload for %qs in %<%s %E%>",
+ opname, opname, arg1);
+ else
+ error ("no match for %qs in %<%s %E%>",
+ opname, opname, arg1);
break;
default:
if (arg2)
- error ("%s for %<operator%s%> in %<%E %s %E%>",
- problem, opname, arg1, opname, arg2);
+ if (match)
+ error ("ambiguous overload for %<operator%s%> in %<%E %s %E%>",
+ opname, arg1, opname, arg2);
+ else
+ error ("no match for %<operator%s%> in %<%E %s %E%>",
+ opname, arg1, opname, arg2);
else
- error ("%s for %<operator%s%> in %<%s%E%>",
- problem, opname, opname, arg1);
+ if (match)
+ error ("ambiguous overload for %<operator%s%> in %<%s%E%>",
+ opname, opname, arg1);
+ else
+ error ("no match for %<operator%s%> in %<%s%E%>",
+ opname, opname, arg1);
break;
}
}
{
if (complain & tf_error)
{
- op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
+ op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
print_z_candidates (candidates);
}
return error_mark_node;
{
if (complain & tf_error)
{
- op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
+ op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
print_z_candidates (candidates);
}
return error_mark_node;
|| (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
{
result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
- arg3, "conditional expression",
+ arg3, CPO_CONDITIONAL_EXPR,
complain);
if (result_type == error_mark_node)
return error_mark_node;
{
/* ... Otherwise, report the more generic
"no matching operator found" error */
- op_error (code, code2, arg1, arg2, arg3, "no match");
+ op_error (code, code2, arg1, arg2, arg3, FALSE);
print_z_candidates (candidates);
}
}
{
if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error))
{
- op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
+ op_error (code, code2, arg1, arg2, arg3, TRUE);
print_z_candidates (candidates);
}
result = error_mark_node;
return cp_build_modify_expr (arg1, code2, arg2, complain);
case INDIRECT_REF:
- return cp_build_indirect_ref (arg1, "unary *", complain);
+ return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain);
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
return build_array_ref (input_location, arg1, arg2);
case MEMBER_REF:
- return build_m_component_ref (cp_build_indirect_ref (arg1, NULL,
+ return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL,
complain),
arg2);
if (expr == null_node && TREE_CODE (t) != BOOLEAN_TYPE && ARITHMETIC_TYPE_P (t))
{
if (fn)
- warning (OPT_Wconversion, "passing NULL to non-pointer argument %P of %qD",
- argnum, fn);
+ warning_at (input_location, OPT_Wconversion_null,
+ "passing NULL to non-pointer argument %P of %qD",
+ argnum, fn);
else
- warning (OPT_Wconversion, "converting to non-pointer type %qT from NULL", t);
+ warning_at (input_location, OPT_Wconversion_null,
+ "converting to non-pointer type %qT from NULL", t);
}
/* Issue warnings if "false" is converted to a NULL pointer */
else if (expr == boolean_false_node && fn && POINTER_TYPE_P (t))
- warning (OPT_Wconversion,
- "converting %<false%> to pointer type for argument %P of %qD",
- argnum, fn);
+ warning_at (input_location, OPT_Wconversion_null,
+ "converting %<false%> to pointer type for argument %P of %qD",
+ argnum, fn);
}
/* Perform the conversions in CONVS on the expression EXPR. FN and
switch (convs->kind)
{
case ck_rvalue:
- expr = convert_bitfield_to_declared_type (expr);
+ expr = decay_conversion (expr);
if (! MAYBE_CLASS_TYPE_P (totype))
return expr;
/* Else fall through. */
/* Build an expression for `*((base*) &expr)'. */
expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
expr = convert_to_base (expr, build_pointer_type (totype),
- !c_cast_p, /*nonnull=*/true);
- expr = cp_build_indirect_ref (expr, "implicit conversion", complain);
+ !c_cast_p, /*nonnull=*/true, complain);
+ expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
return expr;
}
case ck_ptr:
if (convs->base_p)
expr = convert_to_base (expr, totype, !c_cast_p,
- /*nonnull=*/false);
+ /*nonnull=*/false, complain);
return build_nop (totype, expr);
case ck_pmem:
error ("cannot receive objects of non-trivially-copyable type %q#T "
"through %<...%>; ", type);
expr = convert (build_pointer_type (type1), null_node);
- expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+ expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
return expr;
}
tree tmpl = TI_TEMPLATE (cand->template_decl);
tree realparm = chain_index (j, DECL_ARGUMENTS (cand->fn));
tree patparm = get_pattern_parm (realparm, tmpl);
+ tree pattype = TREE_TYPE (patparm);
+ if (PACK_EXPANSION_P (pattype))
+ pattype = PACK_EXPANSION_PATTERN (pattype);
+ pattype = non_reference (pattype);
- if (!is_std_init_list (non_reference (TREE_TYPE (patparm))))
+ if (!is_std_init_list (pattype))
{
pedwarn (input_location, 0, "deducing %qT as %qT",
non_reference (TREE_TYPE (patparm)),
if (targ)
arg = targ;
else
- arg = cp_build_indirect_ref (arg, 0, complain);
+ arg = cp_build_indirect_ref (arg, RO_NULL, complain);
if (TREE_CODE (arg) == TARGET_EXPR
&& TARGET_EXPR_LIST_INIT_P (arg))
|| (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
&& !move_fn_p (fn)))
{
- tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+ tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
complain));
+ tree type = TREE_TYPE (to);
- val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
+ if (TREE_CODE (arg) != TARGET_EXPR
+ && TREE_CODE (arg) != AGGR_INIT_EXPR
+ && is_really_empty_class (type))
+ {
+ /* Avoid copying empty classes. */
+ val = build2 (COMPOUND_EXPR, void_type_node, to, arg);
+ TREE_NO_WARNING (val) = 1;
+ val = build2 (COMPOUND_EXPR, type, val, to);
+ TREE_NO_WARNING (val) = 1;
+ }
+ else
+ val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
}
}
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
- (cp_build_indirect_ref (argarray[0], 0, complain));
+ (cp_build_indirect_ref (argarray[0], RO_NULL, complain));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
tree arg = argarray[1];
- if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
+ if (is_really_empty_class (type))
+ {
+ /* Avoid copying empty classes. */
+ val = build2 (COMPOUND_EXPR, void_type_node, to, arg);
+ TREE_NO_WARNING (val) = 1;
+ val = build2 (COMPOUND_EXPR, type, val, to);
+ TREE_NO_WARNING (val) = 1;
+ }
+ else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
- arg = cp_build_indirect_ref (arg, 0, complain);
+ arg = cp_build_indirect_ref (arg, RO_NULL, complain);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
}
else
t = convert (TREE_TYPE (arg0), t);
if (test)
t = build3 (COND_EXPR, TREE_TYPE (t), test, arg0, t);
- val = cp_build_indirect_ref (t, 0, complain);
+ val = cp_build_indirect_ref (t, RO_NULL, complain);
TREE_NO_WARNING (val) = 1;
}
/* Look up the pointer to the runtime java.lang.Class object for `instance'.
This is the first entry in the vtable. */
- klass_ref = build_vtbl_ref (cp_build_indirect_ref (instance, 0,
+ klass_ref = build_vtbl_ref (cp_build_indirect_ref (instance, RO_NULL,
tf_warning_or_error),
integer_zero_node);
make_args_non_dependent (*args);
}
+ user_args = args == NULL ? NULL : *args;
+ /* Under DR 147 A::A() is an invalid constructor call,
+ not a functional cast. */
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
+ {
+ if (! (complain & tf_error))
+ return error_mark_node;
+
+ permerror (input_location,
+ "cannot call constructor %<%T::%D%> directly",
+ basetype, name);
+ permerror (input_location, " for a function-style cast, remove the "
+ "redundant %<::%D%>", name);
+ call = build_functional_cast (basetype, build_tree_list_vec (user_args),
+ complain);
+ return call;
+ }
+
/* Figure out whether to skip the first argument for the error
message we will display to users if an error occurs. We don't
want to display any compiler-generated arguments. The "this"
pointer if this is a call to a base-class constructor or
destructor. */
skip_first_for_error = false;
- user_args = args == NULL ? NULL : *args;
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
/* Callers should explicitly indicate whether they want to construct
expr = convert_like_real (conv, expr, NULL_TREE, 0, 0,
/*issue_conversion_warnings=*/false,
c_cast_p,
- tf_warning_or_error);
+ complain);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
expr = convert_to_base (expr,
build_pointer_type (base_conv_type),
/*check_access=*/true,
- /*nonnull=*/true);
+ /*nonnull=*/true, complain);
expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
}
else