/* Functions related to invoking methods and overloaded functions.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
ck_ref_bind,
ck_user,
ck_ambig,
+ ck_list,
+ ck_aggr,
ck_rvalue
} conversion_kind;
being bound to an lvalue expression or an rvalue reference is
being bound to an rvalue expression. */
BOOL_BITFIELD rvaluedness_matches_p: 1;
+ BOOL_BITFIELD check_narrowing: 1;
/* The type of the expression resulting from the conversion. */
tree type;
union {
/* The expression at the beginning of the conversion chain. This
variant is used only if KIND is ck_identity or ck_ambig. */
tree expr;
+ /* The array of conversions for an initializer_list. */
+ conversion **list;
} u;
/* The function candidate corresponding to this conversion
sequence. This field is only used if KIND is ck_user. */
static int equal_functions (tree, tree);
static int joust (struct z_candidate *, struct z_candidate *, bool);
static int compare_ics (conversion *, conversion *);
-static tree build_over_call (struct z_candidate *, int);
+static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
static tree build_java_interface_fn_ref (tree, tree);
-#define convert_like(CONV, EXPR) \
+#define convert_like(CONV, EXPR, COMPLAIN) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true, \
- /*c_cast_p=*/false)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
- convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
- /*issue_conversion_warnings=*/true, \
- /*c_cast_p=*/false)
+ /*c_cast_p=*/false, (COMPLAIN))
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO, COMPLAIN ) \
+ convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
+ /*issue_conversion_warnings=*/true, \
+ /*c_cast_p=*/false, (COMPLAIN))
static tree convert_like_real (conversion *, tree, tree, int, int, bool,
- bool);
+ bool, tsubst_flags_t);
static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, const char *);
-static tree build_object_call (tree, tree);
-static tree resolve_args (tree);
+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 *);
static void print_z_candidates (struct z_candidate *);
static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, unification_kind_t);
+ (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+ tree, tree, tree, int, unification_kind_t);
static struct z_candidate *add_template_candidate_real
- (struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, tree, unification_kind_t);
+ (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+ tree, tree, tree, int, tree, unification_kind_t);
static struct z_candidate *add_template_conv_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree, tree);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree, tree);
static void add_builtin_candidates
(struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int);
(struct z_candidate **, tree, tree, tree, tree *, tree *,
int);
static struct z_candidate *add_conv_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree);
static struct z_candidate *add_function_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree, int);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree, int);
static conversion *implicit_conversion (tree, tree, tree, bool, int);
static conversion *standard_conversion (tree, tree, tree, bool, int);
static conversion *reference_binding (tree, tree, tree, bool, int);
static conversion *build_conv (conversion_kind, tree, conversion *);
+static conversion *build_list_conv (tree, tree, int);
static bool is_subseq (conversion *, conversion *);
static conversion *maybe_handle_ref_bind (conversion **);
static void maybe_handle_implicit_object (conversion **);
static struct z_candidate *add_candidate
- (struct z_candidate **, tree, tree, size_t,
+ (struct z_candidate **, tree, tree, const VEC(tree,gc) *, size_t,
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);
+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, tree, tree, bool, tree, tree,
+static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
-typedef void (*diagnostic_fn_t) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
-static tree build_temp (tree, tree, int, diagnostic_fn_t *);
+static tree build_temp (tree, tree, int, diagnostic_t *);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
NAME can take many forms... */
/* OK */;
else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
- if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
+ if ((MAYBE_CLASS_TYPE_P (basetype)
+ && name == constructor_name (basetype))
|| (TREE_CODE (basetype) == ENUMERAL_TYPE
&& name == TYPE_IDENTIFIER (basetype)))
return true;
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)
nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
- if (decl && TREE_THIS_VOLATILE (decl) && cfun)
+ if (decl && TREE_THIS_VOLATILE (decl) && cfun && cp_function_chain)
current_function_returns_abnormally = 1;
if (decl && TREE_DEPRECATED (decl))
- warn_deprecated_use (decl);
+ warn_deprecated_use (decl, NULL_TREE);
require_complete_eh_spec_types (fntype, decl);
if (decl && DECL_CONSTRUCTOR_P (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;
/* The FUNCTION_DECL that will be called if this candidate is
selected by overload resolution. */
tree fn;
- /* The arguments to use when calling this function. */
- tree args;
+ /* If not NULL_TREE, the first argument to use when calling this
+ function. */
+ tree first_arg;
+ /* The rest of the arguments to use when calling this function. If
+ there are no further arguments this may be NULL or it may be an
+ empty vector. */
+ const VEC(tree,gc) *args;
/* The implicit conversion sequences for each of the arguments to
FN. */
conversion **convs;
conversion *t;
conversion_rank rank = CONVERSION_RANK (from);
- /* We can't use buildl1 here because CODE could be USER_CONV, which
- takes two arguments. In that case, the caller is responsible for
- filling in the second argument. */
+ /* Note that the caller is responsible for filling in t->cand for
+ user-defined conversions. */
t = alloc_conversion (code);
t->type = type;
t->u.next = from;
return t;
}
+/* Represent a conversion from CTOR, a braced-init-list, to TYPE, a
+ specialization of std::initializer_list<T>, if such a conversion is
+ possible. */
+
+static conversion *
+build_list_conv (tree type, tree ctor, int flags)
+{
+ tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (type), 0);
+ unsigned len = CONSTRUCTOR_NELTS (ctor);
+ conversion **subconvs = alloc_conversions (len);
+ conversion *t;
+ unsigned i;
+ tree val;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val)
+ {
+ conversion *sub
+ = implicit_conversion (elttype, TREE_TYPE (val), val,
+ false, flags);
+ if (sub == NULL)
+ return NULL;
+
+ subconvs[i] = sub;
+ }
+
+ t = alloc_conversion (ck_list);
+ t->type = type;
+ t->u.list = subconvs;
+ t->rank = cr_exact;
+
+ for (i = 0; i < len; ++i)
+ {
+ conversion *sub = subconvs[i];
+ if (sub->rank > t->rank)
+ t->rank = sub->rank;
+ if (sub->user_conv_p)
+ t->user_conv_p = true;
+ if (sub->bad_p)
+ t->bad_p = true;
+ }
+
+ return t;
+}
+
+/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
+ aggregate class, if such a conversion is possible. */
+
+static conversion *
+build_aggr_conv (tree type, tree ctor, int flags)
+{
+ unsigned HOST_WIDE_INT i = 0;
+ conversion *c;
+ tree field = TYPE_FIELDS (type);
+
+ for (; field; field = TREE_CHAIN (field), ++i)
+ {
+ 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;
+ }
+ else if (build_value_init (TREE_TYPE (field)) == error_mark_node)
+ return NULL;
+ }
+
+ c = alloc_conversion (ck_aggr);
+ c->type = type;
+ c->rank = cr_exact;
+ c->user_conv_p = true;
+ c->u.next = NULL;
+ return c;
+}
+
/* Build a representation of the identity conversion from EXPR to
itself. The TYPE should match the type of EXPR, if EXPR is non-NULL. */
if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
&& expr && type_unknown_p (expr))
{
- expr = instantiate_type (to, expr, tf_conv);
+ tsubst_flags_t tflags = tf_conv;
+ if (!(flags & LOOKUP_PROTECT))
+ tflags |= tf_no_access_control;
+ expr = instantiate_type (to, expr, tflags);
if (expr == error_mark_node)
return NULL;
from = TREE_TYPE (expr);
conv = build_conv (ck_std, to, conv);
conv->bad_p = true;
}
- else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE)
+ else if (UNSCOPED_ENUM_P (to) && fcode == INTEGER_TYPE)
{
/* For backwards brain damage compatibility, allow interconversion of
enums and integers with a pedwarn. */
else if (!same_type_p (fbase, tbase))
return NULL;
}
- else if (IS_AGGR_TYPE (TREE_TYPE (from))
- && IS_AGGR_TYPE (TREE_TYPE (to))
+ else if (CLASS_TYPE_P (TREE_TYPE (from))
+ && CLASS_TYPE_P (TREE_TYPE (to))
/* [conv.ptr]
An rvalue of type "pointer to cv D," where D is a
|| 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;
{
/* [conv.bool]
- An rvalue of arithmetic, enumeration, pointer, or pointer to
- member type can be converted to an rvalue of type bool. */
+ An rvalue of arithmetic, unscoped enumeration, pointer, or
+ pointer to member type can be converted to an rvalue of type
+ bool. */
if (ARITHMETIC_TYPE_P (from)
- || fcode == ENUMERAL_TYPE
+ || UNSCOPED_ENUM_P (from)
|| fcode == POINTER_TYPE
|| TYPE_PTR_TO_MEMBER_P (from))
{
/* As an extension, allow conversion to complex type. */
else if (ARITHMETIC_TYPE_P (to))
{
- if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
+ if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)
+ || SCOPED_ENUM_P (from))
return NULL;
conv = build_conv (ck_std, to, conv);
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& vector_types_convertible_p (from, to, false))
return build_conv (ck_std, to, conv);
- else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
+ else if (MAYBE_CLASS_TYPE_P (to) && MAYBE_CLASS_TYPE_P (from)
&& is_properly_derived_from (from, to))
{
if (conv->kind == ck_rvalue)
else
return NULL;
+ if (flags & LOOKUP_NO_NARROWING)
+ conv->check_narrowing = true;
+
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);
converted to T as in [over.match.ref]. */
static conversion *
-convert_class_to_reference (tree reference_type, tree s, tree expr)
+convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
{
tree conversions;
- tree arglist;
+ tree first_arg;
conversion *conv;
tree t;
struct z_candidate *candidates;
error messages, which we should not issue now because we are just
trying to find a conversion operator. Therefore, we use NULL,
cast to the appropriate type. */
- arglist = build_int_cst (build_pointer_type (s), 0);
- arglist = build_tree_list (NULL_TREE, arglist);
+ first_arg = build_int_cst (build_pointer_type (s), 0);
t = TREE_TYPE (reference_type);
- while (conversions)
+ for (; conversions; conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
tree f = OVL_CURRENT (fns);
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
cand = add_template_candidate (&candidates,
f, s,
NULL_TREE,
- arglist,
+ first_arg,
+ NULL,
reference_type,
TYPE_BINFO (s),
TREE_PURPOSE (conversions),
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
- cand = add_function_candidate (&candidates, f, s, arglist,
- TYPE_BINFO (s),
+ cand = add_function_candidate (&candidates, f, s, first_arg,
+ NULL, TYPE_BINFO (s),
TREE_PURPOSE (conversions),
LOOKUP_NORMAL);
= 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;
}
}
- conversions = TREE_CHAIN (conversions);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
/* Now that we know that this is the function we're going to use fix
the dummy first argument. */
- cand->args = tree_cons (NULL_TREE,
- build_this (expr),
- TREE_CHAIN (cand->args));
+ gcc_assert (cand->first_arg == NULL_TREE
+ || integer_zerop (cand->first_arg));
+ cand->first_arg = build_this (expr);
/* Build a user-defined conversion sequence representing the
conversion. */
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 ("extended 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;
+ 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
- || ((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
the reference is bound to the lvalue result of the conversion
in the second case. */
- conv = convert_class_to_reference (rto, from, expr);
+ conv = convert_class_to_reference (rto, from, expr, flags);
if (conv)
return conv;
}
conversion operator). */
flags |= LOOKUP_NO_TEMP_BIND;
- conv = implicit_conversion (to, from, expr, c_cast_p,
- flags);
+ /* Temporaries are copy-initialized, except for this hack to allow
+ explicit conversion ops to the copy ctor. See also
+ add_function_candidate. */
+ if (!(flags & LOOKUP_COPY_PARM))
+ flags |= LOOKUP_ONLYCONVERTING;
+
+ if (!conv)
+ conv = implicit_conversion (to, from, expr, c_cast_p,
+ flags);
if (!conv)
return NULL;
/* Returns the implicit conversion sequence (see [over.ics]) from type
FROM to type TO. The optional expression EXPR may affect the
- conversion. FLAGS are the usual overloading flags. Only
- LOOKUP_NO_CONVERSION is significant. If C_CAST_P is true, this
- conversion is coming from a C-style cast. */
+ conversion. FLAGS are the usual overloading flags. If C_CAST_P is
+ true, this conversion is coming from a C-style cast. */
static conversion *
implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
if (conv)
return conv;
+ 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 (SCALAR_TYPE_P (to))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ tree elt;
+
+ if (nelts == 0)
+ elt = integer_zero_node;
+ else if (nelts == 1)
+ elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ elt = error_mark_node;
+
+ conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+ c_cast_p, flags);
+ if (conv)
+ {
+ conv->check_narrowing = true;
+ if (BRACE_ENCLOSED_INITIALIZER_P (elt))
+ /* Too many levels of braces, i.e. '{{1}}'. */
+ conv->bad_p = true;
+ return conv;
+ }
+ }
+ }
+
if (expr != NULL_TREE
- && (IS_AGGR_TYPE (from)
- || IS_AGGR_TYPE (to))
+ && (MAYBE_CLASS_TYPE_P (from)
+ || MAYBE_CLASS_TYPE_P (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
struct z_candidate *cand;
- int convflags = ((flags & LOOKUP_NO_TEMP_BIND)
- |LOOKUP_ONLYCONVERTING);
+ int convflags = (flags & (LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING));
+
+ if (CLASS_TYPE_P (to)
+ && !CLASSTYPE_NON_AGGREGATE (complete_type (to))
+ && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ return build_aggr_conv (to, expr, flags);
cand = build_user_type_conversion_1 (to, expr, convflags);
if (cand)
}
/* Add a new entry to the list of candidates. Used by the add_*_candidate
- functions. */
+ functions. ARGS will not be changed until a single candidate is
+ selected. */
static struct z_candidate *
add_candidate (struct z_candidate **candidates,
- tree fn, tree args,
+ tree fn, tree first_arg, const VEC(tree,gc) *args,
size_t num_convs, conversion **convs,
tree access_path, tree conversion_path,
int viable)
conversion_obstack_alloc (sizeof (struct z_candidate));
cand->fn = fn;
+ cand->first_arg = first_arg;
cand->args = args;
cand->convs = convs;
cand->num_convs = num_convs;
return cand;
}
-/* Create an overload candidate for the function or method FN called with
- the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on
- to implicit_conversion.
+/* Create an overload candidate for the function or method FN called
+ with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
+ FLAGS is passed on to implicit_conversion.
+
+ This does not change ARGS.
CTYPE, if non-NULL, is the type we want to pretend this function
comes from for purposes of overload resolution. */
static struct z_candidate *
add_function_candidate (struct z_candidate **candidates,
- tree fn, tree ctype, tree arglist,
- tree access_path, tree conversion_path,
- int flags)
+ tree fn, tree ctype, tree first_arg,
+ const VEC(tree,gc) *args, tree access_path,
+ tree conversion_path, int flags)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
conversion **convs;
- tree parmnode, argnode;
- tree orig_arglist;
+ tree parmnode;
+ tree orig_first_arg = first_arg;
+ int skip;
int viable = 1;
/* At this point we should not see any functions which haven't been
if (DECL_CONSTRUCTOR_P (fn))
{
parmlist = skip_artificial_parms_for (fn, parmlist);
- orig_arglist = arglist;
- arglist = skip_artificial_parms_for (fn, arglist);
+ skip = num_artificial_parms_for (fn);
+ if (skip > 0 && first_arg != NULL_TREE)
+ {
+ --skip;
+ first_arg = NULL_TREE;
+ }
}
else
- orig_arglist = arglist;
+ skip = 0;
- len = list_length (arglist);
+ len = VEC_length (tree, args) - skip + (first_arg != NULL_TREE ? 1 : 0);
convs = alloc_conversions (len);
/* 13.3.2 - Viable functions [over.match.viable]
to the corresponding parameter of F. */
parmnode = parmlist;
- argnode = arglist;
for (i = 0; i < len; ++i)
{
- tree arg = TREE_VALUE (argnode);
- tree argtype = lvalue_type (arg);
+ tree arg, argtype;
conversion *t;
int is_this;
if (parmnode == void_list_node)
break;
+ if (i == 0 && first_arg != NULL_TREE)
+ arg = first_arg;
+ else
+ arg = VEC_index (tree, args,
+ i + skip - (first_arg != NULL_TREE ? 1 : 0));
+ argtype = lvalue_type (arg);
+
is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
&& ! DECL_CONSTRUCTOR_P (fn));
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
+ int lflags = flags;
/* The type of the implicit object parameter ('this') for
overload resolution is not always the same as for the
parmtype = build_pointer_type (parmtype);
}
+ 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
+ work. See also reference_binding. */
+ lflags |= LOOKUP_COPY_PARM;
+ if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
+ lflags |= LOOKUP_NO_CONVERSION;
+ }
+ else
+ lflags |= LOOKUP_ONLYCONVERTING;
+
t = implicit_conversion (parmtype, argtype, arg,
- /*c_cast_p=*/false, flags);
+ /*c_cast_p=*/false, lflags);
}
else
{
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
}
out:
- return add_candidate (candidates, fn, orig_arglist, len, convs,
+ return add_candidate (candidates, fn, orig_first_arg, args, len, convs,
access_path, conversion_path, viable);
}
/* Create an overload candidate for the conversion function FN which will
be invoked for expression OBJ, producing a pointer-to-function which
- will in turn be called with the argument list ARGLIST, and add it to
- CANDIDATES. FLAGS is passed on to implicit_conversion.
+ will in turn be called with the argument list FIRST_ARG/ARGLIST,
+ and add it to CANDIDATES. This does not change ARGLIST. FLAGS is
+ passed on to implicit_conversion.
Actually, we don't really care about FN; we care about the type it
converts to. There may be multiple conversion functions that will
static struct z_candidate *
add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
- tree arglist, tree access_path, tree conversion_path)
+ tree first_arg, const VEC(tree,gc) *arglist,
+ tree access_path, tree conversion_path)
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
- tree parmlist, parmnode, argnode;
+ tree parmlist, parmnode;
conversion **convs;
for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
parmlist = TREE_TYPE (parmlist);
parmlist = TYPE_ARG_TYPES (parmlist);
- len = list_length (arglist) + 1;
+ len = VEC_length (tree, arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
convs = alloc_conversions (len);
parmnode = parmlist;
- argnode = arglist;
viable = 1;
- flags = LOOKUP_NORMAL;
+ flags = LOOKUP_IMPLICIT;
/* Don't bother looking up the same type twice. */
if (*candidates && (*candidates)->fn == totype)
for (i = 0; i < len; ++i)
{
- tree arg = i == 0 ? obj : TREE_VALUE (argnode);
- tree argtype = lvalue_type (arg);
+ tree arg, argtype;
conversion *t;
if (i == 0)
+ arg = obj;
+ else if (i == 1 && first_arg != NULL_TREE)
+ arg = first_arg;
+ else
+ arg = VEC_index (tree, arglist,
+ i - (first_arg != NULL_TREE ? 1 : 0) - 1);
+ argtype = lvalue_type (arg);
+
+ if (i == 0)
t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
flags);
else if (parmnode == void_list_node)
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
}
if (i < len)
if (!sufficient_parms_p (parmnode))
viable = 0;
- return add_candidate (candidates, totype, arglist, len, convs,
+ return add_candidate (candidates, totype, first_arg, arglist, len, convs,
access_path, conversion_path, viable);
}
num_convs = args[2] ? 3 : (args[1] ? 2 : 1);
convs = alloc_conversions (num_convs);
+ /* 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)
{
if (! args[i])
viable = 0;
}
- add_candidate (candidates, fnname, /*args=*/NULL_TREE,
+ add_candidate (candidates, fnname, /*first_arg=*/NULL_TREE, /*args=*/NULL,
num_convs, convs,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE,
(including e.g. int and long but excluding e.g. char).
Similarly, the term promoted arithmetic type refers to promoted
integral types plus floating types. */
- return ((INTEGRAL_TYPE_P (type)
+ return ((CP_INTEGRAL_TYPE_P (type)
&& same_type_p (type_promotes_to (type), type))
|| TREE_CODE (type) == REAL_TYPE);
}
T operator~(T); */
case BIT_NOT_EXPR:
- if (INTEGRAL_TYPE_P (type1))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1))
break;
return;
tree c1 = TREE_TYPE (type1);
tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
- if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
+ if (MAYBE_CLASS_TYPE_P (c1) && DERIVED_FROM_P (c2, c1)
&& (TYPE_PTRMEMFUNC_P (type2)
|| is_complete (TYPE_PTRMEM_POINTED_TO_TYPE (type2))))
break;
case MINUS_EXPR:
if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2))
break;
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1)
+ && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
case ARRAY_REF:
- if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && TYPE_PTROB_P (type2))
{
type1 = ptrdiff_type_node;
break;
}
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
{
case PLUS_EXPR:
case MINUS_EXPR:
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
|| (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
|| (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1)
- || IS_AGGR_TYPE (type1)
+ || MAYBE_CLASS_TYPE_P (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
build_builtin_candidate
{
if (! args[i])
;
- else if (IS_AGGR_TYPE (argtypes[i]))
+ else if (MAYBE_CLASS_TYPE_P (argtypes[i]))
{
tree convs;
for (; convs; convs = TREE_CHAIN (convs))
{
- type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
+ type = TREE_TYPE (convs);
if (i == 0 && ref1
&& (TREE_CODE (type) != REFERENCE_TYPE
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+ if (enum_p && UNSCOPED_ENUM_P (type))
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
types[i] = tree_cons (NULL_TREE, type, types[i]);
TMPL is the template. EXPLICIT_TARGS are any explicit template
arguments. ARGLIST is the arguments provided at the call-site.
- The RETURN_TYPE is the desired type for conversion operators. If
- OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate.
- If an OBJ is supplied, FLAGS and CTYPE are ignored, and OBJ is as for
- add_conv_candidate. */
+ This does not change ARGLIST. The RETURN_TYPE is the desired type
+ for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are
+ as for add_function_candidate. If an OBJ is supplied, FLAGS and
+ CTYPE are ignored, and OBJ is as for add_conv_candidate. */
static struct z_candidate*
add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
- tree ctype, tree explicit_targs, tree arglist,
- tree return_type, tree access_path,
- tree conversion_path, int flags, tree obj,
- unification_kind_t strict)
+ tree ctype, tree explicit_targs, tree first_arg,
+ const VEC(tree,gc) *arglist, tree return_type,
+ tree access_path, tree conversion_path,
+ int flags, tree obj, unification_kind_t strict)
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
- tree args_without_in_chrg = arglist;
+ unsigned int nargs;
+ int skip_without_in_chrg;
+ tree first_arg_without_in_chrg;
+ tree *args_without_in_chrg;
+ unsigned int nargs_without_in_chrg;
+ unsigned int ia, ix;
+ tree arg;
struct z_candidate *cand;
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))
- args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+ {
+ if (first_arg_without_in_chrg != NULL_TREE)
+ first_arg_without_in_chrg = NULL_TREE;
+ else
+ ++skip_without_in_chrg;
+ }
if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
|| DECL_BASE_CONSTRUCTOR_P (tmpl))
&& CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl)))
- args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+ {
+ if (first_arg_without_in_chrg != NULL_TREE)
+ first_arg_without_in_chrg = NULL_TREE;
+ else
+ ++skip_without_in_chrg;
+ }
+
+ nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
+ + (VEC_length (tree, arglist)
+ - skip_without_in_chrg));
+ args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
+ ia = 0;
+ if (first_arg_without_in_chrg != NULL_TREE)
+ {
+ args_without_in_chrg[ia] = first_arg_without_in_chrg;
+ ++ia;
+ }
+ for (ix = skip_without_in_chrg;
+ VEC_iterate (tree, arglist, ix, arg);
+ ++ix)
+ {
+ args_without_in_chrg[ia] = arg;
+ ++ia;
+ }
+ gcc_assert (ia == nargs_without_in_chrg);
i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
+ nargs_without_in_chrg,
return_type, strict, flags);
if (i != 0)
class type, and a logical interpretation is that the intent was
to forbid the instantiation of member templates which would then
have that form. */
- if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2)
+ if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
{
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
- cand = add_conv_candidate (candidates, fn, obj, access_path,
- conversion_path, arglist);
+ cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+ access_path, conversion_path);
else
cand = add_function_candidate (candidates, fn, ctype,
- arglist, access_path,
+ first_arg, arglist, access_path,
conversion_path, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
static struct z_candidate *
add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
- tree explicit_targs, tree arglist, tree return_type,
+ tree explicit_targs, tree first_arg,
+ const VEC(tree,gc) *arglist, tree return_type,
tree access_path, tree conversion_path, int flags,
unification_kind_t strict)
{
return
add_template_candidate_real (candidates, tmpl, ctype,
- explicit_targs, arglist, return_type,
- access_path, conversion_path,
+ explicit_targs, first_arg, arglist,
+ return_type, access_path, conversion_path,
flags, NULL_TREE, strict);
}
static struct z_candidate *
add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
- tree obj, tree arglist, tree return_type,
- tree access_path, tree conversion_path)
+ tree obj, tree first_arg,
+ const VEC(tree,gc) *arglist,
+ tree return_type, tree access_path,
+ tree conversion_path)
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
- arglist, return_type, access_path,
+ first_arg, arglist, return_type, access_path,
conversion_path, 0, obj, DEDUCE_CONV);
}
if (processing_template_decl)
return build_address (obj);
- return build_unary_op (ADDR_EXPR, obj, 0);
+ return cp_build_unary_op (ADDR_EXPR, obj, 0, tf_warning_or_error);
}
/* Returns true iff functions are equivalent. Equivalent functions are
if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE)
{
if (candidate->num_convs == 3)
- inform ("%s %D(%T, %T, %T) <built-in>", msgstr, candidate->fn,
+ inform (input_location, "%s %D(%T, %T, %T) <built-in>", msgstr, candidate->fn,
candidate->convs[0]->type,
candidate->convs[1]->type,
candidate->convs[2]->type);
else if (candidate->num_convs == 2)
- inform ("%s %D(%T, %T) <built-in>", msgstr, candidate->fn,
+ inform (input_location, "%s %D(%T, %T) <built-in>", msgstr, candidate->fn,
candidate->convs[0]->type,
candidate->convs[1]->type);
else
- inform ("%s %D(%T) <built-in>", msgstr, candidate->fn,
+ inform (input_location, "%s %D(%T) <built-in>", msgstr, candidate->fn,
candidate->convs[0]->type);
}
else if (TYPE_P (candidate->fn))
- inform ("%s %T <conversion>", msgstr, candidate->fn);
+ inform (input_location, "%s %T <conversion>", msgstr, candidate->fn);
else if (candidate->viable == -1)
- inform ("%s %+#D <near match>", msgstr, candidate->fn);
+ inform (input_location, "%s %+#D <near match>", msgstr, candidate->fn);
+ else if (DECL_DELETED_FN (candidate->fn))
+ inform (input_location, "%s %+#D <deleted>", msgstr, candidate->fn);
else
- inform ("%s %+#D", msgstr, candidate->fn);
+ inform (input_location, "%s %+#D", msgstr, candidate->fn);
}
static void
struct z_candidate *cand1;
struct z_candidate **cand2;
+ 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
to eliminate duplicates from a set of functions in less than n^2
}
}
- if (!candidates)
- return;
-
str = _("candidates are:");
print_z_candidate (str, candidates);
if (candidates->next)
tree ctors = NULL_TREE;
tree conv_fns = NULL_TREE;
conversion *conv = NULL;
- tree args = NULL_TREE;
+ tree first_arg = NULL_TREE;
+ VEC(tree,gc) *args = NULL;
bool any_viable_p;
int convflags;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
constructor calls, as specified in [dcl.init]. */
- gcc_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
+ gcc_assert (!MAYBE_CLASS_TYPE_P (fromtype) || !MAYBE_CLASS_TYPE_P (totype)
|| !DERIVED_FROM_P (totype, fromtype));
- if (IS_AGGR_TYPE (totype))
+ if (MAYBE_CLASS_TYPE_P (totype))
ctors = lookup_fnfields (totype, complete_ctor_identifier, 0);
- if (IS_AGGR_TYPE (fromtype))
+ if (MAYBE_CLASS_TYPE_P (fromtype))
{
tree to_nonref = non_reference (totype);
if (same_type_ignoring_top_level_qualifiers_p (to_nonref, fromtype) ||
if (ctors)
{
- tree t;
-
ctors = BASELINK_FUNCTIONS (ctors);
- t = build_int_cst (build_pointer_type (totype), 0);
- args = build_tree_list (NULL_TREE, expr);
+ first_arg = build_int_cst (build_pointer_type (totype), 0);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && !TYPE_HAS_LIST_CTOR (totype))
+ {
+ 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);
+ }
+ 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)));
- args = tree_cons (NULL_TREE, t, args);
}
for (; ctors; ctors = OVL_NEXT (ctors))
{
tree ctor = OVL_CURRENT (ctors);
- if (DECL_NONCONVERTING_P (ctor))
+ 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, args, NULL_TREE,
+ NULL_TREE, first_arg, args, NULL_TREE,
TYPE_BINFO (totype),
TYPE_BINFO (totype),
flags,
DEDUCE_CALL);
else
cand = add_function_candidate (&candidates, ctor, totype,
- args, TYPE_BINFO (totype),
+ first_arg, args, TYPE_BINFO (totype),
TYPE_BINFO (totype),
flags);
if (cand)
- cand->second_conv = build_identity_conv (totype, NULL_TREE);
+ {
+ cand->second_conv = build_identity_conv (totype, NULL_TREE);
+
+ /* If totype isn't a reference, and 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. */
+ if (TREE_CODE (totype) != REFERENCE_TYPE
+ && !(convflags & LOOKUP_NO_TEMP_BIND))
+ cand->second_conv
+ = build_conv (ck_rvalue, totype, cand->second_conv);
+ }
}
if (conv_fns)
- args = build_tree_list (NULL_TREE, build_this (expr));
+ first_arg = build_this (expr);
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
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
if (TREE_CODE (fn) == TEMPLATE_DECL)
cand = add_template_candidate (&candidates, fn, fromtype,
NULL_TREE,
- args, totype,
+ first, NULL, totype,
TYPE_BINFO (fromtype),
conversion_path,
flags,
DEDUCE_CONV);
else
cand = add_function_candidate (&candidates, fn, fromtype,
- args,
+ first, NULL,
TYPE_BINFO (fromtype),
conversion_path,
flags);
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)
build_identity_conv (TREE_TYPE (expr), expr));
conv->cand = cand;
+ /* Remember that this was a list-initialization. */
+ if (flags & LOOKUP_NO_NARROWING)
+ conv->check_narrowing = true;
+
/* Combine it with the second conversion sequence. */
cand->second_conv = merge_conversion_sequences (conv,
cand->second_conv);
{
if (cand->second_conv->kind == ck_ambig)
return error_mark_node;
- expr = convert_like (cand->second_conv, expr);
+ expr = convert_like (cand->second_conv, expr, tf_warning_or_error);
return convert_from_reference (expr);
}
return NULL_TREE;
/* Do any initial processing on the arguments to a function call. */
-static tree
-resolve_args (tree args)
+static VEC(tree,gc) *
+resolve_args (VEC(tree,gc) *args)
{
- tree t;
- for (t = args; t; t = TREE_CHAIN (t))
- {
- tree arg = TREE_VALUE (t);
+ unsigned int ix;
+ tree arg;
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ {
if (error_operand_p (arg))
- return error_mark_node;
+ return NULL;
else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
error ("invalid use of void expression");
- return error_mark_node;
+ return NULL;
}
- else if (invalid_nonstatic_memfn_p (arg))
- return error_mark_node;
+ else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error))
+ return NULL;
}
return args;
}
static struct z_candidate *
perform_overload_resolution (tree fn,
- tree args,
+ const VEC(tree,gc) *args,
struct z_candidate **candidates,
bool *any_viable_p)
{
*candidates = NULL;
*any_viable_p = true;
- /* Check FN and ARGS. */
+ /* Check FN. */
gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
|| TREE_CODE (fn) == TEMPLATE_DECL
|| TREE_CODE (fn) == OVERLOAD
|| TREE_CODE (fn) == TEMPLATE_ID_EXPR);
- gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
}
/* Return an expression for a call to FN (a namespace-scope function,
- or a static member function) with the ARGS. */
+ or a static member function) with the ARGS. This may change
+ ARGS. */
tree
-build_new_function_call (tree fn, tree args, bool koenig_p)
+build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
+ tsubst_flags_t complain)
{
struct z_candidate *candidates, *cand;
bool any_viable_p;
void *p;
tree result;
- args = resolve_args (args);
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
/* If this function was found without using argument dependent
lookup, then we want to ignore any undeclared friend
fn = remove_hidden_names (fn);
if (!fn)
{
- error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (orig_fn)), args);
+ if (complain & tf_error)
+ error ("no matching function for call to %<%D(%A)%>",
+ DECL_NAME (OVL_CURRENT (orig_fn)),
+ build_tree_list_vec (*args));
return error_mark_node;
}
}
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
- cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p);
+ cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p);
if (!cand)
{
- if (!any_viable_p && candidates && ! candidates->next)
- return build_function_call (candidates->fn, args);
- if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
- fn = TREE_OPERAND (fn, 0);
- if (!any_viable_p)
- error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (fn)), args);
- else
- error ("call of overloaded %<%D(%A)%> is ambiguous",
- DECL_NAME (OVL_CURRENT (fn)), args);
- if (candidates)
- print_z_candidates (candidates);
+ if (complain & tf_error)
+ {
+ if (!any_viable_p && candidates && ! candidates->next)
+ return cp_build_function_call_vec (candidates->fn, args, complain);
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = TREE_OPERAND (fn, 0);
+ if (!any_viable_p)
+ error ("no matching function for call to %<%D(%A)%>",
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
+ else
+ error ("call of overloaded %<%D(%A)%> is ambiguous",
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
+ if (candidates)
+ print_z_candidates (candidates);
+ }
result = error_mark_node;
}
else
- result = build_over_call (cand, LOOKUP_NORMAL);
+ result = build_over_call (cand, LOOKUP_NORMAL, complain);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
/* Build a call to a global operator new. FNNAME is the name of the
operator (either "operator new" or "operator new[]") and ARGS are
- the arguments provided. *SIZE points to the total number of bytes
- required by the allocation, and is updated if that is changed here.
- *COOKIE_SIZE is non-NULL if a cookie should be used. If this
- function determines that no cookie should be used, after all,
- *COOKIE_SIZE is set to NULL_TREE. If FN is non-NULL, it will be
- set, upon return, to the allocation function called. */
+ the arguments provided. This may change ARGS. *SIZE points to the
+ total number of bytes required by the allocation, and is updated if
+ that is changed here. *COOKIE_SIZE is non-NULL if a cookie should
+ be used. If this function determines that no cookie should be
+ used, after all, *COOKIE_SIZE is set to NULL_TREE. If FN is
+ non-NULL, it will be set, upon return, to the allocation function
+ called. */
tree
-build_operator_new_call (tree fnname, tree args,
+build_operator_new_call (tree fnname, VEC(tree,gc) **args,
tree *size, tree *cookie_size,
tree *fn)
{
if (fn)
*fn = NULL_TREE;
- args = tree_cons (NULL_TREE, *size, args);
- args = resolve_args (args);
- if (args == error_mark_node)
- return args;
+ VEC_safe_insert (tree, gc, *args, 0, *size);
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
/* Based on:
up in the global scope.
we disregard block-scope declarations of "operator new". */
- fns = lookup_function_nonclass (fnname, args, /*block_p=*/false);
+ fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
/* Figure out what function is being called. */
- cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p);
+ cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p);
/* If no suitable function could be found, issue an error message
and give up. */
{
if (!any_viable_p)
error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (fns)), args);
+ DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
else
error ("call of overloaded %<%D(%A)%> is ambiguous",
- DECL_NAME (OVL_CURRENT (fns)), args);
+ DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
bool use_cookie = true;
if (!abi_version_at_least (2))
{
- tree placement = TREE_CHAIN (args);
/* In G++ 3.2, the check was implemented incorrectly; it
looked at the placement expression, rather than the
type of the function. */
- if (placement && !TREE_CHAIN (placement)
- && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+ if (VEC_length (tree, *args) == 2
+ && same_type_p (TREE_TYPE (VEC_index (tree, *args, 1)),
ptr_type_node))
use_cookie = false;
}
/* Update the total size. */
*size = size_binop (PLUS_EXPR, *size, *cookie_size);
/* Update the argument list to reflect the adjusted size. */
- TREE_VALUE (args) = *size;
+ VEC_replace (tree, *args, 0, *size);
}
else
*cookie_size = NULL_TREE;
*fn = cand->fn;
/* Build the CALL_EXPR. */
- return build_over_call (cand, LOOKUP_NORMAL);
+ return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
}
-static tree
-build_object_call (tree obj, tree args)
+/* Build a new call to operator(). This may change ARGS. */
+
+tree
+build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
{
struct z_candidate *candidates = 0, *cand;
- tree fns, convs, mem_args = NULL_TREE;
+ tree fns, convs, first_mem_arg = NULL_TREE;
tree type = TREE_TYPE (obj);
bool any_viable_p;
tree result = NULL_TREE;
void *p;
+ if (error_operand_p (obj))
+ return error_mark_node;
+
+ obj = prep_operand (obj);
+
if (TYPE_PTRMEMFUNC_P (type))
{
- /* It's no good looking for an overloaded operator() on a
- pointer-to-member-function. */
- error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
+ if (complain & tf_error)
+ /* It's no good looking for an overloaded operator() on a
+ pointer-to-member-function. */
+ error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
return error_mark_node;
}
else
fns = NULL_TREE;
- args = resolve_args (args);
-
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
if (fns)
{
tree base = BINFO_TYPE (BASELINK_BINFO (fns));
- mem_args = tree_cons (NULL_TREE, build_this (obj), args);
+ first_mem_arg = build_this (obj);
for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
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,
- mem_args, NULL_TREE,
+ lfirst, *args, NULL_TREE,
TYPE_BINFO (type),
TYPE_BINFO (type),
LOOKUP_NORMAL, DEDUCE_CALL);
else
add_function_candidate
- (&candidates, fn, base, mem_args, TYPE_BINFO (type),
+ (&candidates, fn, base, lfirst, *args, TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
- convs = lookup_conversions (type);
+ /* 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);
for (; convs; convs = TREE_CHAIN (convs))
{
tree fns = TREE_VALUE (convs);
- tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
+ tree totype = TREE_TYPE (convs);
if ((TREE_CODE (totype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
+
+ if (DECL_NONCONVERTING_P (fn))
+ continue;
+
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_conv_candidate
- (&candidates, fn, obj, args, totype,
+ (&candidates, fn, obj, NULL_TREE, *args, totype,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE);
else
- add_conv_candidate (&candidates, fn, obj, args,
- /*conversion_path=*/NULL_TREE,
+ add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+ *args, /*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE);
}
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
- error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args);
- print_z_candidates (candidates);
+ if (complain & tf_error)
+ {
+ error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj),
+ build_tree_list_vec (*args));
+ print_z_candidates (candidates);
+ }
result = error_mark_node;
}
else
cand = tourney (candidates);
if (cand == 0)
{
- error ("call of %<(%T) (%A)%> is ambiguous", TREE_TYPE (obj), args);
- print_z_candidates (candidates);
+ if (complain & tf_error)
+ {
+ error ("call of %<(%T) (%A)%> is ambiguous",
+ TREE_TYPE (obj), build_tree_list_vec (*args));
+ print_z_candidates (candidates);
+ }
result = error_mark_node;
}
/* Since cand->fn will be a type, not a function, for a conversion
DECL_NAME here. */
else if (TREE_CODE (cand->fn) == FUNCTION_DECL
&& DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
- result = build_over_call (cand, LOOKUP_NORMAL);
+ result = build_over_call (cand, LOOKUP_NORMAL, complain);
else
{
- obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1);
+ obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
+ complain);
obj = convert_from_reference (obj);
- result = build_function_call (obj, args);
+ result = cp_build_function_call_vec (obj, args, complain);
}
}
t1,
e1,
/*c_cast_p=*/false,
- LOOKUP_NO_TEMP_BIND);
+ LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING);
if (conv)
return conv;
}
converted to the type that expression E2 would have if E2 were
converted to an rvalue (or the type it has, if E2 is an rvalue). */
return implicit_conversion (t2, t1, e1, /*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ LOOKUP_IMPLICIT);
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
arguments to the conditional expression. */
tree
-build_conditional_expr (tree arg1, tree arg2, tree arg3)
+build_conditional_expr (tree arg1, tree arg2, tree arg3,
+ tsubst_flags_t complain)
{
tree arg2_type;
tree arg3_type;
calculated only once. */
if (!arg2)
{
- if (pedantic)
- pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
+ if (complain & tf_error)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ forbids omitting the middle term of a ?: expression");
/* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */
if (real_lvalue_p (arg1))
/* [expr.cond]
- The first expr ession is implicitly converted to bool (clause
+ The first expression is implicitly converted to bool (clause
_conv_). */
- arg1 = perform_implicit_conversion (boolean_type_node, arg1);
+ 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. */
result_type = void_type_node;
else
{
- if (VOID_TYPE_P (arg2_type))
- error ("second operand to the conditional operator "
- "is of type %<void%>, "
- "but the third operand is neither a throw-expression "
- "nor of type %<void%>");
- else
- error ("third operand to the conditional operator "
- "is of type %<void%>, "
- "but the second operand is neither a throw-expression "
- "nor of type %<void%>");
+ if (complain & tf_error)
+ {
+ if (VOID_TYPE_P (arg2_type))
+ error ("second operand to the conditional operator "
+ "is of type %<void%>, "
+ "but the third operand is neither a throw-expression "
+ "nor of type %<void%>");
+ else
+ error ("third operand to the conditional operator "
+ "is of type %<void%>, "
+ "but the second operand is neither a throw-expression "
+ "nor of type %<void%>");
+ }
return error_mark_node;
}
}
else if (conv2 && (!conv2->bad_p || !conv3))
{
- arg2 = convert_like (conv2, arg2);
+ arg2 = convert_like (conv2, arg2, complain);
arg2 = convert_from_reference (arg2);
arg2_type = TREE_TYPE (arg2);
/* Even if CONV2 is a valid conversion, the result of the
}
else if (conv3 && (!conv3->bad_p || !conv2))
{
- arg3 = convert_like (conv3, arg3);
+ arg3 = convert_like (conv3, arg3, complain);
arg3 = convert_from_reference (arg3);
arg3_type = TREE_TYPE (arg3);
if (error_operand_p (arg3))
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;
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
- op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
- print_z_candidates (candidates);
+ if (complain & tf_error)
+ {
+ op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
+ print_z_candidates (candidates);
+ }
return error_mark_node;
}
cand = tourney (candidates);
if (!cand)
{
- op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
- print_z_candidates (candidates);
+ if (complain & tf_error)
+ {
+ op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
+ print_z_candidates (candidates);
+ }
return error_mark_node;
}
the converted operands are used in place of the original
operands for the remainder of this section. */
conv = cand->convs[0];
- arg1 = convert_like (conv, arg1);
+ arg1 = convert_like (conv, arg1, complain);
conv = cand->convs[1];
- arg2 = convert_like (conv, arg2);
+ arg2 = convert_like (conv, arg2, complain);
+ arg2_type = TREE_TYPE (arg2);
conv = cand->convs[2];
- arg3 = convert_like (conv, arg3);
+ 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; the usual arithmetic conversions are performed to bring
them to a common type, and the result is of that type. */
else if ((ARITHMETIC_TYPE_P (arg2_type)
- || TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+ || UNSCOPED_ENUM_P (arg2_type))
&& (ARITHMETIC_TYPE_P (arg3_type)
- || TREE_CODE (arg3_type) == ENUMERAL_TYPE))
+ || UNSCOPED_ENUM_P (arg3_type)))
{
/* In this case, there is always a common type. */
result_type = type_after_usual_arithmetic_conversions (arg2_type,
if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& TREE_CODE (arg3_type) == ENUMERAL_TYPE)
- warning (0, "enumeral mismatch in conditional expression: %qT vs %qT",
- arg2_type, arg3_type);
+ {
+ if (complain & tf_warning)
+ warning (0,
+ "enumeral mismatch in conditional expression: %qT vs %qT",
+ arg2_type, arg3_type);
+ }
else if (extra_warnings
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type, type_promotes_to (arg3_type)))))
- warning (0, "enumeral and non-enumeral type in conditional expression");
+ {
+ if (complain & tf_warning)
+ warning (0,
+ "enumeral and non-enumeral type in conditional expression");
+ }
- arg2 = perform_implicit_conversion (result_type, arg2);
- arg3 = perform_implicit_conversion (result_type, arg3);
+ arg2 = perform_implicit_conversion (result_type, arg2, complain);
+ arg3 = perform_implicit_conversion (result_type, arg3, complain);
}
/* [expr.cond]
|| (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
{
result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
- arg3, "conditional expression");
+ arg3, "conditional expression",
+ complain);
if (result_type == error_mark_node)
return error_mark_node;
- arg2 = perform_implicit_conversion (result_type, arg2);
- arg3 = perform_implicit_conversion (result_type, arg3);
+ arg2 = perform_implicit_conversion (result_type, arg2, complain);
+ arg3 = perform_implicit_conversion (result_type, arg3, complain);
}
if (!result_type)
{
- error ("operands to ?: have different types %qT and %qT",
- arg2_type, arg3_type);
+ if (complain & tf_error)
+ error ("operands to ?: have different types %qT and %qT",
+ arg2_type, arg3_type);
return error_mark_node;
}
/* 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. 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. */
+ without any implicit object parameter. This may change ARGS. 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, tree args,
+add_candidates (tree fns, const VEC(tree,gc) *args,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates)
{
tree ctype;
- tree non_static_args;
+ VEC(tree,gc) *non_static_args;
+ tree first_arg;
ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
/* Delay creating the implicit this parameter until it is needed. */
- non_static_args = NULL_TREE;
+ non_static_args = NULL;
+ first_arg = NULL_TREE;
while (fns)
{
tree fn;
- tree fn_args;
+ tree fn_first_arg;
+ const VEC(tree,gc) *fn_args;
fn = OVL_CURRENT (fns);
/* Figure out which set of arguments to use. */
{
/* If this function is a non-static member, prepend the implicit
object parameter. */
- if (!non_static_args)
- non_static_args = tree_cons (NULL_TREE,
- build_this (TREE_VALUE (args)),
- TREE_CHAIN (args));
+ if (non_static_args == NULL)
+ {
+ unsigned int ix;
+ tree arg;
+
+ non_static_args = 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);
+ }
+ if (first_arg == NULL_TREE)
+ first_arg = build_this (VEC_index (tree, args, 0));
+ fn_first_arg = first_arg;
fn_args = non_static_args;
}
else
- /* Otherwise, just use the list of arguments provided. */
- fn_args = args;
+ {
+ /* Otherwise, just use the list of arguments provided. */
+ fn_first_arg = NULL_TREE;
+ fn_args = args;
+ }
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (candidates,
fn,
ctype,
explicit_targs,
+ fn_first_arg,
fn_args,
NULL_TREE,
access_path,
add_function_candidate (candidates,
fn,
ctype,
+ fn_first_arg,
fn_args,
access_path,
conversion_path,
}
}
+/* 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)
+ 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;
- tree arglist, fnname;
+ VEC(tree,gc) *arglist;
+ tree fnname;
tree args[3];
tree result = NULL_TREE;
bool result_valid_p = false;
enum tree_code code2 = NOP_EXPR;
+ enum tree_code code_orig_arg1 = ERROR_MARK;
+ enum tree_code code_orig_arg2 = ERROR_MARK;
conversion *conv;
void *p;
bool strict_p;
bool any_viable_p;
- bool expl_eq_arg1 = false;
if (error_operand_p (arg1)
|| error_operand_p (arg2)
gcc_unreachable ();
case CALL_EXPR:
- return build_object_call (arg1, arg2);
+ /* Use build_op_call instead. */
+ gcc_unreachable ();
case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
- if (COMPARISON_CLASS_P (arg1))
- expl_eq_arg1 = true;
+ /* These are saved for the sake of warn_logical_operator. */
+ code_orig_arg1 = TREE_CODE (arg1);
+ code_orig_arg2 = TREE_CODE (arg2);
+
default:
break;
}
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;
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
arg2 = integer_zero_node;
- arglist = NULL_TREE;
- if (arg3)
- arglist = tree_cons (NULL_TREE, arg3, arglist);
- if (arg2)
- arglist = tree_cons (NULL_TREE, arg2, arglist);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
+ arglist = VEC_alloc (tree, gc, 3);
+ VEC_quick_push (tree, arglist, arg1);
+ if (arg2 != NULL_TREE)
+ VEC_quick_push (tree, arglist, arg2);
+ if (arg3 != NULL_TREE)
+ VEC_quick_push (tree, arglist, arg3);
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
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);
{
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- /* Look for an `operator++ (int)'. If they didn't have
- one, then we fall back to the old way of doing things. */
+ /* Don't try anything fancy if we're not allowed to produce
+ errors. */
+ if (!(complain & tf_error))
+ return error_mark_node;
+
+ /* 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)
- pedwarn ("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
code = PREDECREMENT_EXPR;
result = build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE,
- overloaded_p);
+ overloaded_p, complain);
break;
/* The caller will deal with these. */
break;
default:
- if (flags & LOOKUP_COMPLAIN)
+ if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error))
{
- op_error (code, code2, arg1, arg2, arg3, "no match");
- print_z_candidates (candidates);
+ /* If one of the arguments of the operator represents
+ an invalid use of member function pointer, try to report
+ a meaningful error ... */
+ if (invalid_nonstatic_memfn_p (arg1, tf_error)
+ || invalid_nonstatic_memfn_p (arg2, tf_error)
+ || invalid_nonstatic_memfn_p (arg3, tf_error))
+ /* We displayed the error message. */;
+ else
+ {
+ /* ... Otherwise, report the more generic
+ "no matching operator found" error */
+ op_error (code, code2, arg1, arg2, arg3, "no match");
+ print_z_candidates (candidates);
+ }
}
result = error_mark_node;
break;
cand = tourney (candidates);
if (cand == 0)
{
- if (flags & LOOKUP_COMPLAIN)
+ if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error))
{
op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
print_z_candidates (candidates);
if (overloaded_p)
*overloaded_p = true;
- if (resolve_args (arglist) == error_mark_node)
+ if (resolve_args (arglist) == NULL)
result = error_mark_node;
else
- result = build_over_call (cand, LOOKUP_NORMAL);
+ result = build_over_call (cand, LOOKUP_NORMAL, complain);
}
else
{
/* Give any warnings we noticed during overload resolution. */
- if (cand->warnings)
+ if (cand->warnings && (complain & tf_warning))
{
struct candidate_warning *w;
for (w = cand->warnings; w; w = w->next)
if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
&& (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
- != TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))
+ && (complain & tf_warning))
{
- warning (0, "comparison between %q#T and %q#T",
+ warning (OPT_Wenum_compare,
+ "comparison between %q#T and %q#T",
TREE_TYPE (arg1), TREE_TYPE (arg2));
}
break;
conv = cand->convs[0];
if (conv->kind == ck_ref_bind)
conv = conv->u.next;
- arg1 = convert_like (conv, arg1);
+ arg1 = convert_like (conv, arg1, complain);
+
if (arg2)
{
+ /* We need to call warn_logical_operator before
+ converting arg2 to a boolean_type. */
+ if (complain & tf_warning)
+ warn_logical_operator (input_location, code, boolean_type_node,
+ code_orig_arg1, arg1,
+ code_orig_arg2, arg2);
+
conv = cand->convs[1];
if (conv->kind == ck_ref_bind)
conv = conv->u.next;
- arg2 = convert_like (conv, arg2);
+ arg2 = convert_like (conv, arg2, complain);
}
if (arg3)
{
conv = cand->convs[2];
if (conv->kind == ck_ref_bind)
conv = conv->u.next;
- arg3 = convert_like (conv, arg3);
+ arg3 = convert_like (conv, arg3, complain);
}
- if (!expl_eq_arg1)
- {
- warn_logical_operator (code, arg1, arg2);
- expl_eq_arg1 = true;
- }
}
}
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 build_modify_expr (arg1, code2, arg2);
+ return cp_build_modify_expr (arg1, code2, arg2, complain);
case INDIRECT_REF:
- return build_indirect_ref (arg1, "unary *");
+ return cp_build_indirect_ref (arg1, "unary *", complain);
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
- if (!expl_eq_arg1)
- warn_logical_operator (code, arg1, arg2);
+ warn_logical_operator (input_location, code, boolean_type_node,
+ code_orig_arg1, arg1, code_orig_arg2, arg2);
+ /* Fall through. */
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
- return cp_build_binary_op (code, arg1, arg2);
+ return cp_build_binary_op (input_location, code, arg1, arg2, complain);
case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
case POSTDECREMENT_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- return build_unary_op (code, arg1, candidates != 0);
+ return cp_build_unary_op (code, arg1, candidates != 0, complain);
case ARRAY_REF:
- return build_array_ref (arg1, arg2);
-
- case COND_EXPR:
- return build_conditional_expr (arg1, arg2, arg3);
+ return build_array_ref (input_location, arg1, arg2);
case MEMBER_REF:
- return build_m_component_ref (build_indirect_ref (arg1, NULL), arg2);
+ return build_m_component_ref (cp_build_indirect_ref (arg1, NULL,
+ complain),
+ arg2);
/* The caller will deal with these. */
case ADDR_EXPR:
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)
- {
- 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;
- }
- /* 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;
+ error ("non-placement deallocation function %q+D", fn);
+ error ("selected for placement delete");
}
-
- /* 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)
{
}
else
{
- tree args;
- if (pass == 0)
- args = tree_cons (NULL_TREE, addr, NULL_TREE);
- else
- args = tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, size));
- return build_function_call (fn, args);
+ tree ret;
+ VEC(tree,gc) *args = VEC_alloc (tree, gc, 2);
+ VEC_quick_push (tree, args, addr);
+ 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);
+ return ret;
}
}
if (alloc_fn)
{
if (!placement)
- warning (0, "no corresponding deallocation function for `%D'",
+ warning (0, "no corresponding deallocation function for %qD",
alloc_fn);
return NULL_TREE;
}
static tree
build_temp (tree expr, tree type, int flags,
- diagnostic_fn_t *diagnostic_fn)
+ diagnostic_t *diagnostic_kind)
{
int savew, savee;
+ VEC(tree,gc) *args;
savew = warningcount, savee = errorcount;
- expr = build_special_member_call (NULL_TREE,
- complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- type, flags);
+ args = make_tree_vector_single (expr);
+ expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &args, type, flags, tf_warning_or_error);
+ release_tree_vector (args);
if (warningcount > savew)
- *diagnostic_fn = warning0;
+ *diagnostic_kind = DK_WARNING;
else if (errorcount > savee)
- *diagnostic_fn = error;
+ *diagnostic_kind = DK_ERROR;
else
- *diagnostic_fn = NULL;
+ *diagnostic_kind = DK_UNSPECIFIED;
return expr;
}
static tree
convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
int inner, bool issue_conversion_warnings,
- bool c_cast_p)
+ bool c_cast_p, tsubst_flags_t complain)
{
tree totype = convs->type;
- diagnostic_fn_t diagnostic_fn;
+ diagnostic_t diag_kind;
int flags;
if (convs->bad_p
&& convs->kind != ck_user
+ && convs->kind != ck_list
&& convs->kind != ck_ambig
- && convs->kind != ck_ref_bind)
+ && convs->kind != ck_ref_bind
+ && convs->kind != ck_rvalue
+ && convs->kind != ck_base)
{
conversion *t = convs;
+
+ /* Give a helpful error if this is bad because of excess braces. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && SCALAR_TYPE_P (totype)
+ && CONSTRUCTOR_NELTS (expr) > 0
+ && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
+ permerror (input_location, "too many braces around initializer for %qT", totype);
+
for (; t; t = convs->u.next)
{
if (t->kind == ck_user || !t->bad_p)
{
expr = convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false,
- /*c_cast_p=*/false);
+ /*c_cast_p=*/false,
+ complain);
break;
}
else if (t->kind == ck_ambig)
return convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false,
- /*c_cast_p=*/false);
+ /*c_cast_p=*/false,
+ complain);
else if (t->kind == ck_identity)
break;
}
- pedwarn ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
- if (fn)
- pedwarn (" initializing argument %P of %qD", argnum, fn);
+ if (complain & tf_error)
+ {
+ permerror (input_location, "invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
+ if (fn)
+ permerror (input_location, " initializing argument %P of %qD", argnum, fn);
+ }
+ else
+ return error_mark_node;
+
return cp_convert (totype, expr);
}
- if (issue_conversion_warnings)
+ if (issue_conversion_warnings && (complain & tf_warning))
conversion_null_warnings (totype, expr, fn, argnum);
switch (convs->kind)
tree convfn = cand->fn;
unsigned i;
+ /* 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))
+ {
+ if (complain & tf_error)
+ error ("converting to %qT from initializer list would use "
+ "explicit constructor %qD", totype, convfn);
+ else
+ return error_mark_node;
+ }
+
/* Set user_conv_p on the argument conversions, so rvalue/base
handling knows not to allow any more UDCs. */
for (i = 0; i < cand->num_convs; ++i)
cand->convs[i]->user_conv_p = true;
- expr = build_over_call (cand, LOOKUP_NORMAL);
+ expr = build_over_call (cand, LOOKUP_NORMAL, complain);
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
if (DECL_CONSTRUCTOR_P (convfn))
- expr = build_cplus_new (totype, expr);
-
- /* The result of the call is then used to direct-initialize the object
- that is the destination of the copy-initialization. [dcl.init]
-
- Note that this step is not reflected in the conversion sequence;
- it affects the semantics when we actually perform the
- conversion, but is not considered during overload resolution.
-
- If the target is a class, that means call a ctor. */
- if (IS_AGGR_TYPE (totype)
- && (inner >= 0 || !lvalue_p (expr)))
{
- expr = (build_temp
- (expr, totype,
- /* Core issue 84, now a DR, says that we don't
- allow UDCs for these args (which deliberately
- breaks copy-init of an auto_ptr<Base> from an
- auto_ptr<Derived>). */
- LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION,
- &diagnostic_fn));
-
- if (diagnostic_fn)
- {
- if (fn)
- diagnostic_fn
- (" initializing argument %P of %qD from result of %qD",
- argnum, fn, convfn);
- else
- diagnostic_fn
- (" initializing temporary from result of %qD", convfn);
- }
expr = build_cplus_new (totype, expr);
+
+ /* Remember that this was list-initialization. */
+ if (convs->check_narrowing)
+ TARGET_EXPR_LIST_INIT_P (expr) = true;
}
+
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, tf_warning_or_error);
+ expr = instantiate_type (totype, expr, complain);
/* Convert a constant to its underlying value, unless we are
about to bind it to a reference, in which case we need to
leave it as an lvalue. */
if (inner >= 0)
{
expr = decl_constant_value (expr);
- if (expr == null_node && INTEGRAL_TYPE_P (totype))
+ if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not
want to warn about uses of EXPR as an integer, rather than
as a pointer. */
return build_user_type_conversion
(totype, convs->u.expr, LOOKUP_NORMAL);
+ case ck_list:
+ {
+ /* Conversion to std::initializer_list<T>. */
+ tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0);
+ tree new_ctor = build_constructor (init_list_type_node, NULL);
+ unsigned len = CONSTRUCTOR_NELTS (expr);
+ tree array, val;
+ VEC(tree,gc) *parms;
+ unsigned ix;
+
+ /* Convert all the elements. */
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
+ {
+ tree sub = convert_like_real (convs->u.list[ix], val, fn, argnum,
+ 1, false, false, complain);
+ if (sub == error_mark_node)
+ return sub;
+ check_narrowing (TREE_TYPE (sub), val);
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub);
+ }
+ /* Build up the array. */
+ elttype = cp_build_qualified_type
+ (elttype, TYPE_QUALS (elttype) | TYPE_QUAL_CONST);
+ array = build_array_of_n_type (elttype, len);
+ array = finish_compound_literal (array, new_ctor);
+
+ parms = make_tree_vector ();
+ VEC_safe_push (tree, gc, parms, decay_conversion (array));
+ VEC_safe_push (tree, gc, parms, size_int (len));
+ /* Call the private constructor. */
+ push_deferring_access_checks (dk_no_check);
+ new_ctor = build_special_member_call
+ (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain);
+ release_tree_vector (parms);
+ pop_deferring_access_checks ();
+ return build_cplus_new (totype, new_ctor);
+ }
+
+ case ck_aggr:
+ return get_target_expr (digest_init (totype, expr));
+
default:
break;
};
expr = convert_like_real (convs->u.next, expr, fn, argnum,
convs->kind == ck_ref_bind ? -1 : 1,
convs->kind == ck_ref_bind ? issue_conversion_warnings : false,
- c_cast_p);
+ c_cast_p,
+ complain);
if (expr == error_mark_node)
return error_mark_node;
{
case ck_rvalue:
expr = convert_bitfield_to_declared_type (expr);
- if (! IS_AGGR_TYPE (totype))
+ if (! MAYBE_CLASS_TYPE_P (totype))
return expr;
/* Else fall through. */
case ck_base:
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
/* Build an expression for `*((base*) &expr)'. */
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ 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 = build_indirect_ref (expr, "implicit conversion");
+ expr = cp_build_indirect_ref (expr, "implicit conversion", complain);
return expr;
}
flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
if (convs->user_conv_p)
/* This conversion is being done in the context of a user-defined
- conversion, so don't allow any more. */
+ conversion (i.e. the second step of copy-initialization), so
+ don't allow any more. */
flags |= LOOKUP_NO_CONVERSION;
- expr = build_temp (expr, totype, flags, &diagnostic_fn);
- if (diagnostic_fn && fn)
- diagnostic_fn (" initializing argument %P of %qD", argnum, fn);
+ expr = build_temp (expr, totype, flags, &diag_kind);
+ if (diag_kind && fn)
+ {
+ if ((complain & tf_error))
+ emit_diagnostic (diag_kind, input_location, 0,
+ " initializing argument %P of %qD", argnum, fn);
+ else if (diag_kind == DK_ERROR)
+ return error_mark_node;
+ }
return build_cplus_new (totype, expr);
case ck_ref_bind:
{
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
that need temporaries, even when their types are reference
compatible with the type of reference being bound, so the
- upcoming call to build_unary_op (ADDR_EXPR, expr, ...)
+ upcoming call to cp_build_unary_op (ADDR_EXPR, expr, ...)
doesn't fail. */
if (convs->need_temporary_p
|| TREE_CODE (expr) == CONSTRUCTOR
if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))
&& !TYPE_REF_IS_RVALUE (ref_type))
{
- /* If the reference is volatile or non-const, we
- cannot create a temporary. */
- if (lvalue & clk_bitfield)
- error ("cannot bind bitfield %qE to %qT",
- expr, ref_type);
- else if (lvalue & clk_packed)
- error ("cannot bind packed field %qE to %qT",
- expr, ref_type);
- else
- error ("cannot bind rvalue %qE to %qT", expr, ref_type);
+ if (complain & tf_error)
+ {
+ /* If the reference is volatile or non-const, we
+ cannot create a temporary. */
+ if (lvalue & clk_bitfield)
+ error ("cannot bind bitfield %qE to %qT",
+ expr, ref_type);
+ else if (lvalue & clk_packed)
+ error ("cannot bind packed field %qE to %qT",
+ expr, ref_type);
+ else
+ error ("cannot bind rvalue %qE to %qT", expr, ref_type);
+ }
return error_mark_node;
}
/* If the source is a packed field, and we must use a copy
&& CLASS_TYPE_P (type)
&& !TYPE_HAS_TRIVIAL_INIT_REF (type))
{
- error ("cannot bind packed field %qE to %qT",
- expr, ref_type);
+ if (complain & tf_error)
+ error ("cannot bind packed field %qE to %qT",
+ expr, ref_type);
return error_mark_node;
}
if (lvalue & clk_bitfield)
- expr = convert_bitfield_to_declared_type (expr);
+ {
+ expr = convert_bitfield_to_declared_type (expr);
+ expr = fold_convert (type, expr);
+ }
expr = build_target_expr_with_type (expr, type);
}
/* Take the address of the thing to which we will bind the
reference. */
- expr = build_unary_op (ADDR_EXPR, expr, 1);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, 1, complain);
if (expr == error_mark_node)
return error_mark_node;
break;
}
- if (issue_conversion_warnings)
+ if (convs->check_narrowing)
+ check_narrowing (totype, expr);
+
+ if (issue_conversion_warnings && (complain & tf_warning))
expr = convert_and_check (totype, expr);
else
expr = convert (totype, expr);
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 (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))
+ 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 = build_indirect_ref (expr, NULL);
+ expr = cp_build_indirect_ref (expr, 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
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
- arg = break_out_target_exprs (arg);
+ /* Due to:
+
+ [dcl.fct.default]
+
+ The names in the expression are bound, and the semantic
+ constraints are checked, at the point where the default
+ expressions appears.
+ we must not perform access checks here. */
+ push_deferring_access_checks (dk_no_check);
+ arg = break_out_target_exprs (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
{
arg = digest_init (type, arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", fn, parmnum);
+ "default argument", fn, parmnum,
+ tf_warning_or_error);
}
else
{
if (!CONSTANT_CLASS_P (arg))
arg = unshare_expr (arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", fn, parmnum);
+ "default argument", fn, parmnum,
+ tf_warning_or_error);
arg = convert_for_arg_passing (type, arg);
}
+ pop_deferring_access_checks();
VEC_pop (tree, default_arg_context);
case BUILT_IN_CLASSIFY_TYPE:
case BUILT_IN_CONSTANT_P:
case BUILT_IN_NEXT_ARG:
- case BUILT_IN_STDARG_START:
case BUILT_IN_VA_START:
return true;
bitmask of various LOOKUP_* flags which apply to the call itself. */
static tree
-build_over_call (struct z_candidate *cand, int flags)
+build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
tree fn = cand->fn;
- tree args = cand->args;
+ const VEC(tree,gc) *args = cand->args;
+ tree first_arg = cand->first_arg;
conversion **convs = cand->convs;
conversion *conv;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
int parmlen;
- tree arg, val;
+ tree val;
int i = 0;
int j = 0;
+ unsigned int arg_index = 0;
int is_method = 0;
int nargs;
tree *argarray;
+ bool already_used = false;
/* In a template, there is no need to perform all of the work that
is normally done. We are only interested in the type of the call
{
tree expr;
tree return_type;
+ const tree *argarray;
+ unsigned int nargs;
+
return_type = TREE_TYPE (TREE_TYPE (fn));
- expr = build_call_list (return_type, fn, args);
+ nargs = VEC_length (tree, args);
+ if (first_arg == NULL_TREE)
+ argarray = VEC_address (tree, CONST_CAST (VEC(tree,gc) *, args));
+ else
+ {
+ tree *alcarray;
+ unsigned int ix;
+ tree arg;
+
+ ++nargs;
+ alcarray = XALLOCAVEC (tree, nargs);
+ alcarray[0] = first_arg;
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ alcarray[ix + 1] = arg;
+ argarray = alcarray;
+ }
+ 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))
joust (cand, w->loser, 1);
}
+ /* Make =delete work with SFINAE. */
+ if (DECL_DELETED_FN (fn) && !(complain & tf_error))
+ return error_mark_node;
+
if (DECL_FUNCTION_MEMBER_P (fn))
{
/* If FN is a template function, two cases must be considered.
perform_or_defer_access_check (cand->access_path, fn, fn);
}
- if (args && TREE_CODE (args) != TREE_LIST)
- args = build_tree_list (NULL_TREE, args);
- arg = args;
-
/* Find maximum size of vector to hold converted arguments. */
parmlen = list_length (parm);
- nargs = list_length (args);
+ nargs = VEC_length (tree, args) + (first_arg != NULL_TREE ? 1 : 0);
if (parmlen > nargs)
nargs = parmlen;
argarray = (tree *) alloca (nargs * sizeof (tree));
resolution, and must be of the proper type. */
if (DECL_CONSTRUCTOR_P (fn))
{
- argarray[j++] = TREE_VALUE (arg);
- arg = TREE_CHAIN (arg);
+ if (first_arg != NULL_TREE)
+ {
+ argarray[j++] = first_arg;
+ first_arg = NULL_TREE;
+ }
+ else
+ {
+ argarray[j++] = VEC_index (tree, args, arg_index);
+ ++arg_index;
+ }
parm = TREE_CHAIN (parm);
/* We should never try to call the abstract constructor. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn));
if (DECL_HAS_VTT_PARM_P (fn))
{
- argarray[j++] = TREE_VALUE (arg);
- arg = TREE_CHAIN (arg);
+ argarray[j++] = VEC_index (tree, args, arg_index);
+ ++arg_index;
parm = TREE_CHAIN (parm);
}
}
else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
{
tree parmtype = TREE_VALUE (parm);
- tree argtype = TREE_TYPE (TREE_VALUE (arg));
+ tree arg = (first_arg != NULL_TREE
+ ? first_arg
+ : VEC_index (tree, args, arg_index));
+ tree argtype = TREE_TYPE (arg);
tree converted_arg;
tree base_binfo;
if (convs[i]->bad_p)
- pedwarn ("passing %qT as %<this%> argument of %q#D discards qualifiers",
- TREE_TYPE (argtype), fn);
+ {
+ if (complain & tf_error)
+ permerror (input_location, "passing %qT as %<this%> argument of %q#D discards qualifiers",
+ TREE_TYPE (argtype), fn);
+ else
+ return error_mark_node;
+ }
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
X is called for an object that is not of type X, or of a type
/* Convert to the base in which the function was declared. */
gcc_assert (cand->conversion_path != NULL_TREE);
converted_arg = build_base_path (PLUS_EXPR,
- TREE_VALUE (arg),
+ arg,
cand->conversion_path,
1);
/* Check that the base class is accessible. */
argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm);
- arg = TREE_CHAIN (arg);
+ if (first_arg != NULL_TREE)
+ first_arg = NULL_TREE;
+ else
+ ++arg_index;
++i;
is_method = 1;
}
- for (; arg && parm;
- parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
+ gcc_assert (first_arg == NULL_TREE);
+ for (; arg_index < VEC_length (tree, args) && parm;
+ parm = TREE_CHAIN (parm), ++arg_index, ++i)
{
tree type = TREE_VALUE (parm);
&& !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);
+
+ if (!is_std_init_list (non_reference (TREE_TYPE (patparm))))
+ {
+ 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, TREE_VALUE (arg), fn, i - is_method);
+ (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
+ complain);
val = convert_for_arg_passing (type, val);
- argarray[j++] = val;
+ if (val == error_mark_node)
+ return error_mark_node;
+ else
+ argarray[j++] = val;
}
/* Default arguments */
TREE_PURPOSE (parm),
fn, i - is_method);
/* Ellipsis */
- for (; arg; arg = TREE_CHAIN (arg))
+ for (; arg_index < VEC_length (tree, args); ++arg_index)
{
- tree a = TREE_VALUE (arg);
+ tree a = VEC_index (tree, args, arg_index);
if (magic_varargs_p (fn))
/* Do no conversions for magic varargs. */;
else
|| DECL_MOVE_CONSTRUCTOR_P (fn)))
{
tree targ;
- arg = argarray[num_artificial_parms_for (fn)];
+ tree arg = argarray[num_artificial_parms_for (fn)];
+ tree fa;
/* Pull out the real argument, disregarding const-correctness. */
targ = arg;
- while (TREE_CODE (targ) == NOP_EXPR
- || TREE_CODE (targ) == NON_LVALUE_EXPR
- || TREE_CODE (targ) == CONVERT_EXPR)
+ while (CONVERT_EXPR_P (targ)
+ || TREE_CODE (targ) == NON_LVALUE_EXPR)
targ = TREE_OPERAND (targ, 0);
if (TREE_CODE (targ) == ADDR_EXPR)
{
if (targ)
arg = targ;
else
- arg = build_indirect_ref (arg, 0);
+ arg = cp_build_indirect_ref (arg, 0, complain);
+ if (TREE_CODE (arg) == TARGET_EXPR
+ && TARGET_EXPR_LIST_INIT_P (arg))
+ {
+ /* Copy-list-initialization doesn't require the copy constructor
+ to be defined. */
+ }
/* [class.copy]: the copy constructor is implicitly defined even if
the implementation elided its use. */
- if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
- mark_used (fn);
+ else if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
+ {
+ mark_used (fn);
+ already_used = true;
+ }
/* If we're creating a temp and we already have one, don't create a
new one. If we're not creating a temp but we get one, use
INIT_EXPR to collapse the temp into our target. Otherwise, if the
ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
temp or an INIT_EXPR otherwise. */
- if (integer_zerop (TREE_VALUE (args)))
+ fa = (cand->first_arg != NULL_TREE
+ ? cand->first_arg
+ : VEC_index (tree, args, 0));
+ if (integer_zerop (fa))
{
if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
|| (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
&& !move_fn_p (fn)))
{
- tree to = stabilize_reference
- (build_indirect_ref (TREE_VALUE (args), 0));
+ tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+ complain));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
- (build_indirect_ref (argarray[0], 0));
+ (cp_build_indirect_ref (argarray[0], 0, complain));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
+ tree arg = argarray[1];
- arg = argarray[1];
if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
- arg = build_indirect_ref (arg, 0);
+ arg = cp_build_indirect_ref (arg, 0, complain);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
}
else
{
/* We must only copy the non-tail padding parts.
- Use __builtin_memcpy for the bitwise copy. */
+ Use __builtin_memcpy for the bitwise copy.
+ FIXME fix 22488 so we can go back to using MODIFY_EXPR
+ instead of an explicit call to memcpy. */
tree arg0, arg1, arg2, t;
+ tree test = NULL_TREE;
arg2 = TYPE_SIZE_UNIT (as_base);
arg1 = arg;
- arg0 = build_unary_op (ADDR_EXPR, to, 0);
+ arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain);
+
+ if (!can_trust_pointer_alignment ())
+ {
+ /* 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. Otherwise it is
+ expanded as a block move, which should be safe. */
+ arg0 = save_expr (arg0);
+ arg1 = save_expr (arg1);
+ test = build2 (EQ_EXPR, boolean_type_node, arg0, arg1);
+ }
t = implicit_built_in_decls[BUILT_IN_MEMCPY];
t = build_call_n (t, 3, arg0, arg1, arg2);
t = convert (TREE_TYPE (arg0), t);
- val = build_indirect_ref (t, 0);
+ if (test)
+ t = build3 (COND_EXPR, TREE_TYPE (t), test, arg0, t);
+ val = cp_build_indirect_ref (t, 0, complain);
+ TREE_NO_WARNING (val) = 1;
}
return val;
}
- mark_used (fn);
+ if (!already_used)
+ mark_used (fn);
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
/* Warn about deprecated virtual functions now, since we're about
to throw away the decl. */
if (TREE_DEPRECATED (fn))
- warn_deprecated_use (fn);
+ warn_deprecated_use (fn, NULL_TREE);
argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
if (TREE_SIDE_EFFECTS (argarray[0]))
fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
- else if (DECL_INLINE (fn))
- fn = inline_conversion (fn);
else
fn = build_addr_func (fn);
&& cfun)
cp_function_chain->can_throw = 1;
+ /* Check that arguments to builtin functions match the expectations. */
+ if (fndecl
+ && DECL_BUILT_IN (fndecl)
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
+ && !check_builtin_function_arguments (fndecl, nargs, argarray))
+ return error_mark_node;
+
/* Some built-in function calls will be evaluated at compile-time in
fold (). */
fn = fold_if_not_in_template (fn);
if (fn == error_mark_node)
return error_mark_node;
- if (IS_AGGR_TYPE (TREE_TYPE (fn)))
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn);
return convert_from_reference (fn);
}
/* 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 (build_indirect_ref (instance, 0),
+ klass_ref = build_vtbl_ref (cp_build_indirect_ref (instance, 0,
+ tf_warning_or_error),
integer_zero_node);
/* Get the java.lang.Class pointer for the interface being called. */
/* Build a call to a constructor, destructor, or an assignment
operator for INSTANCE, an expression with class type. NAME
- indicates the special member function to call; ARGS are the
- arguments. BINFO indicates the base of INSTANCE that is to be
- passed as the `this' parameter to the member function called.
+ indicates the special member function to call; *ARGS are the
+ arguments. ARGS may be NULL. This may change ARGS. BINFO
+ indicates the base of INSTANCE that is to be passed as the `this'
+ parameter to the member function called.
FLAGS are the LOOKUP_* flags to use when processing the call.
store the newly constructed object into a VAR_DECL. */
tree
-build_special_member_call (tree instance, tree name, tree args,
- tree binfo, int flags)
+build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
+ tree binfo, int flags, tsubst_flags_t complain)
{
tree fns;
/* The type of the subobject to be constructed or destroyed. */
tree class_type;
+ VEC(tree,gc) *allocated = NULL;
+ tree ret;
gcc_assert (name == complete_ctor_identifier
|| name == base_ctor_identifier
if (name == complete_dtor_identifier
|| name == base_dtor_identifier
|| name == deleting_dtor_identifier)
- gcc_assert (args == NULL_TREE);
+ gcc_assert (args == NULL || VEC_empty (tree, *args));
/* Convert to the base class, if necessary. */
if (!same_type_ignoring_top_level_qualifiers_p
sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt,
BINFO_SUBVTT_INDEX (binfo));
- args = tree_cons (NULL_TREE, sub_vtt, args);
+ if (args == NULL)
+ {
+ allocated = make_tree_vector ();
+ args = &allocated;
+ }
+
+ VEC_safe_insert (tree, gc, *args, 0, sub_vtt);
}
- return build_new_method_call (instance, fns, args,
- TYPE_BINFO (BINFO_TYPE (binfo)),
- flags, /*fn=*/NULL);
+ ret = build_new_method_call (instance, fns, args,
+ TYPE_BINFO (BINFO_TYPE (binfo)),
+ flags, /*fn=*/NULL,
+ complain);
+
+ if (allocated != NULL)
+ release_tree_vector (allocated);
+
+ return ret;
}
/* Return the NAME, as a C string. The NAME indicates a function that
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
pretty_name
- = CONST_CAST (char *, IDENTIFIER_POINTER (constructor_name (type)));
+ = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type))));
/* For a destructor, add the '~'. */
if (name == complete_dtor_identifier
|| name == base_dtor_identifier
else if (IDENTIFIER_TYPENAME_P (name))
{
pretty_name = concat ("operator ",
- type_as_string (TREE_TYPE (name),
- TFF_PLAIN_IDENTIFIER),
+ type_as_string_translate (TREE_TYPE (name),
+ TFF_PLAIN_IDENTIFIER),
NULL);
/* Remember that we need to free the memory allocated. */
*free_p = true;
}
else
- pretty_name = CONST_CAST (char *, IDENTIFIER_POINTER (name));
+ pretty_name = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (name)));
return pretty_name;
}
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
- be set, upon return, to the function called. */
+ be set, upon return, to the function called. ARGS may be NULL.
+ This may change ARGS. */
tree
-build_new_method_call (tree instance, tree fns, tree args,
+build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
tree conversion_path, int flags,
- tree *fn_p)
+ tree *fn_p, tsubst_flags_t complain)
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
tree basetype = NULL_TREE;
tree access_binfo;
tree optype;
- tree mem_args = NULL_TREE, instance_ptr;
+ tree first_mem_arg = NULL_TREE;
+ tree instance_ptr;
tree name;
- tree user_args;
+ bool skip_first_for_error;
+ VEC(tree,gc) *user_args;
tree call;
tree fn;
tree class_type;
bool any_viable_p;
tree orig_instance;
tree orig_fns;
- tree orig_args;
+ VEC(tree,gc) *orig_args = NULL;
void *p;
gcc_assert (instance != NULL_TREE);
*fn_p = NULL_TREE;
if (error_operand_p (instance)
- || error_operand_p (fns)
- || args == error_mark_node)
+ || error_operand_p (fns))
return error_mark_node;
if (!BASELINK_P (fns))
{
- error ("call to non-function %qD", fns);
+ if (complain & tf_error)
+ error ("call to non-function %qD", fns);
return error_mark_node;
}
orig_instance = instance;
orig_fns = fns;
- orig_args = args;
/* Dismantle the baselink to collect all the information we need. */
if (!conversion_path)
if (processing_template_decl)
{
+ orig_args = args == NULL ? NULL : make_tree_vector_copy (*args);
instance = build_non_dependent_expr (instance);
- args = build_non_dependent_args (orig_args);
- }
-
- /* The USER_ARGS are the arguments we will display to users if an
- error occurs. The USER_ARGS should not include any
- compiler-generated arguments. The "this" pointer hasn't been
- added yet. However, we must remove the VTT pointer if this is a
- call to a base-class constructor or destructor. */
- user_args = args;
+ if (args != NULL)
+ make_args_non_dependent (*args);
+ }
+
+ /* 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 hasn't been added yet. However, we must remove the VTT
+ 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
/* Remove the VTT pointer, if present. */
if ((name == base_ctor_identifier || name == base_dtor_identifier)
&& CLASSTYPE_VBASECLASSES (basetype))
- user_args = TREE_CHAIN (user_args);
+ skip_first_for_error = true;
}
/* Process the argument list. */
- args = resolve_args (args);
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
instance_ptr = build_this (instance);
if (DECL_DESTRUCTOR_P (fn))
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. */
+ 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))
+ {
+ gcc_assert (VEC_length (tree, *args) == 1);
+ *args = ctor_to_vec (VEC_index (tree, *args, 0));
+ }
+
class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
- mem_args = tree_cons (NULL_TREE, instance_ptr, args);
+ 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))
{
tree t = OVL_CURRENT (fn);
- tree this_arglist;
+ tree this_first_arg;
/* We can end up here for copy-init of same or base class. */
if ((flags & LOOKUP_ONLYCONVERTING)
continue;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_arglist = mem_args;
+ this_first_arg = first_mem_arg;
else
- this_arglist = args;
+ this_first_arg = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_DECL)
/* A member template. */
add_template_candidate (&candidates, t,
class_type,
explicit_targs,
- this_arglist, optype,
+ this_first_arg,
+ args == NULL ? NULL : *args,
+ optype,
access_binfo,
conversion_path,
flags,
else if (! template_only)
add_function_candidate (&candidates, t,
class_type,
- this_arglist,
+ this_first_arg,
+ args == NULL ? NULL : *args,
access_binfo,
conversion_path,
flags);
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
- if (!COMPLETE_TYPE_P (basetype))
- cxx_incomplete_type_error (instance_ptr, basetype);
- else
+ if (complain & tf_error)
{
- char *pretty_name;
- bool free_p;
-
- pretty_name = name_as_c_string (name, basetype, &free_p);
- error ("no matching function for call to %<%T::%s(%A)%#V%>",
- basetype, pretty_name, user_args,
- TREE_TYPE (TREE_TYPE (instance_ptr)));
- if (free_p)
- free (pretty_name);
+ if (!COMPLETE_TYPE_P (basetype))
+ cxx_incomplete_type_error (instance_ptr, basetype);
+ else
+ {
+ char *pretty_name;
+ bool free_p;
+ tree arglist;
+
+ pretty_name = name_as_c_string (name, basetype, &free_p);
+ arglist = build_tree_list_vec (user_args);
+ if (skip_first_for_error)
+ arglist = TREE_CHAIN (arglist);
+ error ("no matching function for call to %<%T::%s(%A)%#V%>",
+ basetype, pretty_name, arglist,
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
+ if (free_p)
+ free (pretty_name);
+ }
+ print_z_candidates (candidates);
}
- print_z_candidates (candidates);
call = error_mark_node;
}
else
{
char *pretty_name;
bool free_p;
+ tree arglist;
- pretty_name = name_as_c_string (name, basetype, &free_p);
- error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name,
- user_args);
- print_z_candidates (candidates);
- if (free_p)
- free (pretty_name);
+ if (complain & tf_error)
+ {
+ pretty_name = name_as_c_string (name, basetype, &free_p);
+ arglist = build_tree_list_vec (user_args);
+ if (skip_first_for_error)
+ arglist = TREE_CHAIN (arglist);
+ error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name,
+ arglist);
+ print_z_candidates (candidates);
+ if (free_p)
+ free (pretty_name);
+ }
call = error_mark_node;
}
else
&& DECL_PURE_VIRTUAL_P (fn)
&& instance == current_class_ref
&& (DECL_CONSTRUCTOR_P (current_function_decl)
- || DECL_DESTRUCTOR_P (current_function_decl)))
+ || DECL_DESTRUCTOR_P (current_function_decl))
+ && (complain & tf_warning))
/* This is not an error, it is runtime undefined
behavior. */
warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ?
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
&& is_dummy_object (instance_ptr))
{
- error ("cannot call member function %qD without object",
- fn);
+ if (complain & tf_error)
+ error ("cannot call member function %qD without object",
+ fn);
call = error_mark_node;
}
else
if (fn_p)
*fn_p = fn;
/* Build the actual CALL_EXPR. */
- call = build_over_call (cand, flags);
+ call = build_over_call (cand, flags, complain);
/* In an expression of the form `a->f()' where `f' turns
out to be a static member function, `a' is
none-the-less evaluated. */
}
if (processing_template_decl && call != error_mark_node)
- call = (build_min_non_dep_call_list
- (call,
- build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE),
- orig_args));
+ {
+ bool cast_to_void = false;
+
+ if (TREE_CODE (call) == COMPOUND_EXPR)
+ call = TREE_OPERAND (call, 1);
+ else if (TREE_CODE (call) == NOP_EXPR)
+ {
+ cast_to_void = true;
+ call = TREE_OPERAND (call, 0);
+ }
+ if (TREE_CODE (call) == INDIRECT_REF)
+ call = TREE_OPERAND (call, 0);
+ call = (build_min_non_dep_call_vec
+ (call,
+ build_min (COMPONENT_REF, TREE_TYPE (CALL_EXPR_FN (call)),
+ orig_instance, orig_fns, NULL_TREE),
+ orig_args));
+ call = convert_from_reference (call);
+ if (cast_to_void)
+ call = build_nop (void_type_node, call);
+ }
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
+ if (orig_args != NULL)
+ release_tree_vector (orig_args);
+
return call;
}
bool
is_properly_derived_from (tree derived, tree base)
{
- if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
- || !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
+ if (!CLASS_TYPE_P (derived) || !CLASS_TYPE_P (base))
return false;
/* We only allow proper derivation here. The DERIVED_FROM_P macro
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 *t2;
for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
- if (t1->kind == ck_ambig)
+ if (t1->kind == ck_ambig || t1->kind == ck_aggr)
return 0;
for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
- if (t2->kind == ck_ambig)
+ if (t2->kind == ck_ambig || t2->kind == ck_aggr)
return 0;
if (t1->cand->fn != t2->cand->fn)
}
if (deref_from_type1 != NULL_TREE
- && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))
- && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))
+ && RECORD_OR_UNION_CODE_P (TREE_CODE (deref_from_type1))
+ && RECORD_OR_UNION_CODE_P (TREE_CODE (deref_from_type2)))
{
/* This was one of the pointer or pointer-like conversions.
return -1;
}
}
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))
- && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))
+ else if (RECORD_OR_UNION_CODE_P (TREE_CODE (deref_to_type1))
+ && RECORD_OR_UNION_CODE_P (TREE_CODE (deref_to_type2)))
{
/* [over.ics.rank]
tree source = source_type (w->convs[0]);
if (! DECL_CONSTRUCTOR_P (w->fn))
source = TREE_TYPE (source);
- warning (OPT_Wconversion, "choosing %qD over %qD", w->fn, l->fn);
- warning (OPT_Wconversion, " for conversion from %qT to %qT",
- source, w->second_conv->type);
- inform (" because conversion sequence for the argument is better");
+ if (warning (OPT_Wconversion, "choosing %qD over %qD", w->fn, l->fn)
+ && warning (OPT_Wconversion, " for conversion from %qT to %qT",
+ source, w->second_conv->type))
+ {
+ inform (input_location, " because conversion sequence for the argument is better");
+ }
}
else
add_warning (w, l);
}
}
- /* If the two functions are the same (this can happen with declarations
- in multiple scopes and arg-dependent lookup), arbitrarily choose one. */
+ /* If the two function declarations represent the same function (this can
+ happen with declarations in multiple scopes and arg-dependent lookup),
+ arbitrarily choose one. But first make sure the default args we're
+ using match. */
if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& equal_functions (cand1->fn, cand2->fn))
- return 1;
+ {
+ tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (cand1->fn));
+ tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (cand2->fn));
+
+ gcc_assert (!DECL_CONSTRUCTOR_P (cand1->fn));
+
+ for (i = 0; i < len; ++i)
+ {
+ /* Don't crash if the fn is variadic. */
+ if (!parms1)
+ break;
+ parms1 = TREE_CHAIN (parms1);
+ parms2 = TREE_CHAIN (parms2);
+ }
+
+ if (off1)
+ parms1 = TREE_CHAIN (parms1);
+ else if (off2)
+ parms2 = TREE_CHAIN (parms2);
+
+ for (; parms1; ++i)
+ {
+ if (!cp_tree_equal (TREE_PURPOSE (parms1),
+ TREE_PURPOSE (parms2)))
+ {
+ if (warn)
+ {
+ permerror (input_location, "default argument mismatch in "
+ "overload resolution");
+ inform (input_location,
+ " candidate 1: %q+#F", cand1->fn);
+ inform (input_location,
+ " candidate 2: %q+#F", cand2->fn);
+ }
+ else
+ add_warning (cand1, cand2);
+ break;
+ }
+ parms1 = TREE_CHAIN (parms1);
+ parms2 = TREE_CHAIN (parms2);
+ }
+
+ return 1;
+ }
tweak:
{
if (warn)
{
- pedwarn ("\
-ISO C++ says that these are ambiguous, even \
-though the worst conversion for the first is better than \
-the worst conversion for the second:");
+ pedwarn (input_location, 0,
+ "ISO C++ says that these are ambiguous, even "
+ "though the worst conversion for the first is better than "
+ "the worst conversion for the second:");
print_z_candidate (_("candidate 1:"), w);
print_z_candidate (_("candidate 2:"), l);
}
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);
doing a bad conversion, convert_like will complain. */
tree
-perform_implicit_conversion (tree type, tree expr)
+perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain, int flags)
{
conversion *conv;
void *p;
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
/*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ flags);
+
if (!conv)
{
- error ("could not convert %qE to %qT", expr, type);
+ if (complain & tf_error)
+ {
+ /* If expr has unknown type, then it is an overloaded function.
+ Call instantiate_type to get good error messages. */
+ if (TREE_TYPE (expr) == unknown_type_node)
+ instantiate_type (type, expr, complain);
+ else if (invalid_nonstatic_memfn_p (expr, complain))
+ /* We gave an error. */;
+ else
+ error ("could not convert %qE to %qT", expr, type);
+ }
expr = error_mark_node;
}
else if (processing_template_decl)
expr = build_nop (type, expr);
}
else
- expr = convert_like (conv, expr);
+ expr = convert_like (conv, expr, complain);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
return expr;
}
+tree
+perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
+{
+ return perform_implicit_conversion_flags (type, expr, complain, LOOKUP_IMPLICIT);
+}
+
/* Convert EXPR to TYPE (as a direct-initialization) if that is
permitted. If the conversion is valid, the converted expression is
returned. Otherwise, NULL_TREE is returned, except in the case
tree
perform_direct_initialization_if_possible (tree type,
tree expr,
- bool c_cast_p)
+ bool c_cast_p,
+ tsubst_flags_t complain)
{
conversion *conv;
void *p;
ill-formed. */
if (CLASS_TYPE_P (type))
{
+ VEC(tree,gc) *args = make_tree_vector_single (expr);
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- type, LOOKUP_NORMAL);
+ &args, type, LOOKUP_NORMAL, complain);
+ release_tree_vector (args);
return build_cplus_new (type, expr);
}
else
expr = convert_like_real (conv, expr, NULL_TREE, 0, 0,
/*issue_conversion_warnings=*/false,
- c_cast_p);
+ c_cast_p,
+ tf_warning_or_error);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
return var;
}
+/* EXPR is the initializer for a variable DECL of reference or
+ std::initializer_list type. Create, push and return a new VAR_DECL
+ for the initializer so that it will live as long as DECL. Any
+ cleanup for the new variable is returned through CLEANUP, and the
+ code to initialize the new variable is returned through INITP. */
+
+tree
+set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp)
+{
+ tree init;
+ tree type;
+ tree var;
+
+ /* Create the temporary variable. */
+ type = TREE_TYPE (expr);
+ var = make_temporary_var_for_ref_to_temp (decl, type);
+ layout_decl (var, 0);
+ /* If the rvalue is the result of a function call it will be
+ a TARGET_EXPR. If it is some other construct (such as a
+ member access expression where the underlying object is
+ itself the result of a function call), turn it into a
+ TARGET_EXPR here. It is important that EXPR be a
+ TARGET_EXPR below since otherwise the INIT_EXPR will
+ attempt to make a bitwise copy of EXPR to initialize
+ VAR. */
+ if (TREE_CODE (expr) != TARGET_EXPR)
+ expr = get_target_expr (expr);
+ /* Create the INIT_EXPR that will initialize the temporary
+ variable. */
+ init = build2 (INIT_EXPR, type, var, expr);
+ if (at_function_scope_p ())
+ {
+ add_decl_expr (var);
+
+ if (TREE_STATIC (var))
+ init = add_stmt_to_compound (init, register_dtor_fn (var));
+ else
+ *cleanup = cxx_maybe_build_cleanup (var);
+
+ /* We must be careful to destroy the temporary only
+ after its initialization has taken place. If the
+ initialization throws an exception, then the
+ destructor should not be run. We cannot simply
+ transform INIT into something like:
+
+ (INIT, ({ CLEANUP_STMT; }))
+
+ because emit_local_var always treats the
+ initializer as a full-expression. Thus, the
+ destructor would run too early; it would run at the
+ end of initializing the reference variable, rather
+ than at the end of the block enclosing the
+ reference variable.
+
+ The solution is to pass back a cleanup expression
+ which the caller is responsible for attaching to
+ the statement tree. */
+ }
+ else
+ {
+ rest_of_decl_compilation (var, /*toplev=*/1, at_eof);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ static_aggregates = tree_cons (NULL_TREE, var,
+ static_aggregates);
+ }
+
+ *initp = init;
+ return var;
+}
+
/* Convert EXPR to the indicated reference TYPE, in a way suitable for
initializing a variable of that TYPE. If DECL is non-NULL, it is
the VAR_DECL being initialized with the EXPR. (In that case, the
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;
}
/*fn=*/NULL_TREE, /*argnum=*/0,
/*inner=*/-1,
/*issue_conversion_warnings=*/true,
- /*c_cast_p=*/false);
+ /*c_cast_p=*/false,
+ tf_warning_or_error);
if (error_operand_p (expr))
expr = error_mark_node;
else
{
- if (!real_lvalue_p (expr))
+ if (!lvalue_or_rvalue_with_address_p (expr))
{
tree init;
- tree type;
-
- /* Create the temporary variable. */
- type = TREE_TYPE (expr);
- var = make_temporary_var_for_ref_to_temp (decl, type);
- layout_decl (var, 0);
- /* If the rvalue is the result of a function call it will be
- a TARGET_EXPR. If it is some other construct (such as a
- member access expression where the underlying object is
- itself the result of a function call), turn it into a
- TARGET_EXPR here. It is important that EXPR be a
- TARGET_EXPR below since otherwise the INIT_EXPR will
- attempt to make a bitwise copy of EXPR to initialize
- VAR. */
- if (TREE_CODE (expr) != TARGET_EXPR)
- expr = get_target_expr (expr);
- /* Create the INIT_EXPR that will initialize the temporary
- variable. */
- init = build2 (INIT_EXPR, type, var, expr);
- if (at_function_scope_p ())
- {
- add_decl_expr (var);
-
- if (TREE_STATIC (var))
- init = add_stmt_to_compound (init, register_dtor_fn (var));
- else
- *cleanup = cxx_maybe_build_cleanup (var);
-
- /* We must be careful to destroy the temporary only
- after its initialization has taken place. If the
- initialization throws an exception, then the
- destructor should not be run. We cannot simply
- transform INIT into something like:
-
- (INIT, ({ CLEANUP_STMT; }))
-
- because emit_local_var always treats the
- initializer as a full-expression. Thus, the
- destructor would run too early; it would run at the
- end of initializing the reference variable, rather
- than at the end of the block enclosing the
- reference variable.
-
- The solution is to pass back a cleanup expression
- which the caller is responsible for attaching to
- the statement tree. */
- }
- else
- {
- rest_of_decl_compilation (var, /*toplev=*/1, at_eof);
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
- static_aggregates = tree_cons (NULL_TREE, var,
- static_aggregates);
- }
+ var = set_up_extended_ref_temp (decl, expr, cleanup, &init);
/* Use its address to initialize the reference variable. */
expr = build_address (var);
if (base_conv_type)
}
else
/* Take the address of EXPR. */
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
/* If a BASE_CONV was required, perform it now. */
if (base_conv_type)
expr = (perform_implicit_conversion
- (build_pointer_type (base_conv_type), expr));
+ (build_pointer_type (base_conv_type), expr,
+ tf_warning_or_error));
expr = build_nop (type, expr);
}
}
else
/* Perform the conversion. */
- expr = convert_like (conv, expr);
+ expr = convert_like (conv, expr, tf_warning_or_error);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
return expr;
}
+/* Returns true iff TYPE is some variant of std::initializer_list. */
+
+bool
+is_std_init_list (tree type)
+{
+ return (CLASS_TYPE_P (type)
+ && CP_TYPE_CONTEXT (type) == std_node
+ && strcmp (TYPE_NAME_STRING (type), "initializer_list") == 0);
+}
+
+/* Returns true iff DECL is a list constructor: i.e. a constructor which
+ will accept an argument list of a single std::initializer_list<T>. */
+
+bool
+is_list_ctor (tree decl)
+{
+ tree args = FUNCTION_FIRST_USER_PARMTYPE (decl);
+ tree arg;
+
+ if (!args || args == void_list_node)
+ return false;
+
+ arg = non_reference (TREE_VALUE (args));
+ if (!is_std_init_list (arg))
+ return false;
+
+ args = TREE_CHAIN (args);
+
+ if (args && args != void_list_node && !TREE_PURPOSE (args))
+ /* There are more non-defaulted parms. */
+ return false;
+
+ return true;
+}
+
#include "gt-cp-call.h"