/* 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, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
#include "cp-tree.h"
#include "output.h"
#include "flags.h"
-#include "rtl.h"
#include "toplev.h"
-#include "expr.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
#include "intl.h"
#include "target.h"
#include "convert.h"
: (NODE)->user_conv_p ? cr_user \
: (NODE)->rank)
+#define BAD_CONVERSION_RANK(NODE) \
+ ((NODE)->ellipsis_p ? cr_ellipsis \
+ : (NODE)->user_conv_p ? cr_user \
+ : (NODE)->rank)
+
static struct obstack conversion_obstack;
static bool conversion_obstack_initialized;
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
static tree prep_operand (tree);
-static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
- int, struct z_candidate **);
+static void add_candidates (tree, tree, const VEC(tree,gc) *, tree, tree, bool,
+ tree, tree, int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
-static tree build_temp (tree, tree, int, diagnostic_t *);
+static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
NAME can take many forms... */
return build_call_a (function, 0, NULL);
else
{
- tree *argarray = (tree *) alloca (n * sizeof (tree));
+ tree *argarray = XALLOCAVEC (tree, n);
va_list ap;
int i;
indicated by the CONVERSION_PATH. */
tree conversion_path;
tree template_decl;
+ tree explicit_targs;
candidate_warning *warnings;
z_candidate *next;
};
/* [conv.ptr]
A null pointer constant is an integral constant expression
- (_expr.const_) rvalue of integer type that evaluates to zero. */
- t = integral_constant_value (t);
- if (t == null_node)
+ (_expr.const_) rvalue of integer type that evaluates to zero or
+ an rvalue of type std::nullptr_t. */
+ if (NULLPTR_TYPE_P (TREE_TYPE (t)))
return true;
- if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))
+ if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- STRIP_NOPS (t);
- if (!TREE_OVERFLOW (t))
- return true;
+ if (cxx_dialect >= cxx0x)
+ {
+ t = fold_non_dependent_expr (t);
+ t = maybe_constant_value (t);
+ if (TREE_CONSTANT (t) && integer_zerop (t))
+ return true;
+ }
+ else
+ {
+ t = integral_constant_value (t);
+ STRIP_NOPS (t);
+ if (integer_zerop (t) && !TREE_OVERFLOW (t))
+ return true;
+ }
}
return false;
}
unsigned i;
tree val;
+ /* Within a list-initialization we can have more user-defined
+ conversions. */
+ flags &= ~LOOKUP_NO_CONVERSION;
+ /* But no narrowing conversions. */
+ flags |= LOOKUP_NO_NARROWING;
+
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val)
{
conversion *sub
return t;
}
+/* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list,
+ is a valid aggregate initializer for array type ATYPE. */
+
+static bool
+can_convert_array (tree atype, tree ctor, int flags)
+{
+ unsigned i;
+ tree elttype = TREE_TYPE (atype);
+ for (i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
+ {
+ tree val = CONSTRUCTOR_ELT (ctor, i)->value;
+ bool ok;
+ if (TREE_CODE (elttype) == ARRAY_TYPE
+ && TREE_CODE (val) == CONSTRUCTOR)
+ ok = can_convert_array (elttype, val, flags);
+ else
+ ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags);
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
aggregate class, if such a conversion is possible. */
unsigned HOST_WIDE_INT i = 0;
conversion *c;
tree field = next_initializable_field (TYPE_FIELDS (type));
+ tree empty_ctor = NULL_TREE;
- for (; field; field = next_initializable_field (TREE_CHAIN (field)))
+ for (; field; field = next_initializable_field (DECL_CHAIN (field)))
{
+ tree ftype = TREE_TYPE (field);
+ tree val;
+ bool ok;
+
if (i < CONSTRUCTOR_NELTS (ctor))
+ val = CONSTRUCTOR_ELT (ctor, i)->value;
+ else
{
- constructor_elt *ce = CONSTRUCTOR_ELT (ctor, i);
- if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (ce->value),
- ce->value, flags))
- return NULL;
- ++i;
- if (TREE_CODE (type) == UNION_TYPE)
- break;
+ if (empty_ctor == NULL_TREE)
+ empty_ctor = build_constructor (init_list_type_node, NULL);
+ val = empty_ctor;
}
- else if (build_value_init (TREE_TYPE (field)) == error_mark_node)
+ ++i;
+
+ if (TREE_CODE (ftype) == ARRAY_TYPE
+ && TREE_CODE (val) == CONSTRUCTOR)
+ ok = can_convert_array (ftype, val, flags);
+ else
+ ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags);
+
+ if (!ok)
return NULL;
+
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
}
if (i < CONSTRUCTOR_NELTS (ctor))
if (same_type_p (from, to))
return conv;
- if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
+ /* [conv.ptr]
+ A null pointer constant can be converted to a pointer type; ... A
+ null pointer constant of integral type can be converted to an
+ rvalue of type std::nullptr_t. */
+ if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to)
+ || NULLPTR_TYPE_P (to))
&& expr && null_ptr_cst_p (expr))
conv = build_conv (ck_std, to, conv);
else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
&& !TYPE_PTRMEM_P (from)
&& TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
{
+ tree nfrom = TREE_TYPE (from);
+ if (c_dialect_objc ())
+ nfrom = objc_non_volatilized_type (nfrom);
from = build_pointer_type
- (cp_build_qualified_type (void_type_node,
- cp_type_quals (TREE_TYPE (from))));
+ (cp_build_qualified_type (void_type_node,
+ cp_type_quals (nfrom)));
conv = build_conv (ck_ptr, from, conv);
}
else if (TYPE_PTRMEM_P (from))
else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */
conv = build_conv (ck_qual, to, conv);
+ /* Allow conversions among compatible ObjC pointer types (base
+ conversions have been already handled above). */
+ else if (c_dialect_objc ()
+ && objc_compare_types (to, from, -4, NULL_TREE))
+ conv = build_conv (ck_ptr, to, conv);
else if (ptr_reasonably_similar (to_pointee, from_pointee))
{
conv = build_conv (ck_ptr, to, conv);
An rvalue of arithmetic, unscoped enumeration, pointer, or
pointer to member type can be converted to an rvalue of type
- bool. */
+ bool. ... An rvalue of type std::nullptr_t can be converted
+ to an rvalue of type bool; */
if (ARITHMETIC_TYPE_P (from)
|| UNSCOPED_ENUM_P (from)
|| fcode == POINTER_TYPE
- || TYPE_PTR_TO_MEMBER_P (from))
+ || TYPE_PTR_TO_MEMBER_P (from)
+ || NULLPTR_TYPE_P (from))
{
conv = build_conv (ck_std, to, conv);
if (fcode == POINTER_TYPE
|| TYPE_PTRMEM_P (from)
|| (TYPE_PTRMEMFUNC_P (from)
- && conv->rank < cr_pbool))
+ && conv->rank < cr_pbool)
+ || NULLPTR_TYPE_P (from))
conv->rank = cr_pbool;
return conv;
}
bool
reference_related_p (tree t1, tree t2)
{
+ if (t1 == error_mark_node || t2 == error_mark_node)
+ return false;
+
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
struct z_candidate *cand;
bool any_viable_p;
- conversions = lookup_conversions (s, /*lookup_template_convs_p=*/true);
+ if (!expr)
+ return NULL;
+
+ conversions = lookup_conversions (s);
if (!conversions)
return NULL;
t = TREE_TYPE (reference_type);
+ /* We're performing a user-defined conversion to a desired type, so set
+ this for the benefit of add_candidates. */
+ flags |= LOOKUP_NO_CONVERSION;
+
for (; conversions; conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
+ tree binfo = TREE_PURPOSE (conversions);
+ struct z_candidate *old_candidates = candidates;;
- for (; fns; fns = OVL_NEXT (fns))
+ add_candidates (fns, first_arg, NULL, reference_type,
+ NULL_TREE, false,
+ binfo, TYPE_BINFO (s),
+ flags, &candidates);
+
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree f = OVL_CURRENT (fns);
+ /* Now, see if the conversion function really returns
+ an lvalue of the appropriate type. From the
+ point of view of unification, simply returning an
+ rvalue of the right type is good enough. */
+ tree f = cand->fn;
tree t2 = TREE_TYPE (TREE_TYPE (f));
-
- if (DECL_NONCONVERTING_P (f)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- cand = NULL;
-
- /* If this is a template function, try to get an exact
- match. */
- if (TREE_CODE (f) == TEMPLATE_DECL)
+ if (TREE_CODE (t2) != REFERENCE_TYPE
+ || !reference_compatible_p (t, TREE_TYPE (t2)))
{
- cand = add_template_candidate (&candidates,
- f, s,
- NULL_TREE,
- first_arg,
- NULL,
- reference_type,
- TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL,
- DEDUCE_CONV);
-
- if (cand)
- {
- /* Now, see if the conversion function really returns
- an lvalue of the appropriate type. From the
- point of view of unification, simply returning an
- rvalue of the right type is good enough. */
- f = cand->fn;
- t2 = TREE_TYPE (TREE_TYPE (f));
- if (TREE_CODE (t2) != REFERENCE_TYPE
- || !reference_compatible_p (t, TREE_TYPE (t2)))
- {
- candidates = candidates->next;
- cand = NULL;
- }
- }
+ cand->viable = 0;
}
- else if (TREE_CODE (t2) == REFERENCE_TYPE
- && reference_compatible_p (t, TREE_TYPE (t2)))
- cand = add_function_candidate (&candidates, f, s, first_arg,
- NULL, TYPE_BINFO (s),
- TREE_PURPOSE (conversions),
- LOOKUP_NORMAL);
-
- if (cand)
+ else
{
conversion *identity_conv;
/* Build a standard conversion sequence indicating the
type, so that we can later do a const_cast to the desired type. */
if (related_p && c_cast_p
&& !at_least_as_qualified_p (to, tfrom))
- to = build_qualified_type (to, cp_type_quals (tfrom));
+ to = cp_build_qualified_type (to, cp_type_quals (tfrom));
compatible_p = reference_compatible_p (to, tfrom);
/* Directly bind reference when target expression's type is compatible with
conversion operator). */
flags |= LOOKUP_NO_TEMP_BIND;
- /* Temporaries are copy-initialized, except for this hack to allow
- explicit conversion ops to the copy ctor. See also
- add_function_candidate. */
+ /* Core issue 899: When [copy-]initializing a temporary to be bound
+ to the first parameter of a copy constructor (12.8) called with
+ a single argument in the context of direct-initialization,
+ explicit conversion functions are also considered.
+
+ So don't set LOOKUP_ONLYCONVERTING in that case. */
if (!(flags & LOOKUP_COPY_PARM))
flags |= LOOKUP_ONLYCONVERTING;
|| expr == error_mark_node)
return NULL;
+ if (c_dialect_objc ())
+ from = objc_non_volatilized_type (from);
+
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, c_cast_p, flags);
else
tree elt;
if (nelts == 0)
- elt = integer_zero_node;
+ elt = build_value_init (to, tf_none);
else if (nelts == 1)
elt = CONSTRUCTOR_ELT (expr, 0)->value;
else
&& (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
+ |LOOKUP_NO_NARROWING));
if (CLASS_TYPE_P (to)
&& !CLASSTYPE_NON_AGGREGATE (complete_type (to))
else if (!sufficient_parms_p (parmnode))
viable = 0;
+ /* Kludge: When looking for a function from a subobject while generating
+ an implicit copy/move constructor/operator=, don't consider anything
+ that takes (a reference to) an unrelated type. See c++/44909. */
+ else if (parmlist
+ && ((flags & LOOKUP_SPECULATIVE)
+ || (current_function_decl
+ && DECL_DEFAULTED_FN (current_function_decl))))
+ {
+ if (DECL_CONSTRUCTOR_P (fn))
+ i = 1;
+ else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
+ && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
+ i = 2;
+ else
+ i = 0;
+ if (i && len == i)
+ {
+ parmnode = chain_index (i-1, parmlist);
+ if (!reference_related_p (non_reference (TREE_VALUE (parmnode)),
+ ctype))
+ viable = 0;
+ }
+ }
+
if (! viable)
goto out;
tree parmtype = TREE_VALUE (parmnode);
int lflags = flags;
+ parmnode = TREE_CHAIN (parmnode);
+
/* The type of the implicit object parameter ('this') for
overload resolution is not always the same as for the
function itself; conversion functions are considered to
parameter, we can just change the parm type. */
if (ctype && is_this)
{
- parmtype
- = build_qualified_type (ctype,
- TYPE_QUALS (TREE_TYPE (parmtype)));
+ parmtype = cp_build_qualified_type
+ (ctype, cp_type_quals (TREE_TYPE (parmtype)));
parmtype = build_pointer_type (parmtype);
}
- if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn)
- && (len-skip == 1))
+ /* Core issue 899: When [copy-]initializing a temporary to be bound
+ to the first parameter of a copy constructor (12.8) called with
+ a single argument in the context of direct-initialization,
+ explicit conversion functions are also considered.
+
+ So set LOOKUP_COPY_PARM to let reference_binding know that
+ it's being called in that context. We generalize the above
+ to handle move constructors and template constructors as well;
+ the standardese should soon be updated similarly. */
+ if (ctype && i == 0 && (len-skip == 1)
+ && !(flags & LOOKUP_ONLYCONVERTING)
+ && DECL_CONSTRUCTOR_P (fn)
+ && parmtype != error_mark_node
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (parmtype), ctype)))
{
- /* Hack: Direct-initialize copy parm (i.e. suppress
- LOOKUP_ONLYCONVERTING) to make explicit conversion ops
- work. See also reference_binding. */
lflags |= LOOKUP_COPY_PARM;
+ /* We allow user-defined conversions within init-lists, but
+ not for the copy constructor. */
if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
lflags |= LOOKUP_NO_CONVERSION;
}
if (t->bad_p)
viable = -1;
-
- if (parmnode)
- parmnode = TREE_CHAIN (parmnode);
}
out:
{
int ref1, i;
int enum_p = 0;
- tree type, argtypes[3];
+ tree type, argtypes[3], t;
/* TYPES[i] is the set of possible builtin-operator parameter types
- we will consider for the Ith argument. These are represented as
- a TREE_LIST; the TREE_VALUE of each node is the potential
- parameter type. */
- tree types[2];
+ we will consider for the Ith argument. */
+ VEC(tree,gc) *types[2];
+ unsigned ix;
for (i = 0; i < 3; ++i)
{
ref1 = 0;
}
- types[0] = types[1] = NULL_TREE;
+ types[0] = make_tree_vector ();
+ types[1] = make_tree_vector ();
for (i = 0; i < 2; ++i)
{
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return;
- convs = lookup_conversions (argtypes[i],
- /*lookup_template_convs_p=*/false);
+ convs = lookup_conversions (argtypes[i]);
if (code == COND_EXPR)
{
if (real_lvalue_p (args[i]))
- types[i] = tree_cons
- (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
+ VEC_safe_push (tree, gc, types[i],
+ build_reference_type (argtypes[i]));
- types[i] = tree_cons
- (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
+ VEC_safe_push (tree, gc, types[i],
+ TYPE_MAIN_VARIANT (argtypes[i]));
}
else if (! convs)
continue;
if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ VEC_safe_push (tree, gc, types[i], type);
type = non_reference (type);
if (i != 0 || ! ref1)
{
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]);
+ VEC_safe_push (tree, gc, types[i], type);
if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
- if (! value_member (type, types[i]))
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ if (! vec_member (type, types[i]))
+ VEC_safe_push (tree, gc, types[i], type);
}
}
else
{
if (code == COND_EXPR && real_lvalue_p (args[i]))
- types[i] = tree_cons
- (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
+ VEC_safe_push (tree, gc, types[i],
+ build_reference_type (argtypes[i]));
type = non_reference (argtypes[i]);
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (enum_p && UNSCOPED_ENUM_P (type))
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ VEC_safe_push (tree, gc, types[i], type);
if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ VEC_safe_push (tree, gc, types[i], type);
}
}
/* Run through the possible parameter types of both arguments,
creating candidates with those parameter types. */
- for (; types[0]; types[0] = TREE_CHAIN (types[0]))
+ FOR_EACH_VEC_ELT_REVERSE (tree, types[0], ix, t)
{
- if (types[1])
- for (type = types[1]; type; type = TREE_CHAIN (type))
+ unsigned jx;
+ tree u;
+
+ if (!VEC_empty (tree, types[1]))
+ FOR_EACH_VEC_ELT_REVERSE (tree, types[1], jx, u)
add_builtin_candidate
- (candidates, code, code2, fnname, TREE_VALUE (types[0]),
- TREE_VALUE (type), args, argtypes, flags);
+ (candidates, code, code2, fnname, t,
+ u, args, argtypes, flags);
else
add_builtin_candidate
- (candidates, code, code2, fnname, TREE_VALUE (types[0]),
+ (candidates, code, code2, fnname, t,
NULL_TREE, args, argtypes, flags);
}
+
+ release_tree_vector (types[0]);
+ release_tree_vector (types[1]);
}
return_type, strict, flags);
if (i != 0)
- return NULL;
+ goto fail;
fn = instantiate_template (tmpl, targs, tf_none);
if (fn == error_mark_node)
- return NULL;
+ goto fail;
/* In [class.copy]:
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
- return NULL;
+ goto fail;
}
if (obj != NULL_TREE)
cand->template_decl = build_template_info (tmpl, targs);
else
cand->template_decl = DECL_TEMPLATE_INFO (fn);
+ cand->explicit_targs = explicit_targs;
return cand;
+ fail:
+ return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL,
+ access_path, conversion_path, 0);
}
}
/* The CANDS are the set of candidates that were considered for
- overload resolution. Return the set of viable candidates. If none
- of the candidates were viable, set *ANY_VIABLE_P to true. STRICT_P
- is true if a candidate should be considered viable only if it is
- strictly viable. */
+ overload resolution. Return the set of viable candidates, or CANDS
+ if none are viable. If any of the candidates were viable, set
+ *ANY_VIABLE_P to true. STRICT_P is true if a candidate should be
+ considered viable only if it is strictly viable. */
static struct z_candidate*
splice_viable (struct z_candidate *cands,
if (processing_template_decl)
return build_address (obj);
- return cp_build_unary_op (ADDR_EXPR, obj, 0, tf_warning_or_error);
+ return cp_build_addr_expr (obj, tf_warning_or_error);
}
/* Returns true iff functions are equivalent. Equivalent functions are
static inline int
equal_functions (tree fn1, tree fn2)
{
+ if (TREE_CODE (fn1) != TREE_CODE (fn2))
+ return 0;
+ if (TREE_CODE (fn1) == TEMPLATE_DECL)
+ return fn1 == fn2;
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
return decls_match (fn1, fn2);
inform (input_location, "%s %T <conversion>", msgstr, candidate->fn);
else if (candidate->viable == -1)
inform (input_location, "%s %+#D <near match>", msgstr, candidate->fn);
- else if (DECL_DELETED_FN (candidate->fn))
+ else if (DECL_DELETED_FN (STRIP_TEMPLATE (candidate->fn)))
inform (input_location, "%s %+#D <deleted>", msgstr, candidate->fn);
else
inform (input_location, "%s %+#D", msgstr, candidate->fn);
if (!candidates)
return;
- /* Remove deleted candidates. */
+ /* Remove non-viable deleted candidates. */
cand1 = candidates;
for (cand2 = &cand1; *cand2; )
{
if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ && !(*cand2)->viable
&& DECL_DELETED_FN ((*cand2)->fn))
*cand2 = (*cand2)->next;
else
{
tree fn = cand1->fn;
/* Skip builtin candidates and conversion functions. */
- if (TREE_CODE (fn) != FUNCTION_DECL)
+ if (!DECL_P (fn))
continue;
cand2 = &cand1->next;
while (*cand2)
{
- if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+ if (DECL_P ((*cand2)->fn)
&& equal_functions (fn, (*cand2)->fn))
*cand2 = (*cand2)->next;
else
return std_seq;
}
+/* Handle overload resolution for initializing an object of class type from
+ an initializer list. First we look for a suitable constructor that
+ takes a std::initializer_list; if we don't find one, we then look for a
+ non-list constructor.
+
+ Parameters are as for add_candidates, except that the arguments are in
+ the form of a CONSTRUCTOR (the initializer list) rather than a VEC, and
+ the RETURN_TYPE parameter is replaced by TOTYPE, the desired type. */
+
+static void
+add_list_candidates (tree fns, tree first_arg,
+ tree init_list, tree totype,
+ tree explicit_targs, bool template_only,
+ tree conversion_path, tree access_path,
+ int flags,
+ struct z_candidate **candidates)
+{
+ VEC(tree,gc) *args;
+
+ gcc_assert (*candidates == NULL);
+
+ /* For list-initialization we consider explicit constructors, but
+ give an error if one is selected. */
+ flags &= ~LOOKUP_ONLYCONVERTING;
+ /* And we don't allow narrowing conversions. We also use this flag to
+ avoid the copy constructor call for copy-list-initialization. */
+ flags |= LOOKUP_NO_NARROWING;
+
+ /* Always use the default constructor if the list is empty (DR 990). */
+ if (CONSTRUCTOR_NELTS (init_list) == 0
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
+ ;
+ /* If the class has a list ctor, try passing the list as a single
+ argument first, but only consider list ctors. */
+ else if (TYPE_HAS_LIST_CTOR (totype))
+ {
+ flags |= LOOKUP_LIST_ONLY;
+ args = make_tree_vector_single (init_list);
+ add_candidates (fns, first_arg, args, NULL_TREE,
+ explicit_targs, template_only, conversion_path,
+ access_path, flags, candidates);
+ if (any_strictly_viable (*candidates))
+ return;
+ }
+
+ args = ctor_to_vec (init_list);
+
+ /* We aren't looking for list-ctors anymore. */
+ flags &= ~LOOKUP_LIST_ONLY;
+ /* We allow more user-defined conversions within an init-list. */
+ flags &= ~LOOKUP_NO_CONVERSION;
+ /* But not for the copy ctor. */
+ flags |= LOOKUP_NO_COPY_CTOR_CONVERSION;
+
+ add_candidates (fns, first_arg, args, NULL_TREE,
+ explicit_targs, template_only, conversion_path,
+ access_path, flags, candidates);
+}
+
/* Returns the best overload candidate to perform the requested
conversion. This function is used for three the overloading situations
described in [over.match.copy], [over.match.conv], and [over.match.ref].
reference to it)... */
}
else
- conv_fns = lookup_conversions (fromtype,
- /*lookup_template_convs_p=*/true);
+ conv_fns = lookup_conversions (fromtype);
}
candidates = 0;
flags |= LOOKUP_NO_CONVERSION;
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ flags |= LOOKUP_NO_NARROWING;
/* It's OK to bind a temporary for converting constructor arguments, but
not in converting the return value of a conversion operator. */
if (ctors)
{
+ int ctorflags = flags;
ctors = BASELINK_FUNCTIONS (ctors);
first_arg = build_int_cst (build_pointer_type (totype), 0);
- if (BRACE_ENCLOSED_INITIALIZER_P (expr)
- && !TYPE_HAS_LIST_CTOR (totype))
- {
- args = ctor_to_vec (expr);
- /* We still allow more conversions within an init-list. */
- flags = ((flags & ~LOOKUP_NO_CONVERSION)
- /* But not for the copy ctor. */
- |LOOKUP_NO_COPY_CTOR_CONVERSION
- |LOOKUP_NO_NARROWING);
- }
- else
- args = make_tree_vector_single (expr);
/* We should never try to call the abstract or base constructor
from here. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
- }
- for (; ctors; ctors = OVL_NEXT (ctors))
- {
- tree ctor = OVL_CURRENT (ctors);
- if (DECL_NONCONVERTING_P (ctor)
- && !BRACE_ENCLOSED_INITIALIZER_P (expr))
- continue;
- if (TREE_CODE (ctor) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, ctor, totype,
- NULL_TREE, first_arg, args, NULL_TREE,
- TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags,
- DEDUCE_CALL);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ /* List-initialization. */
+ add_list_candidates (ctors, first_arg, expr, totype, NULL_TREE,
+ false, TYPE_BINFO (totype), TYPE_BINFO (totype),
+ ctorflags, &candidates);
+ }
else
- cand = add_function_candidate (&candidates, ctor, totype,
- first_arg, args, TYPE_BINFO (totype),
- TYPE_BINFO (totype),
- flags);
+ {
+ args = make_tree_vector_single (expr);
+ add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
+ TYPE_BINFO (totype), TYPE_BINFO (totype),
+ ctorflags, &candidates);
+ }
- if (cand)
+ for (cand = candidates; cand; cand = cand->next)
{
cand->second_conv = build_identity_conv (totype, NULL_TREE);
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
- tree fns;
tree conversion_path = TREE_PURPOSE (conv_fns);
+ struct z_candidate *old_candidates;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
- for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns))
+ old_candidates = candidates;
+ add_candidates (TREE_VALUE (conv_fns), first_arg, NULL, totype,
+ NULL_TREE, false,
+ conversion_path, TYPE_BINFO (fromtype),
+ flags, &candidates);
+
+ for (cand = candidates; cand != old_candidates; cand = cand->next)
{
- tree fn = OVL_CURRENT (fns);
-
- if (DECL_NONCONVERTING_P (fn)
- && (flags & LOOKUP_ONLYCONVERTING))
- continue;
-
- /* [over.match.funcs] For conversion functions, the function
- is considered to be a member of the class of the implicit
- object argument for the purpose of defining the type of
- the implicit object parameter.
-
- So we pass fromtype as CTYPE to add_*_candidate. */
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, fn, fromtype,
- NULL_TREE,
- first_arg, NULL, totype,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags,
- DEDUCE_CONV);
- else
- cand = add_function_candidate (&candidates, fn, fromtype,
- first_arg, NULL,
- TYPE_BINFO (fromtype),
- conversion_path,
- flags);
+ conversion *ics
+ = implicit_conversion (totype,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0,
+ /*c_cast_p=*/false, convflags);
- if (cand)
- {
- conversion *ics
- = implicit_conversion (totype,
- TREE_TYPE (TREE_TYPE (cand->fn)),
- 0,
- /*c_cast_p=*/false, convflags);
-
- /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
- copy-initialization. In that case, "The result of the
- call is then used to direct-initialize the object that is
- the destination of the copy-initialization." [dcl.init]
-
- We represent this in the conversion sequence with an
- rvalue conversion, which means a constructor call. But
- don't add a second rvalue conversion if there's already
- one there. Which there really shouldn't be, but it's
- harmless since we'd add it here anyway. */
- if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
- && !(convflags & LOOKUP_NO_TEMP_BIND))
- ics = build_conv (ck_rvalue, totype, ics);
-
- cand->second_conv = ics;
-
- if (!ics)
- cand->viable = 0;
- else if (candidates->viable == 1 && ics->bad_p)
- cand->viable = -1;
- }
+ /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
+ copy-initialization. In that case, "The result of the
+ call is then used to direct-initialize the object that is
+ the destination of the copy-initialization." [dcl.init]
+
+ We represent this in the conversion sequence with an
+ rvalue conversion, which means a constructor call. But
+ don't add a second rvalue conversion if there's already
+ one there. Which there really shouldn't be, but it's
+ harmless since we'd add it here anyway. */
+ if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
+ && !(convflags & LOOKUP_NO_TEMP_BIND))
+ ics = build_conv (ck_rvalue, totype, ics);
+
+ cand->second_conv = ics;
+
+ if (!ics)
+ cand->viable = 0;
+ else if (cand->viable == 1 && ics->bad_p)
+ cand->viable = -1;
}
}
return NULL_TREE;
}
+/* Subroutine of convert_nontype_argument.
+
+ EXPR is an argument for a template non-type parameter of integral or
+ enumeration type. Do any necessary conversions (that are permitted for
+ non-type arguments) to convert it to the parameter type.
+
+ If conversion is successful, returns the converted expression;
+ otherwise, returns error_mark_node. */
+
+tree
+build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain)
+{
+ conversion *conv;
+ void *p;
+ tree t;
+
+ if (error_operand_p (expr))
+ return error_mark_node;
+
+ gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+
+ /* Get the high-water mark for the CONVERSION_OBSTACK. */
+ p = conversion_obstack_alloc (0);
+
+ conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ /*c_cast_p=*/false,
+ LOOKUP_IMPLICIT);
+
+ /* for a non-type template-parameter of integral or
+ enumeration type, integral promotions (4.5) and integral
+ conversions (4.7) are applied. */
+ /* It should be sufficient to check the outermost conversion step, since
+ there are no qualification conversions to integer type. */
+ if (conv)
+ switch (conv->kind)
+ {
+ /* A conversion function is OK. If it isn't constexpr, we'll
+ complain later that the argument isn't constant. */
+ case ck_user:
+ /* The lvalue-to-rvalue conversion is OK. */
+ case ck_rvalue:
+ case ck_identity:
+ break;
+
+ case ck_std:
+ t = conv->u.next->type;
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
+ break;
+
+ if (complain & tf_error)
+ error ("conversion from %qT to %qT not considered for "
+ "non-type template argument", t, type);
+ /* and fall through. */
+
+ default:
+ conv = NULL;
+ break;
+ }
+
+ if (conv)
+ expr = convert_like (conv, expr, complain);
+ else
+ expr = error_mark_node;
+
+ /* Free all the conversions we allocated. */
+ obstack_free (&conversion_obstack, p);
+
+ return expr;
+}
+
/* Do any initial processing on the arguments to a function call. */
static VEC(tree,gc) *
unsigned int ix;
tree arg;
- for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ FOR_EACH_VEC_ELT (tree, args, ix, arg)
{
if (error_operand_p (arg))
return NULL;
}
/* Add the various candidate functions. */
- add_candidates (fn, args, explicit_targs, template_only,
+ add_candidates (fn, NULL_TREE, args, NULL_TREE,
+ explicit_targs, template_only,
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE,
LOOKUP_NORMAL,
{
if (complain & tf_error)
{
- if (!any_viable_p && candidates && ! candidates->next)
+ if (!any_viable_p && candidates && ! candidates->next
+ && (TREE_CODE (candidates->fn) == FUNCTION_DECL))
return cp_build_function_call_vec (candidates->fn, args, complain);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = TREE_OPERAND (fn, 0);
if (fns)
{
- tree base = BINFO_TYPE (BASELINK_BINFO (fns));
first_mem_arg = build_this (obj);
- for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (&candidates, fn, base, NULL_TREE,
- first_mem_arg, *args, NULL_TREE,
- TYPE_BINFO (type),
- TYPE_BINFO (type),
- LOOKUP_NORMAL, DEDUCE_CALL);
- else
- add_function_candidate
- (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
- TYPE_BINFO (type), LOOKUP_NORMAL);
- }
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ first_mem_arg, *args, NULL_TREE,
+ NULL_TREE, false,
+ BASELINK_BINFO (fns), BASELINK_ACCESS_BINFO (fns),
+ LOOKUP_NORMAL, &candidates);
}
- convs = lookup_conversions (type, /*lookup_template_convs_p=*/true);
+ convs = lookup_conversions (type);
for (; convs; convs = TREE_CHAIN (convs))
{
tree arg2_type;
tree arg3_type;
tree result = NULL_TREE;
- tree result_save;
tree result_type = NULL_TREE;
bool lvalue_p = true;
struct z_candidate *candidates = 0;
the type of the other. */
if ((conv2 || conv3)
&& CLASS_TYPE_P (arg2_type)
- && TYPE_QUALS (arg2_type) != TYPE_QUALS (arg3_type))
+ && cp_type_quals (arg2_type) != cp_type_quals (arg3_type))
arg2_type = arg3_type =
cp_build_qualified_type (arg2_type,
- TYPE_QUALS (arg2_type)
- | TYPE_QUALS (arg3_type));
+ cp_type_quals (arg2_type)
+ | cp_type_quals (arg3_type));
}
/* [expr.cond]
&& same_type_p (arg2_type, arg3_type))
{
result_type = arg2_type;
+ arg2 = mark_lvalue_use (arg2);
+ arg3 = mark_lvalue_use (arg3);
goto valid_operands;
}
/* In this case, there is always a common type. */
result_type = type_after_usual_arithmetic_conversions (arg2_type,
arg3_type);
+ do_warn_double_promotion (result_type, arg2_type, arg3_type,
+ "implicit conversion from %qT to %qT to "
+ "match other result of conditional",
+ input_location);
if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& TREE_CODE (arg3_type) == ENUMERAL_TYPE)
}
valid_operands:
- result_save = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
- result = fold_if_not_in_template (result_save);
-
- if (cp_unevaluated_operand && TREE_CODE (result) == CALL_EXPR)
- /* Avoid folding to a CALL_EXPR within decltype (c++/42013). */
- result = result_save;
+ result = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
+ if (!cp_unevaluated_operand)
+ /* Avoid folding within decltype (c++/42013) and noexcept. */
+ result = fold_if_not_in_template (result);
/* We can't use result_type below, as fold might have returned a
throw_expr. */
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
- CANDIDATES. The ARGS are the arguments provided to the call,
- without any implicit object parameter. This may change ARGS. The
+ CANDIDATES. The ARGS are the arguments provided to the call;
+ if FIRST_ARG is non-null it is the implicit object argument,
+ otherwise the first element of ARGS is used if needed. The
EXPLICIT_TARGS are explicit template arguments provided.
TEMPLATE_ONLY is true if only template functions should be
considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for
add_function_candidate. */
static void
-add_candidates (tree fns, const VEC(tree,gc) *args,
+add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args,
+ tree return_type,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates)
{
tree ctype;
- VEC(tree,gc) *non_static_args;
- tree first_arg;
+ const VEC(tree,gc) *non_static_args;
+ bool check_list_ctor;
+ bool check_converting;
+ unification_kind_t strict;
+ tree fn;
- ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
- /* Delay creating the implicit this parameter until it is needed. */
- non_static_args = NULL;
- first_arg = NULL_TREE;
+ if (!fns)
+ return;
+
+ /* Precalculate special handling of constructors and conversion ops. */
+ fn = OVL_CURRENT (fns);
+ if (DECL_CONV_FN_P (fn))
+ {
+ check_list_ctor = false;
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ if (flags & LOOKUP_NO_CONVERSION)
+ /* We're doing return_type(x). */
+ strict = DEDUCE_CONV;
+ else
+ /* We're doing x.operator return_type(). */
+ strict = DEDUCE_EXACT;
+ /* [over.match.funcs] For conversion functions, the function
+ is considered to be a member of the class of the implicit
+ object argument for the purpose of defining the type of
+ the implicit object parameter. */
+ ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg)));
+ }
+ else
+ {
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ check_list_ctor = !!(flags & LOOKUP_LIST_ONLY);
+ check_converting = !!(flags & LOOKUP_ONLYCONVERTING);
+ }
+ else
+ {
+ check_list_ctor = false;
+ check_converting = false;
+ }
+ strict = DEDUCE_CALL;
+ ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
+ }
+
+ if (first_arg)
+ non_static_args = args;
+ else
+ /* Delay creating the implicit this parameter until it is needed. */
+ non_static_args = NULL;
- while (fns)
+ for (; fns; fns = OVL_NEXT (fns))
{
- tree fn;
tree fn_first_arg;
const VEC(tree,gc) *fn_args;
fn = OVL_CURRENT (fns);
+
+ if (check_converting && DECL_NONCONVERTING_P (fn))
+ continue;
+ if (check_list_ctor && !is_list_ctor (fn))
+ continue;
+
/* Figure out which set of arguments to use. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{
- /* If this function is a non-static member, prepend the implicit
- object parameter. */
- if (non_static_args == NULL)
+ /* If this function is a non-static member and we didn't get an
+ implicit object argument, move it out of args. */
+ if (first_arg == NULL_TREE)
{
unsigned int ix;
tree arg;
-
- non_static_args = VEC_alloc (tree, gc,
- VEC_length (tree, args) - 1);
+ VEC(tree,gc) *tempvec
+ = VEC_alloc (tree, gc, VEC_length (tree, args) - 1);
for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix)
- VEC_quick_push (tree, non_static_args, arg);
+ VEC_quick_push (tree, tempvec, arg);
+ non_static_args = tempvec;
+ first_arg = build_this (VEC_index (tree, args, 0));
}
- if (first_arg == NULL_TREE)
- first_arg = build_this (VEC_index (tree, args, 0));
+
fn_first_arg = first_arg;
fn_args = non_static_args;
}
explicit_targs,
fn_first_arg,
fn_args,
- NULL_TREE,
+ return_type,
access_path,
conversion_path,
flags,
- DEDUCE_CALL);
+ strict);
else if (!template_only)
add_function_candidate (candidates,
fn,
access_path,
conversion_path,
flags);
- fns = OVL_NEXT (fns);
}
}
/* Add namespace-scope operators to the list of functions to
consider. */
add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true),
- arglist, NULL_TREE, false, NULL_TREE, NULL_TREE,
+ NULL_TREE, arglist, NULL_TREE,
+ NULL_TREE, false, NULL_TREE, NULL_TREE,
flags, &candidates);
/* Add class-member operators to the candidate set. */
if (CLASS_TYPE_P (TREE_TYPE (arg1)))
goto user_defined_result_ready;
}
if (fns)
- add_candidates (BASELINK_FUNCTIONS (fns), arglist,
+ add_candidates (BASELINK_FUNCTIONS (fns),
+ NULL_TREE, arglist, NULL_TREE,
NULL_TREE, false,
BASELINK_BINFO (fns),
- TYPE_BINFO (TREE_TYPE (arg1)),
+ BASELINK_ACCESS_BINFO (fns),
flags, &candidates);
}
return cp_build_unary_op (code, arg1, candidates != 0, complain);
case ARRAY_REF:
- return build_array_ref (input_location, arg1, arg2);
+ return cp_build_array_ref (input_location, arg1, arg2, complain);
case MEMBER_REF:
return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL,
/* The placement args might not be suitable for overload
resolution at this point, so build the call directly. */
int nargs = call_expr_nargs (placement);
- tree *argarray = (tree *) alloca (nargs * sizeof (tree));
+ tree *argarray = XALLOCAVEC (tree, nargs);
int i;
argarray[0] = addr;
for (i = 1; i < nargs; i++)
static tree
build_temp (tree expr, tree type, int flags,
- diagnostic_t *diagnostic_kind)
+ diagnostic_t *diagnostic_kind, tsubst_flags_t complain)
{
int savew, savee;
VEC(tree,gc) *args;
savew = warningcount, savee = errorcount;
args = make_tree_vector_single (expr);
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- &args, type, flags, tf_warning_or_error);
+ &args, type, flags, complain);
release_tree_vector (args);
if (warningcount > savew)
*diagnostic_kind = DK_WARNING;
{
permerror (input_location, "invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
if (fn)
- permerror (input_location, " initializing argument %P of %qD", argnum, fn);
+ permerror (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
}
else
return error_mark_node;
tree convfn = cand->fn;
unsigned i;
+ expr = mark_rvalue_use (expr);
+
/* When converting from an init list we consider explicit
constructors, but actually trying to call one is an error. */
- if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
+ if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
+ /* Unless we're calling it for value-initialization from an
+ empty list, since that is handled separately in 8.5.4. */
+ && cand->num_convs > 0)
{
if (complain & tf_error)
error ("converting to %qT from initializer list would use "
return expr;
}
case ck_identity:
+ expr = mark_rvalue_use (expr);
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
int nelts = CONSTRUCTOR_NELTS (expr);
if (nelts == 0)
- expr = integer_zero_node;
+ expr = build_value_init (totype, tf_warning_or_error);
else if (nelts == 1)
expr = CONSTRUCTOR_ELT (expr, 0)->value;
else
}
return expr;
case ck_ambig:
- if (!(complain & tf_error))
- return error_mark_node;
- /* Call build_user_type_conversion again for the error. */
- return build_user_type_conversion
- (totype, convs->u.expr, LOOKUP_NORMAL);
+ if (complain & tf_error)
+ {
+ /* Call build_user_type_conversion again for the error. */
+ build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL);
+ if (fn)
+ error (" initializing argument %P of %q+D", argnum, fn);
+ }
+ return error_mark_node;
case ck_list:
{
1, false, false, complain);
if (sub == error_mark_node)
return sub;
- check_narrowing (TREE_TYPE (sub), val);
+ if (!BRACE_ENCLOSED_INITIALIZER_P (val))
+ check_narrowing (TREE_TYPE (sub), val);
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub);
}
/* Build up the array. */
elttype = cp_build_qualified_type
- (elttype, TYPE_QUALS (elttype) | TYPE_QUAL_CONST);
+ (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
array = build_array_of_n_type (elttype, len);
array = finish_compound_literal (array, new_ctor);
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
/* Build an expression for `*((base*) &expr)'. */
- expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
+ expr = cp_build_addr_expr (expr, complain);
expr = convert_to_base (expr, build_pointer_type (totype),
!c_cast_p, /*nonnull=*/true, complain);
expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
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, &diag_kind);
+ if (TREE_CODE (expr) == TARGET_EXPR
+ && TARGET_EXPR_LIST_INIT_P (expr))
+ /* Copy-list-initialization doesn't actually involve a copy. */
+ return expr;
+ expr = build_temp (expr, totype, flags, &diag_kind, complain);
if (diag_kind && fn)
{
if ((complain & tf_error))
- emit_diagnostic (diag_kind, input_location, 0,
+ emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (fn), 0,
" initializing argument %P of %qD", argnum, fn);
else if (diag_kind == DK_ERROR)
return error_mark_node;
VA_ARG_EXPR and CONSTRUCTOR expressions are special cases
that need temporaries, even when their types are reference
compatible with the type of reference being bound, so the
- upcoming call to cp_build_unary_op (ADDR_EXPR, expr, ...)
- doesn't fail. */
+ upcoming call to cp_build_addr_expr doesn't fail. */
if (convs->need_temporary_p
|| TREE_CODE (expr) == CONSTRUCTOR
|| TREE_CODE (expr) == VA_ARG_EXPR)
{
- tree type = convs->u.next->type;
+ /* Otherwise, a temporary of type "cv1 T1" is created and
+ initialized from the initializer expression using the rules
+ for a non-reference copy-initialization (8.5). */
+
+ tree type = TREE_TYPE (ref_type);
cp_lvalue_kind lvalue = real_lvalue_p (expr);
- if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (type, convs->u.next->type));
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (type)
&& !TYPE_REF_IS_RVALUE (ref_type))
{
if (complain & tf_error)
OK. */
if ((lvalue & clk_packed)
&& CLASS_TYPE_P (type)
- && !TYPE_HAS_TRIVIAL_INIT_REF (type))
+ && type_has_nontrivial_copy_init (type))
{
if (complain & tf_error)
error ("cannot bind packed field %qE to %qT",
/* Take the address of the thing to which we will bind the
reference. */
- expr = cp_build_unary_op (ADDR_EXPR, expr, 1, complain);
+ expr = cp_build_addr_expr (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
case ck_pmem:
return convert_ptrmem (totype, expr, /*allow_inverse_p=*/false,
- c_cast_p);
+ c_cast_p, complain);
default:
break;
tree
convert_arg_to_ellipsis (tree arg)
{
+ tree arg_type;
+
/* [expr.call]
The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
standard conversions are performed. */
arg = decay_conversion (arg);
+ arg_type = TREE_TYPE (arg);
/* [expr.call]
If the argument has integral or enumeration type that is subject
type that is subject to the floating point promotion
(_conv.fpprom_), the value of the argument is converted to the
promoted type before the call. */
- if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
- && (TYPE_PRECISION (TREE_TYPE (arg))
+ if (TREE_CODE (arg_type) == REAL_TYPE
+ && (TYPE_PRECISION (arg_type)
< 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)))
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type)))
+ {
+ if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+ warning (OPT_Wdouble_promotion,
+ "implicit conversion from %qT to %qT when passing "
+ "argument to function",
+ arg_type, double_type_node);
+ arg = convert_to_real (double_type_node, arg);
+ }
+ else if (NULLPTR_TYPE_P (arg_type))
+ arg = null_pointer_node;
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (arg_type))
arg = perform_integral_promotions (arg);
arg = require_complete_type (arg);
+ arg_type = TREE_TYPE (arg);
if (arg != error_mark_node
- && (type_has_nontrivial_copy_init (TREE_TYPE (arg))
- || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (arg))))
+ && (type_has_nontrivial_copy_init (arg_type)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type)))
{
/* [expr.call] 5.2.2/7:
Passing a potentially-evaluated argument of class type (Clause 9)
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));
+ "type %q#T through %<...%>", arg_type);
}
return arg;
if (expr == error_mark_node || !type)
return error_mark_node;
+ expr = mark_lvalue_use (expr);
+
if (type_has_nontrivial_copy_init (type)
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
}
/* Detect recursion. */
- for (i = 0; VEC_iterate (tree, default_arg_context, i, t); ++i)
+ FOR_EACH_VEC_ELT (tree, default_arg_context, i, t)
if (t == fn)
{
error ("recursive evaluation of default argument for %q#D", fn);
{
arg = digest_init (type, arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", fn, parmnum,
+ ICR_DEFAULT_ARGUMENT, fn, parmnum,
tf_warning_or_error);
}
else
if (!CONSTANT_CLASS_P (arg))
arg = unshare_expr (arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", fn, parmnum,
+ ICR_DEFAULT_ARGUMENT, fn, parmnum,
tf_warning_or_error);
arg = convert_for_arg_passing (type, arg);
}
{
type = build_reference_type (type);
/* There are no other pointers to this temporary. */
- type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
+ type = cp_build_qualified_type (type, TYPE_QUAL_RESTRICT);
}
else if (targetm.calls.promote_prototypes (type)
&& INTEGRAL_TYPE_P (type)
++nargs;
alcarray = XALLOCAVEC (tree, nargs);
alcarray[0] = first_arg;
- for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ FOR_EACH_VEC_ELT (tree, args, ix, arg)
alcarray[ix + 1] = arg;
argarray = alcarray;
}
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
- require_complete_type (return_type);
+ require_complete_type_sfinae (return_type, complain);
return convert_from_reference (expr);
}
/* Give any warnings we noticed during overload resolution. */
- if (cand->warnings)
+ if (cand->warnings && (complain & tf_warning))
{
struct candidate_warning *w;
for (w = cand->warnings; w; w = w->next)
if (DECL_FUNCTION_MEMBER_P (fn))
{
+ tree access_fn;
/* If FN is a template function, two cases must be considered.
For example:
different access. */
if (DECL_TEMPLATE_INFO (fn)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
- perform_or_defer_access_check (cand->access_path,
- DECL_TI_TEMPLATE (fn), fn);
+ access_fn = DECL_TI_TEMPLATE (fn);
+ else
+ access_fn = fn;
+ if (flags & LOOKUP_SPECULATIVE)
+ {
+ if (!speculative_access_check (cand->access_path, access_fn, fn,
+ !!(flags & LOOKUP_COMPLAIN)))
+ return error_mark_node;
+ }
else
- perform_or_defer_access_check (cand->access_path, fn, fn);
+ perform_or_defer_access_check (cand->access_path, access_fn, fn);
+ }
+
+ /* If we're checking for implicit delete, don't bother with argument
+ conversions. */
+ if (flags & LOOKUP_SPECULATIVE)
+ {
+ if (DECL_DELETED_FN (fn))
+ {
+ if (flags & LOOKUP_COMPLAIN)
+ mark_used (fn);
+ return error_mark_node;
+ }
+ if (cand->viable == 1)
+ return fn;
+ else if (!(flags & LOOKUP_COMPLAIN))
+ /* Reject bad conversions now. */
+ return error_mark_node;
+ /* else continue to get conversion error. */
}
/* Find maximum size of vector to hold converted arguments. */
nargs = VEC_length (tree, args) + (first_arg != NULL_TREE ? 1 : 0);
if (parmlen > nargs)
nargs = parmlen;
- argarray = (tree *) alloca (nargs * sizeof (tree));
+ argarray = XALLOCAVEC (tree, nargs);
/* The implicit parameters to a constructor are not considered by overload
resolution, and must be of the proper type. */
parm = TREE_CHAIN (parm), ++arg_index, ++i)
{
tree type = TREE_VALUE (parm);
+ tree arg = VEC_index (tree, args, arg_index);
conv = convs[i];
if (cxx_dialect > cxx98
&& flag_deduce_init_list
&& cand->template_decl
- && is_std_init_list (non_reference (type)))
+ && is_std_init_list (non_reference (type))
+ && BRACE_ENCLOSED_INITIALIZER_P (arg))
{
tree tmpl = TI_TEMPLATE (cand->template_decl);
tree realparm = chain_index (j, DECL_ARGUMENTS (cand->fn));
pattype = PACK_EXPANSION_PATTERN (pattype);
pattype = non_reference (pattype);
- if (!is_std_init_list (pattype))
+ if (TREE_CODE (pattype) == TEMPLATE_TYPE_PARM
+ && (cand->explicit_targs == NULL_TREE
+ || (TREE_VEC_LENGTH (cand->explicit_targs)
+ <= TEMPLATE_TYPE_IDX (pattype))))
{
pedwarn (input_location, 0, "deducing %qT as %qT",
non_reference (TREE_TYPE (patparm)),
}
}
- val = convert_like_with_context
- (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
- complain);
+ val = convert_like_with_context (conv, arg, fn, i-is_method, complain);
val = convert_for_arg_passing (type, val);
if (val == error_mark_node)
{
tree a = VEC_index (tree, args, arg_index);
if (magic_varargs_p (fn))
- /* Do no conversions for magic varargs. */;
+ /* Do no conversions for magic varargs. */
+ a = mark_type_use (a);
else
a = convert_arg_to_ellipsis (a);
argarray[j++] = a;
tree targ;
tree arg = argarray[num_artificial_parms_for (fn)];
tree fa;
+ bool trivial = trivial_fn_p (fn);
/* Pull out the real argument, disregarding const-correctness. */
targ = arg;
else
arg = cp_build_indirect_ref (arg, RO_NULL, 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. */
- else if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
+ if (!trivial || DECL_DELETED_FN (fn))
{
mark_used (fn);
already_used = true;
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. */
- fa = (cand->first_arg != NULL_TREE
- ? cand->first_arg
- : VEC_index (tree, args, 0));
+ fa = argarray[0];
if (integer_zerop (fa))
{
if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
- else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
- return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
+ else if (trivial)
+ return force_target_expr (DECL_CONTEXT (fn), arg);
}
- else if (TREE_CODE (arg) == TARGET_EXPR
- || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
- && !move_fn_p (fn)))
+ else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
{
tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
complain));
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
- && copy_fn_p (fn)
- && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
+ && trivial_fn_p (fn)
+ && !DECL_DELETED_FN (fn))
{
tree to = stabilize_reference
(cp_build_indirect_ref (argarray[0], RO_NULL, complain));
arg2 = TYPE_SIZE_UNIT (as_base);
arg1 = arg;
- arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain);
+ arg0 = cp_build_addr_expr (to, complain);
if (!can_trust_pointer_alignment ())
{
return val;
}
+ /* FIXME handle trivial default constructor and destructor, too. */
if (!already_used)
mark_used (fn);
fndecl = get_callee_fndecl (fn);
if ((!fndecl || !TREE_NOTHROW (fndecl))
&& at_function_scope_p ()
- && cfun)
+ && cfun
+ && cp_function_chain)
cp_function_chain->can_throw = 1;
/* Check that arguments to builtin functions match the expectations. */
if (!java_iface_lookup_fn)
{
- tree endlink = build_void_list_node ();
- tree t = tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, java_int_type_node,
- endlink)));
+ tree ftype = build_function_type_list (ptr_type_node,
+ ptr_type_node, ptr_type_node,
+ java_int_type_node, NULL_TREE);
java_iface_lookup_fn
- = add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
- build_function_type (ptr_type_node, t),
+ = add_builtin_function ("_Jv_LookupInterfaceMethodIdx", ftype,
0, NOT_BUILT_IN, NULL, NULL_TREE);
}
/* Determine the itable index of FN. */
i = 1;
- for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
+ for (method = TYPE_METHODS (iface); method; method = DECL_CHAIN (method))
{
if (!DECL_VIRTUAL_P (method))
continue;
if (TYPE_P (binfo))
{
/* Resolve the name. */
- if (!complete_type_or_else (binfo, NULL_TREE))
+ if (!complete_type_or_maybe_complain (binfo, NULL_TREE, complain))
return error_mark_node;
binfo = TYPE_BINFO (binfo);
/* If the current function is a complete object constructor
or destructor, then we fetch the VTT directly.
Otherwise, we look it up using the VTT we were given. */
- vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type));
+ vtt = DECL_CHAIN (CLASSTYPE_VTABLES (current_class_type));
vtt = decay_conversion (vtt);
vtt = build3 (COND_EXPR, TREE_TYPE (vtt),
build2 (EQ_EXPR, boolean_type_node,
VEC(tree,gc) *user_args;
tree call;
tree fn;
- tree class_type;
int template_only = 0;
bool any_viable_p;
tree orig_instance;
if (DECL_DESTRUCTOR_P (fn))
name = complete_dtor_identifier;
- /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
- initializer, not T({ }). If the type doesn't have a list ctor,
- break apart the list into separate ctor args. */
- if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args)
- && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
- && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0))
- && !TYPE_HAS_LIST_CTOR (basetype))
- {
- gcc_assert (VEC_length (tree, *args) == 1);
- *args = ctor_to_vec (VEC_index (tree, *args, 0));
- }
-
- class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
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))
+ /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
+ initializer, not T({ }). */
+ 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)))
{
- tree t = OVL_CURRENT (fn);
- tree this_first_arg;
-
- /* We can end up here for copy-init of same or base class. */
- if ((flags & LOOKUP_ONLYCONVERTING)
- && DECL_NONCONVERTING_P (t))
- continue;
-
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_first_arg = first_mem_arg;
- else
- this_first_arg = NULL_TREE;
+ gcc_assert (VEC_length (tree, *args) == 1
+ && !(flags & LOOKUP_ONLYCONVERTING));
- if (TREE_CODE (t) == TEMPLATE_DECL)
- /* A member template. */
- add_template_candidate (&candidates, t,
- class_type,
- explicit_targs,
- this_first_arg,
- args == NULL ? NULL : *args,
- optype,
- access_binfo,
- conversion_path,
- flags,
- DEDUCE_CALL);
- else if (! template_only)
- add_function_candidate (&candidates, t,
- class_type,
- this_first_arg,
- args == NULL ? NULL : *args,
- access_binfo,
- conversion_path,
- flags);
+ add_list_candidates (fns, first_mem_arg, VEC_index (tree, *args, 0),
+ basetype, explicit_targs, template_only,
+ conversion_path, access_binfo, flags, &candidates);
}
-
+ else
+ {
+ add_candidates (fns, first_mem_arg, user_args, optype,
+ explicit_targs, template_only, conversion_path,
+ access_binfo, flags, &candidates);
+ }
+ any_viable_p = false;
candidates = splice_viable (candidates, pedantic, &any_viable_p);
+
if (!any_viable_p)
{
if (complain & tf_error)
{
- if (!COMPLETE_TYPE_P (basetype))
+ if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
cxx_incomplete_type_error (instance_ptr, basetype);
+ else if (optype)
+ error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
+ basetype, optype, build_tree_list_vec (user_args),
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
else
{
char *pretty_name;
/* This is not an error, it is runtime undefined
behavior. */
warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ?
- "abstract virtual %q#D called from constructor"
- : "abstract virtual %q#D called from destructor"),
+ "pure virtual %q#D called from constructor"
+ : "pure virtual %q#D called from destructor"),
fn);
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
if (ics2->kind == ck_user
|| ics2->kind == ck_ambig
+ || ics2->kind == ck_aggr
+ || ics2->kind == ck_list
|| ics2->kind == ck_identity)
/* At this point, ICS1 cannot be a proper subsequence of
ICS2. We can get a USER_CONV when we are comparing the
if (rank1 == cr_bad)
{
- /* XXX Isn't this an extension? */
- /* Both ICS are bad. We try to make a decision based on what
- would have happened if they'd been good. */
- if (ics1->user_conv_p > ics2->user_conv_p
- || ics1->rank > ics2->rank)
+ /* Both ICS are bad. We try to make a decision based on what would
+ have happened if they'd been good. This is not an extension,
+ we'll still give an error when we build up the call; this just
+ helps us give a more helpful error message. */
+ rank1 = BAD_CONVERSION_RANK (ics1);
+ rank2 = BAD_CONVERSION_RANK (ics2);
+
+ if (rank1 > rank2)
return -1;
- else if (ics1->user_conv_p < ics2->user_conv_p
- || ics1->rank < ics2->rank)
+ else if (rank1 < rank2)
return 1;
/* We couldn't make up our minds; try to figure it out below. */
}
- if (ics1->ellipsis_p || ics1->kind == ck_list)
- /* Both conversions are ellipsis conversions or both are building a
- std::initializer_list. */
+ if (ics1->ellipsis_p)
+ /* Both conversions are ellipsis conversions. */
return 0;
/* User-defined conversion sequence U1 is a better conversion sequence
ond standard conversion sequence of U1 is better than the second
standard conversion sequence of U2. */
- if (ics1->user_conv_p)
+ /* Handle list-conversion with the same code even though it isn't always
+ ranked as a user-defined conversion and it doesn't have a second
+ standard conversion sequence; it will still have the desired effect.
+ Specifically, we need to do the reference binding comparison at the
+ end of this function. */
+
+ if (ics1->user_conv_p || ics1->kind == ck_list)
{
conversion *t1;
conversion *t2;
for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
- if (t1->kind == ck_ambig || t1->kind == ck_aggr)
- return 0;
+ if (t1->kind == ck_ambig || t1->kind == ck_aggr
+ || t1->kind == ck_list)
+ break;
for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
- if (t2->kind == ck_ambig || t2->kind == ck_aggr)
- return 0;
+ if (t2->kind == ck_ambig || t2->kind == ck_aggr
+ || t2->kind == ck_list)
+ break;
- if (t1->cand->fn != t2->cand->fn)
+ if (t1->kind != t2->kind)
return 0;
+ else if (t1->kind == ck_user)
+ {
+ if (t1->cand->fn != t2->cand->fn)
+ return 0;
+ }
+ else
+ {
+ /* For ambiguous or aggregate conversions, use the target type as
+ a proxy for the conversion function. */
+ if (!same_type_ignoring_top_level_qualifiers_p (t1->type, t2->type))
+ return 0;
+ }
/* We can just fall through here, after setting up
FROM_TYPE1 and FROM_TYPE2. */
Two conversion sequences with the same rank are indistinguishable
unless one of the following rules applies:
- --A conversion that is not a conversion of a pointer, or pointer
- to member, to bool is better than another conversion that is such
- a conversion.
+ --A conversion that does not a convert a pointer, pointer to member,
+ or std::nullptr_t to bool is better than one that does.
The ICS_STD_RANK automatically handles the pointer-to-bool rule,
so that we do not have to check it explicitly. */
winner = -1, w = cand2, l = cand1;
if (winner)
{
+ /* Don't choose a deleted function over ambiguity. */
+ if (DECL_P (w->fn) && DECL_DELETED_FN (w->fn))
+ return 0;
if (warn)
{
pedwarn (input_location, 0,
VAR. */
if (TREE_CODE (expr) != TARGET_EXPR)
expr = get_target_expr (expr);
- /* Create the INIT_EXPR that will initialize the temporary
- variable. */
- init = build2 (INIT_EXPR, type, var, expr);
+
+ /* If the initializer is constant, put it in DECL_INITIAL so we get
+ static initialization and use in constant expressions. */
+ init = maybe_constant_init (expr);
+ if (TREE_CONSTANT (init))
+ {
+ if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type))
+ {
+ /* 5.19 says that a constant expression can include an
+ lvalue-rvalue conversion applied to "a glvalue of literal type
+ that refers to a non-volatile temporary object initialized
+ with a constant expression". Rather than try to communicate
+ that this VAR_DECL is a temporary, just mark it constexpr.
+
+ Currently this is only useful for initializer_list temporaries,
+ since reference vars can't appear in constant expressions. */
+ DECL_DECLARED_CONSTEXPR_P (var) = true;
+ TREE_CONSTANT (var) = true;
+ }
+ DECL_INITIAL (var) = init;
+ init = NULL_TREE;
+ }
+ else
+ /* Create the INIT_EXPR that will initialize the temporary
+ variable. */
+ init = build2 (INIT_EXPR, type, var, expr);
if (at_function_scope_p ())
{
add_decl_expr (var);
{
if (complain & tf_error)
{
- if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
+ if (!CP_TYPE_CONST_P (TREE_TYPE (type))
&& !TYPE_REF_IS_RVALUE (type)
&& !real_lvalue_p (expr))
error ("invalid initialization of non-const reference of "
build_pointer_type (base_conv_type),
/*check_access=*/true,
/*nonnull=*/true, complain);
- expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
+ if (init)
+ expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
}
else
/* Take the address of EXPR. */
- expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
+ expr = cp_build_addr_expr (expr, tf_warning_or_error);
/* If a BASE_CONV was required, perform it now. */
if (base_conv_type)
expr = (perform_implicit_conversion
bool
is_std_init_list (tree type)
{
+ /* Look through typedefs. */
+ if (!TYPE_P (type))
+ return false;
+ type = TYPE_MAIN_VARIANT (type);
return (CLASS_TYPE_P (type)
&& CP_TYPE_CONTEXT (type) == std_node
&& strcmp (TYPE_NAME_STRING (type), "initializer_list") == 0);