/* 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).
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, tsubst_flags_t);
-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 *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... */
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)
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 *c;
tree field = TYPE_FIELDS (type);
- for (; field; field = TREE_CHAIN (field))
+ for (; field; field = TREE_CHAIN (field), ++i)
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
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 (MAYBE_CLASS_TYPE_P (TREE_TYPE (from))
- && MAYBE_CLASS_TYPE_P (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);
/* 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
- || (!(flags & LOOKUP_NO_TEMP_BIND)
- && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
- && CLASS_TYPE_P (from))))
+ && (is_lvalue
+ || (((CP_TYPE_CONST_NON_VOLATILE_P (to)
+ && !(flags & LOOKUP_NO_TEMP_BIND))
+ || TYPE_REF_IS_RVALUE (rto))
+ && (CLASS_TYPE_P (from) || (expr && lvalue_p (expr))))))
{
/* [dcl.init.ref]
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
else
conv->rvaluedness_matches_p
- = (TYPE_REF_IS_RVALUE (rto) == !lvalue_p);
+ = (TYPE_REF_IS_RVALUE (rto) == !is_lvalue);
- if ((lvalue_p & clk_bitfield) != 0
- || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
+ if ((is_lvalue & clk_bitfield) != 0
+ || ((is_lvalue & clk_packed) != 0 && !TYPE_PACKED (to)))
/* For the purposes of overload resolution, we ignore the fact
this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
actually occurs. */
conv->need_temporary_p = true;
+ /* Don't allow binding of lvalues to rvalue references. */
+ if (is_lvalue && TYPE_REF_IS_RVALUE (rto)
+ && !(flags & LOOKUP_PREFER_RVALUE))
+ conv->bad_p = true;
+
return conv;
}
/* [class.conv.fct] A conversion function is never used to convert a
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 (is_std_init_list (to) && expr
- && BRACE_ENCLOSED_INITIALIZER_P (expr))
- return build_list_conv (to, expr, flags);
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ if (is_std_init_list (to))
+ return build_list_conv (to, expr, flags);
+
+ /* Allow conversion from an initializer-list with one element to a
+ scalar type. */
+ if (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
&& (MAYBE_CLASS_TYPE_P (from)
&& (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))
}
/* 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));
parmtype = build_pointer_type (parmtype);
}
- if ((flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
- && ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
- lflags |= LOOKUP_NO_CONVERSION;
+ 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, lflags);
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;
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;
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 (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;
if (ctors)
{
- tree t;
-
ctors = BASELINK_FUNCTIONS (ctors);
- t = build_int_cst (build_pointer_type (totype), 0);
+ first_arg = build_int_cst (build_pointer_type (totype), 0);
if (BRACE_ENCLOSED_INITIALIZER_P (expr)
&& !TYPE_HAS_LIST_CTOR (totype))
{
- args = ctor_to_list (expr);
+ args = ctor_to_vec (expr);
/* We still allow more conversions within an init-list. */
flags = ((flags & ~LOOKUP_NO_CONVERSION)
/* But not for the copy ctor. */
|LOOKUP_NO_NARROWING);
}
else
- args = build_tree_list (NULL_TREE, expr);
+ 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))
{
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 (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);
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);
/* 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, tf_warning_or_error))
- return error_mark_node;
+ 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;
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
{
if (complain & tf_error)
error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (orig_fn)), args);
+ 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 (complain & tf_error)
{
if (!any_viable_p && candidates && ! candidates->next)
- return cp_build_function_call (candidates->fn, args, complain);
+ 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)), args);
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
else
error ("call of overloaded %<%D(%A)%> is ambiguous",
- DECL_NAME (OVL_CURRENT (fn)), args);
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
if (candidates)
print_z_candidates (candidates);
}
/* 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;
return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
}
-static tree
-build_object_call (tree obj, tree args, tsubst_flags_t complain)
+/* 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))
{
if (complain & tf_error)
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);
}
}
{
if (complain & tf_error)
{
- error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args);
+ error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj),
+ build_tree_list_vec (*args));
print_z_candidates (candidates);
}
result = error_mark_node;
if (complain & tf_error)
{
error ("call of %<(%T) (%A)%> is ambiguous",
- TREE_TYPE (obj), args);
+ TREE_TYPE (obj), build_tree_list_vec (*args));
print_z_candidates (candidates);
}
result = error_mark_node;
obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
complain);
obj = convert_from_reference (obj);
- result = cp_build_function_call (obj, args, complain);
+ 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
calculated only once. */
if (!arg2)
{
- if (pedantic && (complain & tf_error))
- 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, complain);
+ arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain,
+ LOOKUP_NORMAL);
/* If something has already gone wrong, just pass that fact up the
tree. */
bool any_viable_p;
/* Rearrange the arguments so that add_builtin_candidate only has
- to know about two args. In build_builtin_candidates, the
+ to know about two args. In build_builtin_candidate, the
arguments are unscrambled. */
args[0] = arg2;
args[1] = arg3;
arg1 = convert_like (conv, arg1, complain);
conv = cand->convs[1];
arg2 = convert_like (conv, arg2, complain);
+ arg2_type = TREE_TYPE (arg2);
conv = cand->convs[2];
arg3 = convert_like (conv, arg3, complain);
+ arg3_type = TREE_TYPE (arg3);
}
/* [expr.cond]
arg2_type = TREE_TYPE (arg2);
arg3 = force_rvalue (arg3);
- if (!CLASS_TYPE_P (arg2_type))
+ if (!CLASS_TYPE_P (arg3_type))
arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == error_mark_node)
type; 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,
/* 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, 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, complain);
+ /* 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);
if (!(complain & tf_error))
return error_mark_node;
- /* Look for an `operator++ (int)'. If they didn't have
- one, then we fall back to the old way of doing things. */
+ /* Look for an `operator++ (int)'. Pre-1985 C++ didn't
+ distinguish between prefix and postfix ++ and
+ operator++() was used for both, so we allow this with
+ -fpermissive. */
if (flags & LOOKUP_COMPLAIN)
- permerror ("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
default:
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;
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, complain);
if (conv->kind == ck_ref_bind)
conv = conv->u.next;
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;
arg3 = convert_like (conv, arg3, complain);
}
- if (!expl_eq_arg1)
- {
- if (complain & tf_warning)
- 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:
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, complain);
+ return cp_build_binary_op (input_location, code, arg1, arg2, complain);
case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
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, complain);
+ return build_array_ref (input_location, arg1, arg2);
case MEMBER_REF:
return build_m_component_ref (cp_build_indirect_ref (arg1, NULL,
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 cp_build_function_call (fn, args, tf_warning_or_error);
+ 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;
}
}
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, tf_warning_or_error);
+ 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;
}
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_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)
}
if (complain & tf_error)
{
- permerror ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
+ permerror (input_location, "invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
if (fn)
- permerror (" initializing argument %P of %qD", argnum, fn);
+ permerror (input_location, " initializing argument %P of %qD", argnum, fn);
}
else
return error_mark_node;
/* When converting from an init list we consider explicit
constructors, but actually trying to call one is an error. */
- if (DECL_NONCONVERTING_P (convfn))
+ if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
{
if (complain & tf_error)
error ("converting to %qT from initializer list would use "
/* 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);
+ {
+ 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, complain);
/* Convert a constant to its underlying value, unless we are
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. */
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, parms, val;
+ tree array, val;
+ VEC(tree,gc) *parms;
unsigned ix;
/* Convert all the elements. */
array = build_array_of_n_type (elttype, len);
array = finish_compound_literal (array, new_ctor);
- parms = build_tree_list (NULL_TREE, size_int (len));
- parms = tree_cons (NULL_TREE, decay_conversion (array), parms);
+ 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);
+ (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain);
+ release_tree_vector (parms);
pop_deferring_access_checks ();
return build_cplus_new (totype, new_ctor);
}
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)
+ expr = build_temp (expr, totype, flags, &diag_kind);
+ if (diag_kind && fn)
{
if ((complain & tf_error))
- diagnostic_fn (" initializing argument %P of %qD", argnum, fn);
- else if (diagnostic_fn == 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);
{
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
if (convs->check_narrowing)
check_narrowing (totype, expr);
- if (issue_conversion_warnings)
+ 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 = 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);
tf_warning_or_error);
arg = convert_for_arg_passing (type, arg);
}
+ pop_deferring_access_checks();
VEC_pop (tree, default_arg_context);
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)
{
if (complain & tf_error)
- permerror ("passing %qT as %<this%> argument of %q#D discards qualifiers",
+ permerror (input_location, "passing %qT as %<this%> argument of %q#D discards qualifiers",
TREE_TYPE (argtype), fn);
else
return error_mark_node;
/* 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, complain);
+ (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
+ complain);
val = convert_for_arg_passing (type, val);
- if ((complain == tf_none) && val == error_mark_node)
+ if (val == error_mark_node)
return error_mark_node;
else
argarray[j++] = val;
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;
else
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
- (cp_build_indirect_ref (TREE_VALUE (args), 0, complain));
+ tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+ complain));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
(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 = cp_build_indirect_ref (arg, 0, complain);
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 = 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);
+ 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);
/* 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,
+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,
- complain);
+ 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, tsubst_flags_t complain)
{
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))
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 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
- && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (args))
- && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (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 (TREE_CHAIN (args) == NULL_TREE);
- args = ctor_to_list (TREE_VALUE (args));
+ 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);
{
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, user_args,
+ basetype, pretty_name, arglist,
TREE_TYPE (TREE_TYPE (instance_ptr)));
if (free_p)
free (pretty_name);
{
char *pretty_name;
bool free_p;
+ tree arglist;
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,
- user_args);
+ arglist);
print_z_candidates (candidates);
if (free_p)
free (pretty_name);
}
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;
}
conversion *old_ics = *ics;
*ics = old_ics->u.next;
(*ics)->user_conv_p = old_ics->user_conv_p;
- (*ics)->bad_p = old_ics->bad_p;
return old_ics;
}
ref_conv1 = maybe_handle_ref_bind (&ics1);
ref_conv2 = maybe_handle_ref_bind (&ics2);
+ /* List-initialization sequence L1 is a better conversion sequence than
+ list-initialization sequence L2 if L1 converts to
+ std::initializer_list<X> for some X and L2 does not. */
+ if (ics1->kind == ck_list && ics2->kind != ck_list)
+ return 1;
+ if (ics2->kind == ck_list && ics1->kind != ck_list)
+ return -1;
+
/* [over.ics.rank]
When comparing the basic forms of implicit conversion sequences (as
/* We couldn't make up our minds; try to figure it out below. */
}
- if (ics1->ellipsis_p)
- /* Both conversions are ellipsis conversions. */
+ if (ics1->ellipsis_p || ics1->kind == ck_list)
+ /* Both conversions are ellipsis conversions or both are building a
+ std::initializer_list. */
return 0;
/* User-defined conversion sequence U1 is a better conversion sequence
conversion *t1;
conversion *t2;
- for (t1 = ics1; t1->kind != ck_user && t1->kind != ck_list; t1 = t1->u.next)
+ for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
if (t1->kind == ck_ambig || t1->kind == ck_aggr)
return 0;
- for (t2 = ics2; t2->kind != ck_user && t2->kind != ck_list; t2 = t2->u.next)
+ for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
if (t2->kind == ck_ambig || t2->kind == ck_aggr)
return 0;
- /* Conversion to std::initializer_list is better than other
- user-defined conversions. */
- if (t1->kind == ck_list
- || t2->kind == ck_list)
- {
- if (t2->kind != ck_list)
- return 1;
- else if (t1->kind != ck_list)
- return -1;
- else
- return 0;
- }
-
if (t1->cand->fn != t2->cand->fn)
return 0;
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)
{
- warning (0,
+ 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:");
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, tsubst_flags_t complain)
+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)
{
if (complain & tf_error)
- error ("could not convert %qE to %qT", expr, type);
+ {
+ /* 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)
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
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, complain);
+ &args, type, LOOKUP_NORMAL, complain);
+ release_tree_vector (args);
return build_cplus_new (type, expr);
}
Return the converted expression. */
tree
-initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
+initialize_reference (tree type, tree expr, tree decl, tree *cleanup,
+ tsubst_flags_t complain)
{
conversion *conv;
void *p;
LOOKUP_NORMAL);
if (!conv || conv->bad_p)
{
- if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
- && !real_lvalue_p (expr))
- error ("invalid initialization of non-const reference of "
- "type %qT from a temporary of type %qT",
- type, TREE_TYPE (expr));
- else
- error ("invalid initialization of reference of type "
- "%qT from expression of type %qT", type,
- TREE_TYPE (expr));
+ if (complain & tf_error)
+ {
+ if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
+ && !TYPE_REF_IS_RVALUE (type)
+ && !real_lvalue_p (expr))
+ error ("invalid initialization of non-const reference of "
+ "type %qT from an rvalue of type %qT",
+ type, TREE_TYPE (expr));
+ else
+ error ("invalid initialization of reference of type "
+ "%qT from expression of type %qT", type,
+ TREE_TYPE (expr));
+ }
return error_mark_node;
}
expr = error_mark_node;
else
{
- if (!real_lvalue_p (expr))
+ if (!lvalue_or_rvalue_with_address_p (expr))
{
tree init;
var = set_up_extended_ref_temp (decl, expr, cleanup, &init);