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 *);
conversion **, tree, tree, int);
static tree source_type (conversion *);
static void add_warning (struct z_candidate *, struct z_candidate *);
-static bool reference_related_p (tree, tree);
static bool reference_compatible_p (tree, tree);
static conversion *convert_class_to_reference (tree, tree, tree, int);
static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
-static tree call_builtin_trap (void);
static tree prep_operand (tree);
-static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
- int, struct z_candidate **);
+static void add_candidates (tree, tree, const VEC(tree,gc) *, tree, tree, bool,
+ tree, tree, int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
static tree build_temp (tree, tree, int, diagnostic_t *);
return false;
}
- if (!name)
+ if (!name || name == error_mark_node)
return false;
return same_type_p (TYPE_MAIN_VARIANT (basetype), TYPE_MAIN_VARIANT (name));
}
gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
|| TREE_CODE (fntype) == METHOD_TYPE);
result_type = TREE_TYPE (fntype);
+ /* An rvalue has no cv-qualifiers. */
+ if (SCALAR_TYPE_P (result_type) || VOID_TYPE_P (result_type))
+ result_type = cv_unqualified (result_type);
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
argarray[i], t);
}
- function = build_call_array (result_type, function, n, argarray);
+ function = build_call_array_loc (input_location,
+ result_type, function, n, argarray);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
/* [conv.ptr]
A null pointer constant is an integral constant expression
- (_expr.const_) rvalue of integer type that evaluates to zero. */
+ (_expr.const_) rvalue of integer type that evaluates to zero or
+ an rvalue of type std::nullptr_t. */
t = integral_constant_value (t);
- if (t == null_node)
+ if (t == null_node
+ || TREE_CODE (TREE_TYPE (t)) == NULLPTR_TYPE)
return true;
if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))
{
{
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;
if (same_type_p (from, to))
return conv;
- if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
+ /* [conv.ptr]
+ A null pointer constant can be converted to a pointer type; ... A
+ null pointer constant of integral type can be converted to an
+ rvalue of type std::nullptr_t. */
+ if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)
+ || tcode == NULLPTR_TYPE)
&& expr && null_ptr_cst_p (expr))
conv = build_conv (ck_std, to, conv);
else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
|| cp_type_quals (fbase) != cp_type_quals (tbase))
return NULL;
- from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
- from = build_method_type_directly (from,
- TREE_TYPE (fromfn),
- TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+ from = build_memfn_type (fromfn, tbase, cp_type_quals (tbase));
from = build_ptrmemfunc_type (build_pointer_type (from));
conv = build_conv (ck_pmem, from, conv);
conv->base_p = true;
An rvalue of arithmetic, unscoped enumeration, pointer, or
pointer to member type can be converted to an rvalue of type
- bool. */
+ bool. ... An rvalue of type std::nullptr_t can be converted
+ to an rvalue of type bool; */
if (ARITHMETIC_TYPE_P (from)
|| UNSCOPED_ENUM_P (from)
|| fcode == POINTER_TYPE
- || TYPE_PTR_TO_MEMBER_P (from))
+ || TYPE_PTR_TO_MEMBER_P (from)
+ || fcode == NULLPTR_TYPE)
{
conv = build_conv (ck_std, to, conv);
if (fcode == POINTER_TYPE
|| TYPE_PTRMEM_P (from)
|| (TYPE_PTRMEMFUNC_P (from)
- && conv->rank < cr_pbool))
+ && conv->rank < cr_pbool)
+ || fcode == NULLPTR_TYPE)
conv->rank = cr_pbool;
return conv;
}
/* Returns nonzero if T1 is reference-related to T2. */
-static bool
+bool
reference_related_p (tree t1, tree t2)
{
t1 = TYPE_MAIN_VARIANT (t1);
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;
t = TREE_TYPE (reference_type);
+ /* We're performing a user-defined conversion to a desired type, so set
+ this for the benefit of add_candidates. */
+ flags |= LOOKUP_NO_CONVERSION;
+
for (; conversions; conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
+ tree binfo = TREE_PURPOSE (conversions);
+ struct z_candidate *old_candidates = candidates;;
+
+ add_candidates (fns, first_arg, NULL, reference_type,
+ NULL_TREE, false,
+ binfo, TYPE_BINFO (s),
+ flags, &candidates);
- for (; fns; fns = OVL_NEXT (fns))
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree f = OVL_CURRENT (fns);
+ /* Now, see if the conversion function really returns
+ an lvalue of the appropriate type. From the
+ point of view of unification, simply returning an
+ rvalue of the right type is good enough. */
+ tree f = cand->fn;
tree t2 = TREE_TYPE (TREE_TYPE (f));
-
- if (DECL_NONCONVERTING_P (f)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- cand = NULL;
-
- /* If this is a template function, try to get an exact
- match. */
- if (TREE_CODE (f) == TEMPLATE_DECL)
+ if (TREE_CODE (t2) != REFERENCE_TYPE
+ || !reference_compatible_p (t, TREE_TYPE (t2)))
{
- cand = add_template_candidate (&candidates,
- f, s,
- NULL_TREE,
- first_arg,
- NULL,
- reference_type,
- TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL,
- DEDUCE_CONV);
-
- if (cand)
- {
- /* Now, see if the conversion function really returns
- an lvalue of the appropriate type. From the
- point of view of unification, simply returning an
- rvalue of the right type is good enough. */
- f = cand->fn;
- t2 = TREE_TYPE (TREE_TYPE (f));
- if (TREE_CODE (t2) != REFERENCE_TYPE
- || !reference_compatible_p (t, TREE_TYPE (t2)))
- {
- candidates = candidates->next;
- cand = NULL;
- }
- }
+ cand->viable = 0;
}
- else if (TREE_CODE (t2) == REFERENCE_TYPE
- && reference_compatible_p (t, TREE_TYPE (t2)))
- cand = add_function_candidate (&candidates, f, s, first_arg,
- NULL, TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL);
-
- if (cand)
+ else
{
conversion *identity_conv;
/* Build a standard conversion sequence indicating the
= TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn)))
== TYPE_REF_IS_RVALUE (reference_type);
cand->second_conv->bad_p |= cand->convs[0]->bad_p;
+
+ /* Don't allow binding of lvalues to rvalue references. */
+ if (TYPE_REF_IS_RVALUE (reference_type)
+ && !TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn))))
+ cand->second_conv->bad_p = true;
}
}
}
build_identity_conv (TREE_TYPE (expr), expr));
conv->cand = cand;
+ if (cand->viable == -1)
+ conv->bad_p = true;
+
/* Merge it with the standard conversion sequence from the
conversion function's return type to the desired type. */
cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
- if (cand->viable == -1)
- conv->bad_p = true;
-
return cand->second_conv;
}
tree tfrom;
bool related_p;
bool compatible_p;
- cp_lvalue_kind lvalue_p = clk_none;
+ cp_lvalue_kind is_lvalue = clk_none;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
if (TREE_CODE (from) == REFERENCE_TYPE)
{
/* Anything with reference type is an lvalue. */
- lvalue_p = clk_ordinary;
+ is_lvalue = clk_ordinary;
from = TREE_TYPE (from);
}
- else if (expr)
- lvalue_p = real_lvalue_p (expr);
+
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+ conv = implicit_conversion (to, from, expr, c_cast_p,
+ flags);
+ if (!CLASS_TYPE_P (to)
+ && CONSTRUCTOR_NELTS (expr) == 1)
+ {
+ expr = CONSTRUCTOR_ELT (expr, 0)->value;
+ if (error_operand_p (expr))
+ return NULL;
+ from = TREE_TYPE (expr);
+ }
+ }
+
+ if (is_lvalue == clk_none && expr)
+ is_lvalue = real_lvalue_p (expr);
tfrom = from;
- if ((lvalue_p & clk_bitfield) != 0)
+ if ((is_lvalue & clk_bitfield) != 0)
tfrom = unlowered_expr_type (expr);
/* Figure out whether or not the types are reference-related and
/* Directly bind reference when target expression's type is compatible with
the reference and expression is an lvalue. In DR391, the wording in
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
- const and rvalue references to rvalues of compatible class type. */
+ const and rvalue references to rvalues of compatible class type.
+ We should also do direct bindings for non-class "rvalues" derived from
+ rvalue references. */
if (compatible_p
- && (lvalue_p
- || (!(flags & LOOKUP_NO_TEMP_BIND)
- && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
- && CLASS_TYPE_P (from))))
+ && (is_lvalue
+ || (((CP_TYPE_CONST_NON_VOLATILE_P (to)
+ && !(flags & LOOKUP_NO_TEMP_BIND))
+ || TYPE_REF_IS_RVALUE (rto))
+ && (CLASS_TYPE_P (from) || (expr && lvalue_p (expr))))))
{
/* [dcl.init.ref]
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
else
conv->rvaluedness_matches_p
- = (TYPE_REF_IS_RVALUE (rto) == !lvalue_p);
+ = (TYPE_REF_IS_RVALUE (rto) == !is_lvalue);
- if ((lvalue_p & clk_bitfield) != 0
- || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
+ if ((is_lvalue & clk_bitfield) != 0
+ || ((is_lvalue & clk_packed) != 0 && !TYPE_PACKED (to)))
/* For the purposes of overload resolution, we ignore the fact
this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
actually occurs. */
conv->need_temporary_p = true;
+ /* Don't allow binding of lvalues to rvalue references. */
+ if (is_lvalue && TYPE_REF_IS_RVALUE (rto)
+ && !(flags & LOOKUP_PREFER_RVALUE))
+ conv->bad_p = true;
+
return conv;
}
/* [class.conv.fct] A conversion function is never used to convert a
if (!(flags & LOOKUP_COPY_PARM))
flags |= LOOKUP_ONLYCONVERTING;
- conv = implicit_conversion (to, from, expr, c_cast_p,
- flags);
+ if (!conv)
+ conv = implicit_conversion (to, from, expr, c_cast_p,
+ flags);
if (!conv)
return NULL;
parmtype = build_pointer_type (parmtype);
}
- if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
+ if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn)
+ && (len-skip == 1))
{
/* Hack: Direct-initialize copy parm (i.e. suppress
LOOKUP_ONLYCONVERTING) to make explicit conversion ops
num_convs = args[2] ? 3 : (args[1] ? 2 : 1);
convs = alloc_conversions (num_convs);
- flags |= LOOKUP_ONLYCONVERTING;
+
+ /* TRUTH_*_EXPR do "contextual conversion to bool", which means explicit
+ conversion ops are allowed. We handle that here by just checking for
+ boolean_type_node because other operators don't ask for it. COND_EXPR
+ also does contextual conversion to bool for the first operand, but we
+ handle that in build_conditional_expr, and type1 here is operand 2. */
+ if (type1 != boolean_type_node)
+ flags |= LOOKUP_ONLYCONVERTING;
for (i = 0; i < 2; ++i)
{
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)
return_type, strict, flags);
if (i != 0)
- return NULL;
+ goto fail;
fn = instantiate_template (tmpl, targs, tf_none);
if (fn == error_mark_node)
- return NULL;
+ goto fail;
/* In [class.copy]:
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
- return NULL;
+ goto fail;
}
if (obj != 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);
return cand;
+ fail:
+ return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL,
+ access_path, conversion_path, 0);
}
}
/* The CANDS are the set of candidates that were considered for
- overload resolution. Return the set of viable candidates. If none
- of the candidates were viable, set *ANY_VIABLE_P to true. STRICT_P
- is true if a candidate should be considered viable only if it is
- strictly viable. */
+ overload resolution. Return the set of viable candidates, or CANDS
+ if none are viable. If any of the candidates were viable, set
+ *ANY_VIABLE_P to true. STRICT_P is true if a candidate should be
+ considered viable only if it is strictly viable. */
static struct z_candidate*
splice_viable (struct z_candidate *cands,
static inline int
equal_functions (tree fn1, tree fn2)
{
+ if (TREE_CODE (fn1) != TREE_CODE (fn2))
+ return 0;
+ if (TREE_CODE (fn1) == TEMPLATE_DECL)
+ return fn1 == fn2;
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
return decls_match (fn1, fn2);
inform (input_location, "%s %T <conversion>", msgstr, candidate->fn);
else if (candidate->viable == -1)
inform (input_location, "%s %+#D <near match>", msgstr, candidate->fn);
+ else if (DECL_DELETED_FN (STRIP_TEMPLATE (candidate->fn)))
+ inform (input_location, "%s %+#D <deleted>", msgstr, candidate->fn);
else
inform (input_location, "%s %+#D", msgstr, candidate->fn);
}
const char *str;
struct z_candidate *cand1;
struct z_candidate **cand2;
+ char *spaces;
+
+ if (!candidates)
+ return;
+
+ /* Remove deleted candidates. */
+ cand1 = candidates;
+ for (cand2 = &cand1; *cand2; )
+ {
+ if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ && DECL_DELETED_FN ((*cand2)->fn))
+ *cand2 = (*cand2)->next;
+ else
+ cand2 = &(*cand2)->next;
+ }
+ /* ...if there are any non-deleted ones. */
+ if (cand1)
+ candidates = cand1;
/* There may be duplicates in the set of candidates. We put off
checking this condition as long as possible, since we have no way
{
tree fn = cand1->fn;
/* Skip builtin candidates and conversion functions. */
- if (TREE_CODE (fn) != FUNCTION_DECL)
+ if (!DECL_P (fn))
continue;
cand2 = &cand1->next;
while (*cand2)
{
- if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ if (DECL_P ((*cand2)->fn)
&& equal_functions (fn, (*cand2)->fn))
*cand2 = (*cand2)->next;
else
}
}
- 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;
flags |= LOOKUP_NO_CONVERSION;
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ flags |= LOOKUP_NO_NARROWING;
/* It's OK to bind a temporary for converting constructor arguments, but
not in converting the return value of a conversion operator. */
if (ctors)
{
+ int ctorflags = flags;
+ bool try_single_arg = true;
ctors = BASELINK_FUNCTIONS (ctors);
first_arg = build_int_cst (build_pointer_type (totype), 0);
- if (BRACE_ENCLOSED_INITIALIZER_P (expr)
- && !TYPE_HAS_LIST_CTOR (totype))
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
- args = ctor_to_vec (expr);
- /* We still allow more conversions within an init-list. */
- flags = ((flags & ~LOOKUP_NO_CONVERSION)
- /* But not for the copy ctor. */
- |LOOKUP_NO_COPY_CTOR_CONVERSION
- |LOOKUP_NO_NARROWING);
+ /* For list-initialization we consider explicit constructors, but
+ give an error if one is selected. */
+ ctorflags &= ~LOOKUP_ONLYCONVERTING;
+ /* If the class has a list ctor, try passing the list as a single
+ argument first, but only consider list ctors. */
+ if (TYPE_HAS_LIST_CTOR (totype))
+ ctorflags |= LOOKUP_LIST_ONLY;
+ else
+ try_single_arg = false;
}
- else
- args = make_tree_vector_single (expr);
/* We should never try to call the abstract or base constructor
from here. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
- }
- for (; ctors; ctors = OVL_NEXT (ctors))
- {
- tree ctor = OVL_CURRENT (ctors);
- if (DECL_NONCONVERTING_P (ctor)
- && !BRACE_ENCLOSED_INITIALIZER_P (expr))
- continue;
- if (TREE_CODE (ctor) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, ctor, totype,
- NULL_TREE, first_arg, args, NULL_TREE,
- TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags,
- DEDUCE_CALL);
- else
- cand = add_function_candidate (&candidates, ctor, totype,
- first_arg, args, TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags);
+ /* If EXPR is not an initializer-list, or if totype has a list
+ constructor, try EXPR as a single argument. */
+ if (try_single_arg)
+ {
+ args = make_tree_vector_single (expr);
+ add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
+ TYPE_BINFO (totype), TYPE_BINFO (totype),
+ ctorflags, &candidates);
+ }
- if (cand)
+ /* If we didn't find a suitable list constructor for an initializer-list,
+ try breaking it apart. */
+ if (!candidates && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ args = ctor_to_vec (expr);
+ /* We aren't looking for list-ctors anymore. */
+ ctorflags &= ~LOOKUP_LIST_ONLY;
+ /* We still allow more conversions within an init-list. */
+ ctorflags &= ~LOOKUP_NO_CONVERSION;
+ /* But not for the copy ctor. */
+ ctorflags |= LOOKUP_NO_COPY_CTOR_CONVERSION;
+ add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
+ TYPE_BINFO (totype), TYPE_BINFO (totype),
+ ctorflags, &candidates);
+ }
+
+ for (cand = candidates; cand; cand = cand->next)
{
cand->second_conv = build_identity_conv (totype, NULL_TREE);
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
- tree fns;
tree conversion_path = TREE_PURPOSE (conv_fns);
+ struct z_candidate *old_candidates;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
- for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
+ old_candidates = candidates;
+ add_candidates (TREE_VALUE (conv_fns), first_arg, NULL, totype,
+ NULL_TREE, false,
+ conversion_path, TYPE_BINFO (fromtype),
+ flags, &candidates);
+
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree fn = OVL_CURRENT (fns);
-
- if (DECL_NONCONVERTING_P (fn)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- /* [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
- the implicit object parameter.
-
- So we pass fromtype as CTYPE to add_*_candidate. */
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, fn, fromtype,
- NULL_TREE,
- first_arg, NULL, totype,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags,
- DEDUCE_CONV);
- else
- cand = add_function_candidate (&candidates, fn, fromtype,
- first_arg, NULL,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags);
+ conversion *ics
+ = implicit_conversion (totype,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0,
+ /*c_cast_p=*/false, convflags);
- if (cand)
- {
- conversion *ics
- = implicit_conversion (totype,
- TREE_TYPE (TREE_TYPE (cand->fn)),
- 0,
- /*c_cast_p=*/false, convflags);
-
- /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
- copy-initialization. In that case, "The result of the
- call is then used to direct-initialize the object that is
- the destination of the copy-initialization." [dcl.init]
-
- We represent this in the conversion sequence with an
- rvalue conversion, which means a constructor call. But
- don't add a second rvalue conversion if there's already
- one there. Which there really shouldn't be, but it's
- harmless since we'd add it here anyway. */
- if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
- && !(convflags & LOOKUP_NO_TEMP_BIND))
- ics = build_conv (ck_rvalue, totype, ics);
-
- cand->second_conv = ics;
-
- if (!ics)
- cand->viable = 0;
- else if (candidates->viable == 1 && ics->bad_p)
- cand->viable = -1;
- }
+ /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
+ copy-initialization. In that case, "The result of the
+ call is then used to direct-initialize the object that is
+ the destination of the copy-initialization." [dcl.init]
+
+ We represent this in the conversion sequence with an
+ rvalue conversion, which means a constructor call. But
+ don't add a second rvalue conversion if there's already
+ one there. Which there really shouldn't be, but it's
+ harmless since we'd add it here anyway. */
+ if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
+ && !(convflags & LOOKUP_NO_TEMP_BIND))
+ ics = build_conv (ck_rvalue, totype, ics);
+
+ cand->second_conv = ics;
+
+ if (!ics)
+ cand->viable = 0;
+ else if (cand->viable == 1 && ics->bad_p)
+ cand->viable = -1;
}
}
}
/* Add the various candidate functions. */
- add_candidates (fn, args, explicit_targs, template_only,
+ add_candidates (fn, NULL_TREE, args, NULL_TREE,
+ explicit_targs, template_only,
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE,
LOOKUP_NORMAL,
{
if (complain & tf_error)
{
- if (!any_viable_p && candidates && ! candidates->next)
+ if (!any_viable_p && candidates && ! candidates->next
+ && (TREE_CODE (candidates->fn) == FUNCTION_DECL))
return cp_build_function_call_vec (candidates->fn, args, complain);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = TREE_OPERAND (fn, 0);
if (fns)
{
- tree base = BINFO_TYPE (BASELINK_BINFO (fns));
first_mem_arg = build_this (obj);
- for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (&candidates, fn, base, 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, first_mem_arg, *args, TYPE_BINFO (type),
- TYPE_BINFO (type), LOOKUP_NORMAL);
- }
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ first_mem_arg, *args, NULL_TREE,
+ NULL_TREE, false,
+ BASELINK_BINFO (fns), BASELINK_ACCESS_BINFO (fns),
+ LOOKUP_NORMAL, &candidates);
}
- 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;
}
}
tree arg2_type;
tree arg3_type;
tree result = NULL_TREE;
+ tree result_save;
tree result_type = NULL_TREE;
bool lvalue_p = true;
struct z_candidate *candidates = 0;
The first expression is implicitly converted to bool (clause
_conv_). */
- arg1 = perform_implicit_conversion (boolean_type_node, arg1, complain);
+ arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain,
+ LOOKUP_NORMAL);
/* If something has already gone wrong, just pass that fact up the
tree. */
bool any_viable_p;
/* Rearrange the arguments so that add_builtin_candidate only has
- to know about two args. In build_builtin_candidates, the
+ to know about two args. In build_builtin_candidate, the
arguments are unscrambled. */
args[0] = arg2;
args[1] = arg3;
{
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;
arg1 = convert_like (conv, arg1, complain);
conv = cand->convs[1];
arg2 = convert_like (conv, arg2, complain);
+ arg2_type = TREE_TYPE (arg2);
conv = cand->convs[2];
arg3 = convert_like (conv, arg3, complain);
+ arg3_type = TREE_TYPE (arg3);
}
/* [expr.cond]
arg2_type = TREE_TYPE (arg2);
arg3 = force_rvalue (arg3);
- if (!CLASS_TYPE_P (arg2_type))
+ if (!CLASS_TYPE_P (arg3_type))
arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == 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;
}
valid_operands:
- result = fold_if_not_in_template (build3 (COND_EXPR, result_type, arg1,
- arg2, arg3));
+ result_save = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
+ result = fold_if_not_in_template (result_save);
+
+ if (cp_unevaluated_operand && TREE_CODE (result) == CALL_EXPR)
+ /* Avoid folding to a CALL_EXPR within decltype (c++/42013). */
+ result = result_save;
+
/* We can't use result_type below, as fold might have returned a
throw_expr. */
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
- CANDIDATES. The ARGS are the arguments provided to the call,
- without any implicit object parameter. This may change ARGS. The
+ CANDIDATES. The ARGS are the arguments provided to the call;
+ if FIRST_ARG is non-null it is the implicit object argument,
+ otherwise the first element of ARGS is used if needed. The
EXPLICIT_TARGS are explicit template arguments provided.
TEMPLATE_ONLY is true if only template functions should be
considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for
add_function_candidate. */
static void
-add_candidates (tree fns, const VEC(tree,gc) *args,
+add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
+ tree return_type,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates)
{
tree ctype;
- VEC(tree,gc) *non_static_args;
- tree first_arg;
+ const VEC(tree,gc) *non_static_args;
+ bool check_list_ctor;
+ bool check_converting;
+ unification_kind_t strict;
+ tree fn;
+
+ if (!fns)
+ return;
+
+ /* Precalculate special handling of constructors and conversion ops. */
+ fn = OVL_CURRENT (fns);
+ if (DECL_CONV_FN_P (fn))
+ {
+ check_list_ctor = false;
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ if (flags & LOOKUP_NO_CONVERSION)
+ /* We're doing return_type(x). */
+ strict = DEDUCE_CONV;
+ else
+ /* We're doing x.operator return_type(). */
+ strict = DEDUCE_EXACT;
+ /* [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
+ the implicit object parameter. */
+ ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg)));
+ }
+ else
+ {
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ check_list_ctor = !!(flags & LOOKUP_LIST_ONLY);
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ }
+ else
+ {
+ check_list_ctor = false;
+ check_converting = false;
+ }
+ strict = DEDUCE_CALL;
+ ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
+ }
- ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
- /* Delay creating the implicit this parameter until it is needed. */
- non_static_args = NULL;
- first_arg = NULL_TREE;
+ if (first_arg)
+ non_static_args = args;
+ else
+ /* Delay creating the implicit this parameter until it is needed. */
+ non_static_args = NULL;
- while (fns)
+ for (; fns; fns = OVL_NEXT (fns))
{
- tree fn;
tree fn_first_arg;
const VEC(tree,gc) *fn_args;
fn = OVL_CURRENT (fns);
+
+ if (check_converting && DECL_NONCONVERTING_P (fn))
+ continue;
+ if (check_list_ctor && !is_list_ctor (fn))
+ continue;
+
/* Figure out which set of arguments to use. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{
- /* If this function is a non-static member, prepend the implicit
- object parameter. */
- if (non_static_args == NULL)
+ /* If this function is a non-static member and we didn't get an
+ implicit object argument, move it out of args. */
+ if (first_arg == NULL_TREE)
{
unsigned int ix;
tree arg;
-
- non_static_args = VEC_alloc (tree, gc,
- VEC_length (tree, args) - 1);
+ VEC(tree,gc) *tempvec
+ = VEC_alloc (tree, gc, VEC_length (tree, args) - 1);
for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix)
- VEC_quick_push (tree, non_static_args, arg);
+ VEC_quick_push (tree, tempvec, arg);
+ non_static_args = tempvec;
+ first_arg = build_this (VEC_index (tree, args, 0));
}
- if (first_arg == NULL_TREE)
- first_arg = build_this (VEC_index (tree, args, 0));
+
fn_first_arg = first_arg;
fn_args = non_static_args;
}
explicit_targs,
fn_first_arg,
fn_args,
- NULL_TREE,
+ return_type,
access_path,
conversion_path,
flags,
- DEDUCE_CALL);
+ strict);
else if (!template_only)
add_function_candidate (candidates,
fn,
access_path,
conversion_path,
flags);
- fns = OVL_NEXT (fns);
}
}
+/* Even unsigned enum types promote to signed int. We don't want to
+ issue -Wsign-compare warnings for this case. Here ORIG_ARG is the
+ original argument and ARG is the argument after any conversions
+ have been applied. We set TREE_NO_WARNING if we have added a cast
+ from an unsigned enum type to a signed integer type. */
+
+static void
+avoid_sign_compare_warnings (tree orig_arg, tree arg)
+{
+ if (orig_arg != NULL_TREE
+ && arg != NULL_TREE
+ && orig_arg != arg
+ && TREE_CODE (TREE_TYPE (orig_arg)) == ENUMERAL_TYPE
+ && TYPE_UNSIGNED (TREE_TYPE (orig_arg))
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg))
+ && !TYPE_UNSIGNED (TREE_TYPE (arg)))
+ TREE_NO_WARNING (arg) = 1;
+}
+
tree
build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
bool *overloaded_p, tsubst_flags_t complain)
{
+ tree orig_arg1 = arg1;
+ tree orig_arg2 = arg2;
+ tree orig_arg3 = arg3;
struct z_candidate *candidates = 0, *cand;
VEC(tree,gc) *arglist;
tree fnname;
arg3 = prep_operand (arg3);
if (code == COND_EXPR)
- {
- if (arg2 == NULL_TREE
- || TREE_CODE (TREE_TYPE (arg2)) == VOID_TYPE
- || TREE_CODE (TREE_TYPE (arg3)) == VOID_TYPE
- || (! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))
- && ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3))))
- goto builtin;
- }
+ /* Use build_conditional_expr instead. */
+ gcc_unreachable ();
else if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1))
&& (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))))
goto builtin;
/* Add namespace-scope operators to the list of functions to
consider. */
add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true),
- arglist, NULL_TREE, false, NULL_TREE, NULL_TREE,
+ NULL_TREE, arglist, NULL_TREE,
+ NULL_TREE, false, NULL_TREE, NULL_TREE,
flags, &candidates);
/* Add class-member operators to the candidate set. */
if (CLASS_TYPE_P (TREE_TYPE (arg1)))
goto user_defined_result_ready;
}
if (fns)
- add_candidates (BASELINK_FUNCTIONS (fns), arglist,
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ NULL_TREE, arglist, NULL_TREE,
NULL_TREE, false,
BASELINK_BINFO (fns),
- TYPE_BINFO (TREE_TYPE (arg1)),
+ BASELINK_ACCESS_BINFO (fns),
flags, &candidates);
}
- /* Rearrange the arguments for ?: so that add_builtin_candidate only has
- to know about two args; a builtin candidate will always have a first
- parameter of type bool. We'll handle that in
- build_builtin_candidate. */
- if (code == COND_EXPR)
- {
- args[0] = arg2;
- args[1] = arg3;
- args[2] = arg1;
- }
- else
- {
- args[0] = arg1;
- args[1] = arg2;
- args[2] = NULL_TREE;
- }
+ args[0] = arg1;
+ args[1] = arg2;
+ args[2] = NULL_TREE;
add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
if (!(complain & tf_error))
return error_mark_node;
- /* Look for an `operator++ (int)'. If they didn't have
- one, then we fall back to the old way of doing things. */
+ /* Look for an `operator++ (int)'. Pre-1985 C++ didn't
+ distinguish between prefix and postfix ++ and
+ operator++() was used for both, so we allow this with
+ -fpermissive. */
if (flags & LOOKUP_COMPLAIN)
- permerror (input_location, "no %<%D(int)%> declared for postfix %qs, "
- "trying prefix operator instead",
- fnname,
- operator_name_info[code].name);
+ {
+ const char *msg = (flag_permissive)
+ ? G_("no %<%D(int)%> declared for postfix %qs,"
+ " trying prefix operator instead")
+ : G_("no %<%D(int)%> declared for postfix %qs");
+ permerror (input_location, msg, fnname,
+ operator_name_info[code].name);
+ }
+
+ if (!flag_permissive)
+ return error_mark_node;
+
if (code == POSTINCREMENT_EXPR)
code = PREINCREMENT_EXPR;
else
{
/* ... 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 result;
builtin:
+ avoid_sign_compare_warnings (orig_arg1, arg1);
+ avoid_sign_compare_warnings (orig_arg2, arg2);
+ avoid_sign_compare_warnings (orig_arg3, arg3);
+
switch (code)
{
case MODIFY_EXPR:
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 cp_build_unary_op (code, arg1, candidates != 0, complain);
case ARRAY_REF:
- return build_array_ref (arg1, arg2, input_location);
-
- case COND_EXPR:
- return build_conditional_expr (arg1, arg2, arg3, complain);
+ 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);
return NULL_TREE;
}
+/* Returns true iff T, an element of an OVERLOAD chain, is a usual
+ deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */
+
+static bool
+non_placement_deallocation_fn_p (tree t)
+{
+ /* A template instance is never a usual deallocation function,
+ regardless of its signature. */
+ if (TREE_CODE (t) == TEMPLATE_DECL
+ || primary_template_instantiation_p (t))
+ return false;
+
+ /* If a class T has a member deallocation function named operator delete
+ with exactly one parameter, then that function is a usual
+ (non-placement) deallocation function. If class T does not declare
+ such an operator delete but does declare a member deallocation
+ function named operator delete with exactly two parameters, the second
+ of which has type std::size_t (18.2), then this function is a usual
+ deallocation function. */
+ t = FUNCTION_ARG_CHAIN (t);
+ if (t == void_list_node
+ || (t && same_type_p (TREE_VALUE (t), size_type_node)
+ && TREE_CHAIN (t) == void_list_node))
+ return true;
+ return false;
+}
+
/* Build a call to operator delete. This has to be handled very specially,
because the restrictions on what signatures match are different from all
other call instances. For a normal delete, only a delete taking (void *)
tree alloc_fn)
{
tree fn = NULL_TREE;
- tree fns, fnname, argtypes, type;
- int pass;
+ tree fns, fnname, type, t;
if (addr == error_mark_node)
return error_mark_node;
if (placement)
{
- /* Get the parameter types for the allocation function that is
- being called. */
- gcc_assert (alloc_fn != NULL_TREE);
- argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
- }
- else
- {
- /* First try it without the size argument. */
- argtypes = void_list_node;
- }
-
- /* We make two tries at finding a matching `operator delete'. On
- the first pass, we look for a one-operator (or placement)
- operator delete. If we're not doing placement delete, then on
- the second pass we look for a two-argument delete. */
- for (pass = 0; pass < (placement ? 1 : 2); ++pass)
- {
- /* Go through the `operator delete' functions looking for one
- with a matching type. */
- for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
- fn;
- fn = OVL_NEXT (fn))
+ /* "A declaration of a placement deallocation function matches the
+ declaration of a placement allocation function if it has the same
+ number of parameters and, after parameter transformations (8.3.5),
+ all parameter types except the first are identical."
+
+ So we build up the function type we want and ask instantiate_type
+ to get it for us. */
+ t = FUNCTION_ARG_CHAIN (alloc_fn);
+ t = tree_cons (NULL_TREE, ptr_type_node, t);
+ t = build_function_type (void_type_node, t);
+
+ fn = instantiate_type (t, fns, tf_none);
+ if (fn == error_mark_node)
+ return NULL_TREE;
+
+ if (BASELINK_P (fn))
+ fn = BASELINK_FUNCTIONS (fn);
+
+ /* "If the lookup finds the two-parameter form of a usual deallocation
+ function (3.7.4.2) and that function, considered as a placement
+ deallocation function, would have been selected as a match for the
+ allocation function, the program is ill-formed." */
+ if (non_placement_deallocation_fn_p (fn))
{
- tree t;
-
- /* The first argument must be "void *". */
- t = TYPE_ARG_TYPES (TREE_TYPE (OVL_CURRENT (fn)));
- if (!same_type_p (TREE_VALUE (t), ptr_type_node))
- continue;
- t = TREE_CHAIN (t);
- /* On the first pass, check the rest of the arguments. */
- if (pass == 0)
+ /* But if the class has an operator delete (void *), then that is
+ the usual deallocation function, so we shouldn't complain
+ about using the operator delete (void *, size_t). */
+ for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+ t; t = OVL_NEXT (t))
{
- tree a = argtypes;
- while (a && t)
- {
- if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
- break;
- a = TREE_CHAIN (a);
- t = TREE_CHAIN (t);
- }
- if (!a && !t)
- break;
+ tree elt = OVL_CURRENT (t);
+ if (non_placement_deallocation_fn_p (elt)
+ && FUNCTION_ARG_CHAIN (elt) == void_list_node)
+ goto ok;
}
- /* On the second pass, look for a function with exactly two
- arguments: "void *" and "size_t". */
- else if (pass == 1
- /* For "operator delete(void *, ...)" there will be
- no second argument, but we will not get an exact
- match above. */
- && t
- && same_type_p (TREE_VALUE (t), size_type_node)
- && TREE_CHAIN (t) == void_list_node)
- break;
+ permerror (0, "non-placement deallocation function %q+D", fn);
+ permerror (input_location, "selected for placement delete");
+ ok:;
}
-
- /* If we found a match, we're done. */
- if (fn)
- break;
}
+ else
+ /* "Any non-placement deallocation function matches a non-placement
+ allocation function. If the lookup finds a single matching
+ deallocation function, that function will be called; otherwise, no
+ deallocation function will be called." */
+ for (t = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+ t; t = OVL_NEXT (t))
+ {
+ tree elt = OVL_CURRENT (t);
+ if (non_placement_deallocation_fn_p (elt))
+ {
+ fn = elt;
+ /* "If a class T has a member deallocation function named
+ operator delete with exactly one parameter, then that
+ function is a usual (non-placement) deallocation
+ function. If class T does not declare such an operator
+ delete but does declare a member deallocation function named
+ operator delete with exactly two parameters, the second of
+ which has type std::size_t (18.2), then this function is a
+ usual deallocation function."
+
+ So (void*) beats (void*, size_t). */
+ if (FUNCTION_ARG_CHAIN (fn) == void_list_node)
+ break;
+ }
+ }
/* If we have a matching function, call it. */
if (fn)
{
- /* Make sure we have the actual function, and not an
- OVERLOAD. */
- fn = OVL_CURRENT (fn);
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
/* If the FN is a member function, make sure that it is
accessible. */
- if (DECL_CLASS_SCOPE_P (fn))
- perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
+ if (BASELINK_P (fns))
+ perform_or_defer_access_check (BASELINK_BINFO (fns), fn, fn);
+
+ /* Core issue 901: It's ok to new a type with deleted delete. */
+ if (DECL_DELETED_FN (fn) && alloc_fn)
+ return NULL_TREE;
if (placement)
{
tree ret;
VEC(tree,gc) *args = VEC_alloc (tree, gc, 2);
VEC_quick_push (tree, args, addr);
- if (pass != 0)
+ if (FUNCTION_ARG_CHAIN (fn) != void_list_node)
VEC_quick_push (tree, args, size);
ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error);
VEC_free (tree, gc, args);
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
tree convfn = cand->fn;
unsigned i;
+ expr = mark_rvalue_use (expr);
+
/* When converting from an init list we consider explicit
constructors, but actually trying to call one is an error. */
if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
return expr;
}
case ck_identity:
+ expr = mark_rvalue_use (expr);
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
int nelts = CONSTRUCTOR_NELTS (expr);
}
return expr;
case ck_ambig:
+ if (!(complain & tf_error))
+ return error_mark_node;
/* Call build_user_type_conversion again for the error. */
return build_user_type_conversion
(totype, convs->u.expr, LOOKUP_NORMAL);
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;
}
{
tree ref_type = totype;
+ if (convs->bad_p && TYPE_REF_IS_RVALUE (ref_type)
+ && real_lvalue_p (expr))
+ {
+ if (complain & tf_error)
+ {
+ error ("cannot bind %qT lvalue to %qT",
+ TREE_TYPE (expr), totype);
+ if (fn)
+ error (" initializing argument %P of %q+D", argnum, fn);
+ }
+ return error_mark_node;
+ }
+
/* If necessary, create a temporary.
VA_ARG_EXPR and CONSTRUCTOR expressions are special cases
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:
return expr;
}
-/* Build a call to __builtin_trap. */
-
-static tree
-call_builtin_trap (void)
-{
- tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
-
- gcc_assert (fn != NULL);
- fn = build_call_n (fn, 0);
- return fn;
-}
-
/* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */
promoted type before the call. */
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg))
- < TYPE_PRECISION (double_type_node)))
+ < TYPE_PRECISION (double_type_node))
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (arg))))
arg = convert_to_real (double_type_node, arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == NULLPTR_TYPE)
+ arg = null_pointer_node;
else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
arg = perform_integral_promotions (arg);
arg = require_complete_type (arg);
if (arg != error_mark_node
- && !pod_type_p (TREE_TYPE (arg)))
+ && (type_has_nontrivial_copy_init (TREE_TYPE (arg))
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg))))
{
- /* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
- here and do a bitwise copy, but now cp_expr_size will abort if we
- try to do that.
+ /* [expr.call] 5.2.2/7:
+ Passing a potentially-evaluated argument of class type (Clause 9)
+ with a non-trivial copy constructor or a non-trivial destructor
+ with no corresponding parameter is conditionally-supported, with
+ implementation-defined semantics.
+
+ We used to just warn here and do a bitwise copy, but now
+ cp_expr_size will abort if we try to do that.
+
If the call appears in the context of a sizeof expression,
- there is no need to emit a warning, since the expression won't be
- evaluated. We keep the builtin_trap just as a safety check. */
- if (!skip_evaluation)
- warning (0, "cannot pass objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", TREE_TYPE (arg));
- arg = call_builtin_trap ();
- arg = build2 (COMPOUND_EXPR, integer_type_node, arg,
- integer_zero_node);
+ it is not potentially-evaluated. */
+ if (cp_unevaluated_operand == 0)
+ error ("cannot pass objects of non-trivially-copyable "
+ "type %q#T through %<...%>", TREE_TYPE (arg));
}
return arg;
if (expr == error_mark_node || !type)
return error_mark_node;
- if (! pod_type_p (type))
+ expr = mark_lvalue_use (expr);
+
+ if (type_has_nontrivial_copy_init (type)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ || TREE_CODE (type) == REFERENCE_TYPE)
{
/* Remove reference types so we don't ICE later on. */
tree type1 = non_reference (type);
- /* Undefined behavior [expr.call] 5.2.2/7. */
- warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
- "call will abort at runtime", type);
+ /* conditionally-supported behavior [expr.call] 5.2.2/7. */
+ error ("cannot receive objects of non-trivially-copyable type %q#T "
+ "through %<...%>; ", type);
expr = convert (build_pointer_type (type1), null_node);
- expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
- call_builtin_trap (), expr);
- 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;
}
- return build_va_arg (expr, type);
+ return build_va_arg (input_location, expr, type);
}
/* TYPE has been given to va_arg. Apply the default conversions which
alcarray[ix + 1] = arg;
argarray = alcarray;
}
- expr = build_call_array (return_type, build_addr_func (fn), nargs,
- argarray);
+ expr = build_call_array_loc (input_location,
+ return_type, build_addr_func (fn), nargs,
+ argarray);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
&& !TREE_ADDRESSABLE (type))
conv = conv->u.next;
+ /* Warn about initializer_list deduction that isn't currently in the
+ working draft. */
+ if (cxx_dialect > cxx98
+ && flag_deduce_init_list
+ && cand->template_decl
+ && is_std_init_list (non_reference (type)))
+ {
+ 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 (pattype))
+ {
+ pedwarn (input_location, 0, "deducing %qT as %qT",
+ non_reference (TREE_TYPE (patparm)),
+ non_reference (type));
+ pedwarn (input_location, 0, " in call to %q+D", cand->fn);
+ pedwarn (input_location, 0,
+ " (you can disable this with -fno-deduce-init-list)");
+ }
+ }
+
val = convert_like_with_context
(conv, VEC_index (tree, args, arg_index), fn, i - is_method,
complain);
{
tree a = VEC_index (tree, args, arg_index);
if (magic_varargs_p (fn))
- /* Do no conversions for magic varargs. */;
+ /* Do no conversions for magic varargs. */
+ a = mark_type_use (a);
else
a = convert_arg_to_ellipsis (a);
argarray[j++] = a;
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));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
&& 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
arg1 = arg;
arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain);
- if (!(optimize && flag_tree_ter))
+ if (!can_trust_pointer_alignment ())
{
- /* When TER is off get_pointer_alignment returns 0, so a call
+ /* If we can't be sure about pointer alignment, a call
to __builtin_memcpy is expanded as a call to memcpy, which
- is invalid with identical args. When TER is on it is
+ is invalid with identical args. Otherwise it is
expanded as a block move, which should be safe. */
arg0 = save_expr (arg0);
arg1 = save_expr (arg1);
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);
VEC(tree,gc) *user_args;
tree call;
tree fn;
- tree class_type;
int template_only = 0;
bool any_viable_p;
tree orig_instance;
tree orig_fns;
VEC(tree,gc) *orig_args = NULL;
void *p;
+ tree list = NULL_TREE;
+ bool try_normal;
gcc_assert (instance != NULL_TREE);
*fn_p = NULL_TREE;
if (error_operand_p (instance)
- || error_operand_p (fns))
+ || !fns || error_operand_p (fns))
return error_mark_node;
if (!BASELINK_P (fns))
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
name = complete_dtor_identifier;
/* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
- initializer, not T({ }). If the type doesn't have a list ctor,
- break apart the list into separate ctor args. */
+ initializer, not T({ }). If the type doesn't have a list ctor (or no
+ viable list ctor), break apart the list into separate ctor args. */
+ try_normal = true;
if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args)
&& BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
- && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0))
- && !TYPE_HAS_LIST_CTOR (basetype))
+ && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)))
{
gcc_assert (VEC_length (tree, *args) == 1);
- *args = ctor_to_vec (VEC_index (tree, *args, 0));
+ list = VEC_index (tree, *args, 0);
+
+ if (TYPE_HAS_LIST_CTOR (basetype))
+ flags |= LOOKUP_LIST_ONLY;
+ else
+ try_normal = false;
}
- class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
first_mem_arg = instance_ptr;
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
- for (fn = fns; fn; fn = OVL_NEXT (fn))
+ any_viable_p = false;
+ if (try_normal)
{
- tree t = OVL_CURRENT (fn);
- tree this_first_arg;
-
- /* We can end up here for copy-init of same or base class. */
- if ((flags & LOOKUP_ONLYCONVERTING)
- && DECL_NONCONVERTING_P (t))
- continue;
-
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_first_arg = first_mem_arg;
- else
- this_first_arg = NULL_TREE;
+ add_candidates (fns, first_mem_arg, user_args, optype,
+ explicit_targs, template_only, conversion_path,
+ access_binfo, flags, &candidates);
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ }
- if (TREE_CODE (t) == TEMPLATE_DECL)
- /* A member template. */
- add_template_candidate (&candidates, t,
- class_type,
- explicit_targs,
- this_first_arg,
- args == NULL ? NULL : *args,
- optype,
- access_binfo,
- conversion_path,
- flags,
- DEDUCE_CALL);
- else if (! template_only)
- add_function_candidate (&candidates, t,
- class_type,
- this_first_arg,
- args == NULL ? NULL : *args,
- access_binfo,
- conversion_path,
- flags);
+ if (!any_viable_p && list)
+ {
+ VEC(tree,gc) *list_args = ctor_to_vec (list);
+ flags &= ~LOOKUP_LIST_ONLY;
+ add_candidates (fns, first_mem_arg, list_args, optype,
+ explicit_targs, template_only, conversion_path,
+ access_binfo, flags, &candidates);
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
}
- candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
if (complain & tf_error)
{
if (!COMPLETE_TYPE_P (basetype))
cxx_incomplete_type_error (instance_ptr, basetype);
+ else if (optype)
+ error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
+ basetype, optype, build_tree_list_vec (user_args),
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
else
{
char *pretty_name;
conversion *old_ics = *ics;
*ics = old_ics->u.next;
(*ics)->user_conv_p = old_ics->user_conv_p;
- (*ics)->bad_p = old_ics->bad_p;
return old_ics;
}
ref_conv1 = maybe_handle_ref_bind (&ics1);
ref_conv2 = maybe_handle_ref_bind (&ics2);
+ /* List-initialization sequence L1 is a better conversion sequence than
+ list-initialization sequence L2 if L1 converts to
+ std::initializer_list<X> for some X and L2 does not. */
+ if (ics1->kind == ck_list && ics2->kind != ck_list)
+ return 1;
+ if (ics2->kind == ck_list && ics1->kind != ck_list)
+ return -1;
+
/* [over.ics.rank]
When comparing the basic forms of implicit conversion sequences (as
/* We couldn't make up our minds; try to figure it out below. */
}
- if (ics1->ellipsis_p)
- /* Both conversions are ellipsis conversions. */
+ if (ics1->ellipsis_p || ics1->kind == ck_list)
+ /* Both conversions are ellipsis conversions or both are building a
+ std::initializer_list. */
return 0;
/* User-defined conversion sequence U1 is a better conversion sequence
conversion *t1;
conversion *t2;
- for (t1 = ics1; t1->kind != ck_user && t1->kind != ck_list; t1 = t1->u.next)
+ for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
if (t1->kind == ck_ambig || t1->kind == ck_aggr)
return 0;
- for (t2 = ics2; t2->kind != ck_user && t2->kind != ck_list; t2 = t2->u.next)
+ for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
if (t2->kind == ck_ambig || t2->kind == ck_aggr)
return 0;
- /* Conversion to std::initializer_list is better than other
- user-defined conversions. */
- if (t1->kind == ck_list
- || t2->kind == ck_list)
- {
- if (t2->kind != ck_list)
- return 1;
- else if (t1->kind != ck_list)
- return -1;
- else
- return 0;
- }
-
if (t1->cand->fn != t2->cand->fn)
return 0;
Two conversion sequences with the same rank are indistinguishable
unless one of the following rules applies:
- --A conversion that is not a conversion of a pointer, or pointer
- to member, to bool is better than another conversion that is such
- a conversion.
+ --A conversion that does not a convert a pointer, pointer to member,
+ or std::nullptr_t to bool is better than one that does.
The ICS_STD_RANK automatically handles the pointer-to-bool rule,
so that we do not have to check it explicitly. */
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);
Return the converted expression. */
tree
-initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
+initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
+ tsubst_flags_t complain)
{
conversion *conv;
void *p;
LOOKUP_NORMAL);
if (!conv || conv->bad_p)
{
- if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
- && !real_lvalue_p (expr))
- error ("invalid initialization of non-const reference of "
- "type %qT from a temporary of type %qT",
- type, TREE_TYPE (expr));
- else
- error ("invalid initialization of reference of type "
- "%qT from expression of type %qT", type,
- TREE_TYPE (expr));
+ if (complain & tf_error)
+ {
+ if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
+ && !TYPE_REF_IS_RVALUE (type)
+ && !real_lvalue_p (expr))
+ error ("invalid initialization of non-const reference of "
+ "type %qT from an rvalue of type %qT",
+ type, TREE_TYPE (expr));
+ else
+ error ("invalid initialization of reference of type "
+ "%qT from expression of type %qT", type,
+ TREE_TYPE (expr));
+ }
return error_mark_node;
}
expr = error_mark_node;
else
{
- if (!real_lvalue_p (expr))
+ if (!lvalue_or_rvalue_with_address_p (expr))
{
tree init;
var = set_up_extended_ref_temp (decl, expr, cleanup, &init);
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