#include "config.h"
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "output.h"
#include "flags.h"
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
#include "ggc.h"
#include "diagnostic.h"
extern int inhibit_warnings;
static tree build_new_method_call PARAMS ((tree, tree, tree, tree, int));
static tree build_field_call PARAMS ((tree, tree, tree, tree));
static struct z_candidate * tourney PARAMS ((struct z_candidate *));
static int equal_functions PARAMS ((tree, tree));
static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PARAMS ((tree, tree));
static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
static tree build_java_interface_fn_ref PARAMS ((tree, tree));
#define convert_like(CONV, EXPR) convert_like_real (CONV, EXPR, NULL_TREE, 0, 0)
#define convert_like_with_context(CONV, EXPR, FN, ARGNO) convert_like_real (CONV, EXPR, FN, ARGNO, 0)
static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
tree, const char *));
static tree build_object_call PARAMS ((tree, tree));
static tree resolve_args PARAMS ((tree));
static struct z_candidate * build_user_type_conversion_1
PARAMS ((tree, tree, int));
static void print_z_candidates PARAMS ((struct z_candidate *));
static tree build_this PARAMS ((tree));
static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
static int any_viable PARAMS ((struct z_candidate *));
static struct z_candidate * add_template_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
unification_kind_t));
static struct z_candidate * add_template_candidate_real
PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
tree, unification_kind_t));
static struct z_candidate * add_template_conv_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, tree));
static struct z_candidate * add_builtin_candidates
PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
static struct z_candidate * add_builtin_candidate
PARAMS ((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree, tree, tree *, tree *, int));
static int is_complete PARAMS ((tree));
static struct z_candidate * build_builtin_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, tree *, tree *,
int));
static struct z_candidate * add_conv_candidate
PARAMS ((struct z_candidate *, tree, tree, tree));
static struct z_candidate * add_function_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, int));
static tree implicit_conversion PARAMS ((tree, tree, tree, int));
static tree standard_conversion PARAMS ((tree, tree, tree));
static tree reference_binding PARAMS ((tree, tree, tree, int));
static tree non_reference PARAMS ((tree));
static tree build_conv PARAMS ((enum tree_code, tree, tree));
static int is_subseq PARAMS ((tree, tree));
static tree maybe_handle_ref_bind PARAMS ((tree*));
static void maybe_handle_implicit_object PARAMS ((tree*));
static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
tree, tree, int));
static tree source_type PARAMS ((tree));
static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
static int reference_related_p PARAMS ((tree, tree));
static int reference_compatible_p PARAMS ((tree, tree));
static tree convert_class_to_reference PARAMS ((tree, tree, tree));
static tree direct_reference_binding PARAMS ((tree, tree));
static int promoted_arithmetic_type_p PARAMS ((tree));
static tree conditional_conversion PARAMS ((tree, tree));
tree
build_vfield_ref (datum, type)
tree datum, type;
{
tree rval;
if (datum == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
datum = convert_from_reference (datum);
if (! TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (type))
rval = build (COMPONENT_REF, TREE_TYPE (TYPE_VFIELD (type)),
datum, TYPE_VFIELD (type));
else
rval = build_component_ref (datum, DECL_NAME (TYPE_VFIELD (type)), NULL_TREE, 0);
return rval;
}
static tree
build_field_call (basetype_path, instance_ptr, name, parms)
tree basetype_path, instance_ptr, name, parms;
{
tree field, instance;
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
return NULL_TREE;
if (instance_ptr == current_class_ptr
&& IDENTIFIER_CLASS_VALUE (name) == NULL_TREE)
return NULL_TREE;
field = lookup_field (basetype_path, name, 1, 0);
if (field == error_mark_node || field == NULL_TREE)
return field;
if (TREE_CODE (field) == FIELD_DECL || TREE_CODE (field) == VAR_DECL)
{
instance = build_indirect_ref (instance_ptr, NULL);
instance = build_component_ref_1 (instance, field, 0);
if (instance == error_mark_node)
return error_mark_node;
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
instance, parms, NULL_TREE);
else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
== FUNCTION_TYPE)))
return build_function_call (instance, parms);
}
return NULL_TREE;
}
int
check_dtor_name (basetype, name)
tree basetype, name;
{
name = TREE_OPERAND (name, 0);
if (name == error_mark_node)
return 1;
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
else if (TYPE_P (name))
;
else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
|| (TREE_CODE (basetype) == ENUMERAL_TYPE
&& name == TYPE_IDENTIFIER (basetype)))
name = basetype;
else
name = get_type_value (name);
}
else if (DECL_CLASS_TEMPLATE_P (name))
return 0;
else
my_friendly_abort (980605);
if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
return 1;
return 0;
}
tree
build_scoped_method_call (exp, basetype, name, parms)
tree exp, basetype, name, parms;
{
tree binfo, decl;
tree type = TREE_TYPE (exp);
if (type == error_mark_node
|| basetype == error_mark_node)
return error_mark_node;
if (processing_template_decl)
{
if (TREE_CODE (name) == BIT_NOT_EXPR
&& TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
{
tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
if (type)
name = build_min_nt (BIT_NOT_EXPR, type);
}
name = build_min_nt (SCOPE_REF, basetype, name);
return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (basetype) == TREE_VEC)
{
binfo = basetype;
basetype = BINFO_TYPE (binfo);
}
else
binfo = NULL_TREE;
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
if (TREE_CODE (basetype) == NAMESPACE_DECL)
return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
if (! check_dtor_name (basetype, name))
error ("qualified type `%T' does not match destructor name `~%T'",
basetype, TREE_OPERAND (name, 0));
if (! IS_AGGR_TYPE (basetype))
{
if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
error ("type of `%E' does not match destructor type `%T' (type was `%T')",
exp, basetype, type);
return cp_convert (void_type_node, exp);
}
}
if (TREE_CODE (basetype) == NAMESPACE_DECL)
{
error ("`%D' is a namespace", basetype);
return error_mark_node;
}
if (! is_aggr_type (basetype, 1))
return error_mark_node;
if (! IS_AGGR_TYPE (type))
{
error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
exp, type);
return error_mark_node;
}
if (! binfo)
{
binfo = lookup_base (type, basetype, ba_check, NULL);
if (binfo == error_mark_node)
return error_mark_node;
if (! binfo)
error_not_base_type (basetype, type);
}
if (binfo)
{
if (TREE_CODE (exp) == INDIRECT_REF)
{
decl = build_base_path (PLUS_EXPR,
build_unary_op (ADDR_EXPR, exp, 0),
binfo, 1);
decl = build_indirect_ref (decl, NULL);
}
else
decl = build_scoped_ref (exp, basetype);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
return cp_convert (void_type_node, exp);
return build_delete (TREE_TYPE (decl), decl,
sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
0);
}
return build_method_call (decl, name, parms, binfo,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
}
return error_mark_node;
}
tree
build_addr_func (function)
tree function;
{
tree type = TREE_TYPE (function);
if (TREE_CODE (type) == METHOD_TYPE)
{
tree addr;
type = build_pointer_type (type);
if (mark_addressable (function) == 0)
return error_mark_node;
addr = build1 (ADDR_EXPR, type, function);
if (staticp (function))
TREE_CONSTANT (addr) = 1;
function = addr;
}
else
function = default_conversion (function);
return function;
}
tree
build_call (function, parms)
tree function, parms;
{
int is_constructor = 0;
int nothrow;
tree tmp;
tree decl;
tree result_type;
function = build_addr_func (function);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
sorry ("unable to call pointer to member function here");
return error_mark_node;
}
result_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (function)));
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
decl = TREE_OPERAND (function, 0);
else
decl = NULL_TREE;
nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl);
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
if (decl && ! TREE_USED (decl))
{
if (DECL_ARTIFICIAL (decl)
|| !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "__", 2))
mark_used (decl);
else
my_friendly_abort (990125);
}
if (! decl || ! DECL_BUILT_IN (decl))
for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp))
if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp)))
&& ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp))))
{
tree t = build (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp)));
TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t),
TREE_VALUE (tmp), t);
}
function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_TYPE (function) = result_type;
TREE_SIDE_EFFECTS (function) = 1;
TREE_NOTHROW (function) = nothrow;
return function;
}
#ifdef GATHER_STATISTICS
extern int n_build_method_call;
#endif
tree
build_method_call (instance, name, parms, basetype_path, flags)
tree instance, name, parms, basetype_path;
int flags;
{
tree basetype, instance_ptr;
#ifdef GATHER_STATISTICS
n_build_method_call++;
#endif
if (instance == error_mark_node
|| name == error_mark_node
|| parms == error_mark_node
|| (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
if (processing_template_decl)
{
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
tree type = NULL_TREE;
if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL)
type = TREE_TYPE (TREE_OPERAND (name, 0));
if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
name = build_min_nt (BIT_NOT_EXPR, type);
}
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
if (parms)
error ("destructors take no parameters");
basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
if (! check_dtor_name (basetype, name))
error
("destructor name `~%T' does not match type `%T' of expression",
TREE_OPERAND (name, 0), basetype);
if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
return cp_convert (void_type_node, instance);
instance = default_conversion (instance);
instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
return build_delete (build_pointer_type (basetype),
instance_ptr, sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
return build_new_method_call (instance, name, parms, basetype_path, flags);
}
struct z_candidate {
tree fn;
tree convs;
tree second_conv;
int viable;
tree basetype_path;
tree template;
tree warnings;
struct z_candidate *next;
};
#define IDENTITY_RANK 0
#define EXACT_RANK 1
#define PROMO_RANK 2
#define STD_RANK 3
#define PBOOL_RANK 4
#define USER_RANK 5
#define ELLIPSIS_RANK 6
#define BAD_RANK 7
#define ICS_RANK(NODE) \
(ICS_BAD_FLAG (NODE) ? BAD_RANK \
: ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \
: ICS_USER_FLAG (NODE) ? USER_RANK \
: ICS_STD_RANK (NODE))
#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE)
#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
#define NEED_TEMPORARY_P(NODE) (TREE_LANG_FLAG_4 ((NODE)))
#define USER_CONV_CAND(NODE) \
((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
int
null_ptr_cst_p (t)
tree t;
{
if (t == null_node
|| (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
return 1;
return 0;
}
int
sufficient_parms_p (parmlist)
tree parmlist;
{
for (; parmlist && parmlist != void_list_node;
parmlist = TREE_CHAIN (parmlist))
if (!TREE_PURPOSE (parmlist))
return 0;
return 1;
}
static tree
build_conv (code, type, from)
enum tree_code code;
tree type, from;
{
tree t;
int rank = ICS_STD_RANK (from);
t = make_node (code);
TREE_TYPE (t) = type;
TREE_OPERAND (t, 0) = from;
switch (code)
{
case PTR_CONV:
case PMEM_CONV:
case BASE_CONV:
case STD_CONV:
if (rank < STD_RANK)
rank = STD_RANK;
break;
case QUAL_CONV:
if (rank < EXACT_RANK)
rank = EXACT_RANK;
default:
break;
}
ICS_STD_RANK (t) = rank;
ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
return t;
}
static tree
non_reference (t)
tree t;
{
if (TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
return t;
}
tree
strip_top_quals (t)
tree t;
{
if (TREE_CODE (t) == ARRAY_TYPE)
return t;
return TYPE_MAIN_VARIANT (t);
}
static tree
standard_conversion (to, from, expr)
tree to, from, expr;
{
enum tree_code fcode, tcode;
tree conv;
int fromref = 0;
if (TREE_CODE (to) == REFERENCE_TYPE)
to = TREE_TYPE (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
{
fromref = 1;
from = TREE_TYPE (from);
}
to = strip_top_quals (to);
from = strip_top_quals (from);
if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
&& expr && type_unknown_p (expr))
{
expr = instantiate_type (to, expr, itf_none);
if (expr == error_mark_node)
return NULL_TREE;
from = TREE_TYPE (expr);
}
fcode = TREE_CODE (from);
tcode = TREE_CODE (to);
conv = build1 (IDENTITY_CONV, from, expr);
if (fcode == FUNCTION_TYPE)
{
from = build_pointer_type (from);
fcode = TREE_CODE (from);
conv = build_conv (LVALUE_CONV, from, conv);
}
else if (fcode == ARRAY_TYPE)
{
from = build_pointer_type (TREE_TYPE (from));
fcode = TREE_CODE (from);
conv = build_conv (LVALUE_CONV, from, conv);
}
else if (fromref || (expr && lvalue_p (expr)))
conv = build_conv (RVALUE_CONV, from, conv);
if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE)
{
tree part_conv = standard_conversion
(TREE_TYPE (to), TREE_TYPE (from), NULL_TREE);
if (part_conv)
{
conv = build_conv (TREE_CODE (part_conv), to, conv);
ICS_STD_RANK (conv) = ICS_STD_RANK (part_conv);
}
else
conv = NULL_TREE;
return conv;
}
if (same_type_p (from, to))
return conv;
if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
&& expr && null_ptr_cst_p (expr))
{
conv = build_conv (STD_CONV, to, conv);
}
else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
|| (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
{
conv = build_conv (STD_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
}
else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
&& TYPE_PRECISION (to) == TYPE_PRECISION (from))
{
conv = build_conv (STD_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
}
else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
{
enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
TREE_TYPE (to)))
;
else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
&& ufcode != FUNCTION_TYPE)
{
from = build_pointer_type
(cp_build_qualified_type (void_type_node,
cp_type_quals (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
{
tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
tree binfo = lookup_base (tbase, fbase, ba_check, NULL);
if (binfo && !binfo_from_vbase (binfo)
&& (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (TREE_TYPE (from)),
TREE_TYPE (TREE_TYPE (to)))))
{
from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PMEM_CONV, from, conv);
}
}
else if (IS_AGGR_TYPE (TREE_TYPE (from))
&& IS_AGGR_TYPE (TREE_TYPE (to)))
{
if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
{
from =
cp_build_qualified_type (TREE_TYPE (to),
cp_type_quals (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PTR_CONV, from, conv);
}
}
if (same_type_p (from, to))
;
else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
conv = build_conv (QUAL_CONV, to, conv);
else if (expr && string_conv_p (to, expr, 0))
conv = build_conv (QUAL_CONV, to, conv);
else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
{
conv = build_conv (PTR_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
}
else
return 0;
from = to;
}
else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
{
tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from));
tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to));
tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
tree binfo = lookup_base (tbase, fbase, ba_check, NULL);
if (!binfo || binfo_from_vbase (binfo)
|| !same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
|| !compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
|| cp_type_quals (fbase) != cp_type_quals (tbase))
return 0;
from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
conv = build_conv (PMEM_CONV, from, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
|| fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
return 0;
conv = build_conv (STD_CONV, to, conv);
if (fcode == POINTER_TYPE
|| (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK))
ICS_STD_RANK (conv) = PBOOL_RANK;
}
else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE
|| tcode == REAL_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
conv = build_conv (STD_CONV, to, conv);
if (to == type_promotes_to (from)
&& ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK;
}
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& is_properly_derived_from (from, to))
{
if (TREE_CODE (conv) == RVALUE_CONV)
conv = TREE_OPERAND (conv, 0);
conv = build_conv (BASE_CONV, to, conv);
NEED_TEMPORARY_P (conv) = 1;
}
else
return 0;
return conv;
}
static int
reference_related_p (t1, t2)
tree t1;
tree t2;
{
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
return (same_type_p (t1, t2)
|| (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
&& DERIVED_FROM_P (t1, t2)));
}
static int
reference_compatible_p (t1, t2)
tree t1;
tree t2;
{
return (reference_related_p (t1, t2)
&& at_least_as_qualified_p (t1, t2));
}
static tree
convert_class_to_reference (t, s, expr)
tree t;
tree s;
tree expr;
{
tree conversions;
tree arglist;
tree conv;
struct z_candidate *candidates;
struct z_candidate *cand;
candidates = 0;
arglist = build_int_2 (0, 0);
TREE_TYPE (arglist) = build_pointer_type (s);
arglist = build_tree_list (NULL_TREE, arglist);
for (conversions = lookup_conversions (s);
conversions;
conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
for (; fns; fns = OVL_NEXT (fns))
{
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
struct z_candidate *old_candidates = candidates;
if (TREE_CODE (f) == TEMPLATE_DECL)
{
candidates
= add_template_candidate (candidates,
f, s,
NULL_TREE,
arglist,
build_reference_type (t),
LOOKUP_NORMAL,
DEDUCE_CONV);
if (candidates != old_candidates)
{
f = candidates->fn;
t2 = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (t2) != REFERENCE_TYPE
|| !reference_compatible_p (t, TREE_TYPE (t2)))
candidates = candidates->next;
}
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
candidates
= add_function_candidate (candidates, f, s, arglist,
LOOKUP_NORMAL);
if (candidates != old_candidates)
candidates->basetype_path = TYPE_BINFO (s);
}
}
if (!any_viable (candidates))
return NULL_TREE;
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
conv = build1 (IDENTITY_CONV, s, expr);
conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
conv);
TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
ICS_USER_FLAG (conv) = 1;
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
cand->second_conv = conv;
return conv;
}
static tree
direct_reference_binding (type, conv)
tree type;
tree conv;
{
tree t = TREE_TYPE (type);
if (!same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (conv)))
{
conv = build_conv (BASE_CONV, t, conv);
NEED_TEMPORARY_P (conv) = 0;
}
return build_conv (REF_BIND, type, conv);
}
static tree
reference_binding (rto, rfrom, expr, flags)
tree rto, rfrom, expr;
int flags;
{
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
tree from = rfrom;
int related_p;
int compatible_p;
cp_lvalue_kind lvalue_p = clk_none;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
expr = instantiate_type (to, expr, itf_none);
if (expr == error_mark_node)
return NULL_TREE;
from = TREE_TYPE (expr);
}
if (TREE_CODE (from) == REFERENCE_TYPE)
{
lvalue_p = clk_ordinary;
from = TREE_TYPE (from);
}
else if (expr)
lvalue_p = real_lvalue_p (expr);
related_p = reference_related_p (to, from);
compatible_p = reference_compatible_p (to, from);
if (lvalue_p && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
conv = direct_reference_binding (rto, conv);
if ((lvalue_p & clk_bitfield) != 0
&& CP_TYPE_CONST_NON_VOLATILE_P (to))
NEED_TEMPORARY_P (conv) = 1;
return conv;
}
else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
{
conv = convert_class_to_reference (to, from, expr);
if (conv)
return direct_reference_binding (rto, conv);
}
if (flags & LOOKUP_NO_TEMP_BIND)
return NULL_TREE;
if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
return NULL_TREE;
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
return direct_reference_binding (rto, conv);
}
if (related_p && !at_least_as_qualified_p (to, from))
return NULL_TREE;
conv = implicit_conversion (to, from, expr, flags);
if (!conv)
return NULL_TREE;
conv = build_conv (REF_BIND, rto, conv);
NEED_TEMPORARY_P (conv) = 1;
return conv;
}
static tree
implicit_conversion (to, from, expr, flags)
tree to, from, expr;
int flags;
{
tree conv;
struct z_candidate *cand;
if (expr && TREE_CODE (expr) == OFFSET_REF)
{
expr = resolve_offset_ref (expr);
from = TREE_TYPE (expr);
}
if (from == error_mark_node || to == error_mark_node
|| expr == error_mark_node)
return NULL_TREE;
complete_type (from);
complete_type (to);
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
conv = standard_conversion (to, from, expr);
if (conv)
;
else if (expr != NULL_TREE
&& (IS_AGGR_TYPE (from)
|| IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
}
return conv;
}
static struct z_candidate *
add_candidate (candidates, fn, convs, viable)
struct z_candidate *candidates;
tree fn, convs;
int viable;
{
struct z_candidate *cand
= (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
cand->fn = fn;
cand->convs = convs;
cand->viable = viable;
cand->next = candidates;
return cand;
}
static struct z_candidate *
add_function_candidate (candidates, fn, ctype, arglist, flags)
struct z_candidate *candidates;
tree fn, ctype, arglist;
int flags;
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
tree convs;
tree parmnode, argnode;
int viable = 1;
if (DECL_CONSTRUCTOR_P (fn))
{
parmlist = skip_artificial_parms_for (fn, parmlist);
arglist = skip_artificial_parms_for (fn, arglist);
}
len = list_length (arglist);
convs = make_tree_vec (len);
parmnode = parmlist;
for (i = 0; i < len; ++i)
{
if (parmnode == NULL_TREE || parmnode == void_list_node)
break;
parmnode = TREE_CHAIN (parmnode);
}
if (i < len && parmnode)
viable = 0;
else if (!sufficient_parms_p (parmnode))
viable = 0;
if (! viable)
goto out;
parmnode = parmlist;
argnode = arglist;
for (i = 0; i < len; ++i)
{
tree arg = TREE_VALUE (argnode);
tree argtype = lvalue_type (arg);
tree t;
int is_this;
if (parmnode == void_list_node)
break;
is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
&& ! DECL_CONSTRUCTOR_P (fn));
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
if (ctype && is_this)
{
parmtype
= build_qualified_type (ctype,
TYPE_QUALS (TREE_TYPE (parmtype)));
parmtype = build_pointer_type (parmtype);
}
t = implicit_conversion (parmtype, argtype, arg, flags);
}
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
ICS_ELLIPSIS_FLAG (t) = 1;
}
if (t && is_this)
ICS_THIS_FLAG (t) = 1;
TREE_VEC_ELT (convs, i) = t;
if (! t)
{
viable = 0;
break;
}
if (ICS_BAD_FLAG (t))
viable = -1;
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
argnode = TREE_CHAIN (argnode);
}
out:
return add_candidate (candidates, fn, convs, viable);
}
static struct z_candidate *
add_conv_candidate (candidates, fn, obj, arglist)
struct z_candidate *candidates;
tree fn, obj, arglist;
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
tree parmlist, convs, parmnode, argnode;
for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
parmlist = TREE_TYPE (parmlist);
parmlist = TYPE_ARG_TYPES (parmlist);
len = list_length (arglist) + 1;
convs = make_tree_vec (len);
parmnode = parmlist;
argnode = arglist;
viable = 1;
flags = LOOKUP_NORMAL;
if (candidates && candidates->fn == totype)
return candidates;
for (i = 0; i < len; ++i)
{
tree arg = i == 0 ? obj : TREE_VALUE (argnode);
tree argtype = lvalue_type (arg);
tree t;
if (i == 0)
t = implicit_conversion (totype, argtype, arg, flags);
else if (parmnode == void_list_node)
break;
else if (parmnode)
t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
ICS_ELLIPSIS_FLAG (t) = 1;
}
TREE_VEC_ELT (convs, i) = t;
if (! t)
break;
if (ICS_BAD_FLAG (t))
viable = -1;
if (i == 0)
continue;
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
argnode = TREE_CHAIN (argnode);
}
if (i < len)
viable = 0;
if (!sufficient_parms_p (parmnode))
viable = 0;
return add_candidate (candidates, totype, convs, viable);
}
static struct z_candidate *
build_builtin_candidate (candidates, fnname, type1, type2,
args, argtypes, flags)
struct z_candidate *candidates;
tree fnname, type1, type2, *args, *argtypes;
int flags;
{
tree t, convs;
int viable = 1, i;
tree types[2];
types[0] = type1;
types[1] = type2;
convs = make_tree_vec (args[2] ? 3 : (args[1] ? 2 : 1));
for (i = 0; i < 2; ++i)
{
if (! args[i])
break;
t = implicit_conversion (types[i], argtypes[i], args[i], flags);
if (! t)
{
viable = 0;
t = build1 (IDENTITY_CONV, types[i], NULL_TREE);
}
else if (ICS_BAD_FLAG (t))
viable = 0;
TREE_VEC_ELT (convs, i) = t;
}
if (args[2])
{
TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1);
TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0);
t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags);
if (t)
TREE_VEC_ELT (convs, 0) = t;
else
viable = 0;
}
return add_candidate (candidates, fnname, convs, viable);
}
static int
is_complete (t)
tree t;
{
return COMPLETE_TYPE_P (complete_type (t));
}
static int
promoted_arithmetic_type_p (type)
tree type;
{
return ((INTEGRAL_TYPE_P (type)
&& same_type_p (type_promotes_to (type), type))
|| TREE_CODE (type) == REAL_TYPE);
}
static struct z_candidate *
add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
args, argtypes, flags)
struct z_candidate *candidates;
enum tree_code code, code2;
tree fnname, type1, type2, *args, *argtypes;
int flags;
{
switch (code)
{
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
args[1] = integer_zero_node;
type2 = integer_type_node;
break;
default:
break;
}
switch (code)
{
case POSTDECREMENT_EXPR:
case PREDECREMENT_EXPR:
if (TREE_CODE (type1) == BOOLEAN_TYPE)
return candidates;
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
{
type1 = build_reference_type (type1);
break;
}
return candidates;
case INDIRECT_REF:
if (TREE_CODE (type1) == POINTER_TYPE
&& (TYPE_PTROB_P (type1)
|| TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
break;
return candidates;
case CONVERT_EXPR:
if (TREE_CODE (type1) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
break;
case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1))
break;
return candidates;
case BIT_NOT_EXPR:
if (INTEGRAL_TYPE_P (type1))
break;
return candidates;
case MEMBER_REF:
if (TREE_CODE (type1) == POINTER_TYPE
&& (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)))
{
tree c1 = TREE_TYPE (type1);
tree c2 = (TYPE_PTRMEMFUNC_P (type2)
? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
: TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
&& (TYPE_PTRMEMFUNC_P (type2)
|| is_complete (TREE_TYPE (TREE_TYPE (type2)))))
break;
}
return candidates;
case MINUS_EXPR:
if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2))
break;
if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
}
case MULT_EXPR:
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
return candidates;
case EQ_EXPR:
case NE_EXPR:
if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
|| (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
break;
if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1))
&& null_ptr_cst_p (args[1]))
{
type2 = type1;
break;
}
if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
&& null_ptr_cst_p (args[0]))
{
type1 = type2;
break;
}
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
case GE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
if (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
break;
if (TREE_CODE (type1) == ENUMERAL_TYPE && TREE_CODE (type2) == ENUMERAL_TYPE)
break;
if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
{
type2 = type1;
break;
}
if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2))
{
type1 = type2;
break;
}
return candidates;
case PLUS_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
case ARRAY_REF:
if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2))
{
type1 = ptrdiff_type_node;
break;
}
if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
}
return candidates;
case TRUNC_MOD_EXPR:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
return candidates;
case MODIFY_EXPR:
switch (code2)
{
case PLUS_EXPR:
case MINUS_EXPR:
if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
}
case MULT_EXPR:
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
return candidates;
case TRUNC_MOD_EXPR:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
break;
return candidates;
case NOP_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
|| (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
|| (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
|| ((TYPE_PTRMEMFUNC_P (type1)
|| TREE_CODE (type1) == POINTER_TYPE)
&& null_ptr_cst_p (args[1])))
{
type2 = type1;
break;
}
return candidates;
default:
my_friendly_abort (367);
}
type1 = build_reference_type (type1);
break;
case COND_EXPR:
if (promoted_arithmetic_type_p (type1)
&& promoted_arithmetic_type_p (type2))
break;
if (!(TREE_CODE (type1) == POINTER_TYPE
|| TYPE_PTRMEM_P (type1)
|| TYPE_PTRMEMFUNC_P (type1))
|| !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2)))
return candidates;
break;
return candidates;
default:
my_friendly_abort (367);
}
if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
|| (TREE_CODE (type1) == POINTER_TYPE
&& TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1)
|| IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
candidates = build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
return build_builtin_candidate
(candidates, fnname, type2, type2, args, argtypes, flags);
}
return build_builtin_candidate
(candidates, fnname, type1, type2, args, argtypes, flags);
}
tree
type_decays_to (type)
tree type;
{
if (TREE_CODE (type) == ARRAY_TYPE)
return build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (type) == FUNCTION_TYPE)
return build_pointer_type (type);
return type;
}
static struct z_candidate *
add_builtin_candidates (candidates, code, code2, fnname, args, flags)
struct z_candidate *candidates;
enum tree_code code, code2;
tree fnname, *args;
int flags;
{
int ref1, i;
int enum_p = 0;
tree type, argtypes[3];
tree types[2];
for (i = 0; i < 3; ++i)
{
if (args[i])
argtypes[i] = lvalue_type (args[i]);
else
argtypes[i] = NULL_TREE;
}
switch (code)
{
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case PREDECREMENT_EXPR:
case MODIFY_EXPR:
ref1 = 1;
break;
case TRUTH_NOT_EXPR:
return build_builtin_candidate
(candidates, fnname, boolean_type_node,
NULL_TREE, args, argtypes, flags);
case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR:
return build_builtin_candidate
(candidates, fnname, boolean_type_node,
boolean_type_node, args, argtypes, flags);
case ADDR_EXPR:
case COMPOUND_EXPR:
case COMPONENT_REF:
return candidates;
case COND_EXPR:
case EQ_EXPR:
case NE_EXPR:
case LT_EXPR:
case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
enum_p = 1;
default:
ref1 = 0;
}
types[0] = types[1] = NULL_TREE;
for (i = 0; i < 2; ++i)
{
if (! args[i])
;
else if (IS_AGGR_TYPE (argtypes[i]))
{
tree convs;
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return candidates;
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]);
types[i] = tree_cons
(NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
}
else if (! convs)
return candidates;
for (; convs; convs = TREE_CHAIN (convs))
{
type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
if (i == 0 && ref1
&& (TREE_CODE (type) != REFERENCE_TYPE
|| CP_TYPE_CONST_P (TREE_TYPE (type))))
continue;
if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
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]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
if (! value_member (type, types[i]))
types[i] = tree_cons (NULL_TREE, type, types[i]);
}
}
else
{
if (code == COND_EXPR && real_lvalue_p (args[i]))
types[i] = tree_cons
(NULL_TREE, build_reference_type (argtypes[i]), types[i]);
type = non_reference (argtypes[i]);
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]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
types[i] = tree_cons (NULL_TREE, type, types[i]);
}
}
for (; types[0]; types[0] = TREE_CHAIN (types[0]))
{
if (types[1])
for (type = types[1]; type; type = TREE_CHAIN (type))
candidates = add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
TREE_VALUE (type), args, argtypes, flags);
else
candidates = add_builtin_candidate
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
NULL_TREE, args, argtypes, flags);
}
return candidates;
}
static struct z_candidate*
add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
arglist, return_type, flags,
obj, strict)
struct z_candidate *candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
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;
struct z_candidate *cand;
int i;
tree fn;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
|| DECL_BASE_CONSTRUCTOR_P (tmpl))
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl)))
args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
return_type, strict, -1);
if (i != 0)
return candidates;
fn = instantiate_template (tmpl, targs);
if (fn == error_mark_node)
return candidates;
if (obj != NULL_TREE)
cand = add_conv_candidate (candidates, fn, obj, arglist);
else
cand = add_function_candidate (candidates, fn, ctype,
arglist, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
cand->template = tree_cons (tmpl, targs, NULL_TREE);
else
cand->template = DECL_TEMPLATE_INFO (fn);
return cand;
}
static struct z_candidate *
add_template_candidate (candidates, tmpl, ctype, explicit_targs,
arglist, return_type, flags, strict)
struct z_candidate *candidates;
tree tmpl, ctype, explicit_targs, arglist, return_type;
int flags;
unification_kind_t strict;
{
return
add_template_candidate_real (candidates, tmpl, ctype,
explicit_targs, arglist, return_type, flags,
NULL_TREE, strict);
}
static struct z_candidate *
add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
struct z_candidate *candidates;
tree tmpl, obj, arglist, return_type;
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
arglist, return_type, 0, obj, DEDUCE_CONV);
}
static int
any_viable (cands)
struct z_candidate *cands;
{
for (; cands; cands = cands->next)
if (pedantic ? cands->viable == 1 : cands->viable)
return 1;
return 0;
}
static struct z_candidate *
splice_viable (cands)
struct z_candidate *cands;
{
struct z_candidate **p = &cands;
for (; *p; )
{
if (pedantic ? (*p)->viable == 1 : (*p)->viable)
p = &((*p)->next);
else
*p = (*p)->next;
}
return cands;
}
static tree
build_this (obj)
tree obj;
{
return build_unary_op (ADDR_EXPR, obj, 0);
}
static void
print_z_candidates (candidates)
struct z_candidate *candidates;
{
const char *str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
{
if (TREE_VEC_LENGTH (candidates->convs) == 3)
error ("%s %D(%T, %T, %T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
else if (TREE_VEC_LENGTH (candidates->convs) == 2)
error ("%s %D(%T, %T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
else
error ("%s %D(%T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
}
else if (TYPE_P (candidates->fn))
error ("%s %T <conversion>", str, candidates->fn);
else
cp_error_at ("%s %+#D%s", str, candidates->fn,
candidates->viable == -1 ? " <near match>" : "");
str = " ";
}
}
static struct z_candidate *
build_user_type_conversion_1 (totype, expr, flags)
tree totype, expr;
int flags;
{
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, *p;
tree args = NULL_TREE;
tree templates = NULL_TREE;
my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
|| !DERIVED_FROM_P (totype, fromtype), 20011226);
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype),
complete_ctor_identifier,
0);
if (IS_AGGR_TYPE (fromtype))
convs = lookup_conversions (fromtype);
candidates = 0;
flags |= LOOKUP_NO_CONVERSION;
if (ctors)
{
tree t;
ctors = TREE_VALUE (ctors);
t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
args = build_tree_list (NULL_TREE, expr);
my_friendly_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)),
20011226);
args = tree_cons (NULL_TREE, t, args);
}
for (; ctors; ctors = OVL_NEXT (ctors))
{
tree ctor = OVL_CURRENT (ctors);
if (DECL_NONCONVERTING_P (ctor))
continue;
if (TREE_CODE (ctor) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, ctor, templates);
candidates =
add_template_candidate (candidates, ctor, totype,
NULL_TREE, args, NULL_TREE, flags,
DEDUCE_CALL);
}
else
candidates = add_function_candidate (candidates, ctor, totype,
args, flags);
if (candidates)
{
candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
candidates->basetype_path = TYPE_BINFO (totype);
}
}
if (convs)
args = build_tree_list (NULL_TREE, build_this (expr));
for (; convs; convs = TREE_CHAIN (convs))
{
tree fns = TREE_VALUE (convs);
int convflags = LOOKUP_NO_CONVERSION;
tree ics;
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
else
ics = error_mark_node;
if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
;
else if (ics)
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
struct z_candidate *old_candidates = candidates;
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, fn, templates);
candidates =
add_template_candidate (candidates, fn, fromtype, NULL_TREE,
args, totype, flags,
DEDUCE_CONV);
}
else
candidates = add_function_candidate (candidates, fn, fromtype,
args, flags);
if (candidates != old_candidates)
{
if (TREE_CODE (fn) == TEMPLATE_DECL)
ics = implicit_conversion
(totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
0, convflags);
candidates->second_conv = ics;
candidates->basetype_path = TYPE_BINFO (fromtype);
if (ics == NULL_TREE)
candidates->viable = 0;
else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
candidates->viable = -1;
}
}
}
if (! any_viable (candidates))
{
#if 0
if (flags & LOOKUP_COMPLAIN)
{
if (candidates && ! candidates->next)
;
else
error ("no viable candidates");
}
#endif
return 0;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("conversion from `%T' to `%T' is ambiguous",
fromtype, totype);
print_z_candidates (candidates);
}
cand = candidates;
cand->second_conv = build1 (AMBIG_CONV, totype, expr);
ICS_USER_FLAG (cand->second_conv) = 1;
ICS_BAD_FLAG (cand->second_conv) = 1;
return cand;
}
for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
p = &(TREE_OPERAND (*p, 0));
*p = build
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
expr, build_ptr_wrapper (cand));
ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
if (cand->viable == -1)
ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
return cand;
}
tree
build_user_type_conversion (totype, expr, flags)
tree totype, expr;
int flags;
{
struct z_candidate *cand
= build_user_type_conversion_1 (totype, expr, flags);
if (cand)
{
if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node;
return convert_from_reference (convert_like (cand->second_conv, expr));
}
return NULL_TREE;
}
static tree
resolve_args (args)
tree args;
{
tree t;
for (t = args; t; t = TREE_CHAIN (t))
{
tree arg = TREE_VALUE (t);
if (arg == error_mark_node)
return error_mark_node;
else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
error ("invalid use of void expression");
return error_mark_node;
}
else if (TREE_CODE (arg) == OFFSET_REF)
arg = resolve_offset_ref (arg);
arg = convert_from_reference (arg);
TREE_VALUE (t) = arg;
}
return args;
}
tree
build_new_function_call (fn, args)
tree fn, args;
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
int template_only = 0;
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (fn, 1);
fn = TREE_OPERAND (fn, 0);
template_only = 1;
}
if (really_overloaded_fn (fn))
{
tree t1;
tree templates = NULL_TREE;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
tree t = OVL_FUNCTION (t1);
if (TREE_CODE (t) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
(candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else if (! template_only)
candidates = add_function_candidate
(candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
{
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_FUNCTION (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
error ("call of overloaded `%D(%A)' is ambiguous",
DECL_NAME (OVL_FUNCTION (fn)), args);
print_z_candidates (candidates);
return error_mark_node;
}
return build_over_call (cand, args, LOOKUP_NORMAL);
}
fn = OVL_CURRENT (fn);
return build_function_call (fn, args);
}
static tree
build_object_call (obj, args)
tree obj, args;
{
struct z_candidate *candidates = 0, *cand;
tree fns, convs, mem_args = NULL_TREE;
tree type = TREE_TYPE (obj);
if (TYPE_PTRMEMFUNC_P (type))
{
error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
return error_mark_node;
}
fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname (CALL_EXPR), 1);
if (fns == error_mark_node)
return error_mark_node;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
if (fns)
{
tree base = BINFO_TYPE (TREE_PURPOSE (fns));
mem_args = tree_cons (NULL_TREE, build_this (obj), args);
for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
candidates
= add_template_candidate (candidates, fn, base, NULL_TREE,
mem_args, NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else
candidates = add_function_candidate
(candidates, fn, base, mem_args, LOOKUP_NORMAL);
if (candidates)
candidates->basetype_path = TYPE_BINFO (type);
}
}
convs = lookup_conversions (type);
for (; convs; convs = TREE_CHAIN (convs))
{
tree fns = TREE_VALUE (convs);
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
if ((TREE_CODE (totype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
|| (TREE_CODE (totype) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
|| (TREE_CODE (totype) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE))
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
candidates = add_template_conv_candidate (candidates,
fn,
obj,
args,
totype);
}
else
candidates = add_conv_candidate (candidates, fn, obj, args);
}
}
if (! any_viable (candidates))
{
error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
if (TREE_CODE (cand->fn) == FUNCTION_DECL
&& DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
obj = convert_like_with_context
(TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
return build_function_call (obj, args);
}
static void
op_error (code, code2, arg1, arg2, arg3, problem)
enum tree_code code, code2;
tree arg1, arg2, arg3;
const char *problem;
{
const char *opname;
if (code == MODIFY_EXPR)
opname = assignment_operator_name_info[code2].name;
else
opname = operator_name_info[code].name;
switch (code)
{
case COND_EXPR:
error ("%s for `%T ? %T : %T' operator", problem,
error_type (arg1), error_type (arg2), error_type (arg3));
break;
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
break;
case ARRAY_REF:
error ("%s for `%T [%T]' operator", problem,
error_type (arg1), error_type (arg2));
break;
default:
if (arg2)
error ("%s for `%T %s %T' operator", problem,
error_type (arg1), opname, error_type (arg2));
else
error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
}
}
static tree
conditional_conversion (e1, e2)
tree e1;
tree e2;
{
tree t1 = non_reference (TREE_TYPE (e1));
tree t2 = non_reference (TREE_TYPE (e2));
tree conv;
if (real_lvalue_p (e2))
{
conv = implicit_conversion (build_reference_type (t2),
t1,
e1,
LOOKUP_NO_TEMP_BIND);
if (conv)
return conv;
}
if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
&& same_or_base_type_p (TYPE_MAIN_VARIANT (t2),
TYPE_MAIN_VARIANT (t1)))
{
if (at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
if (!same_type_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2)))
conv = build_conv (BASE_CONV, t2, conv);
return conv;
}
else
return NULL_TREE;
}
return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
}
tree
build_conditional_expr (arg1, arg2, arg3)
tree arg1;
tree arg2;
tree arg3;
{
tree arg2_type;
tree arg3_type;
tree result;
tree result_type = NULL_TREE;
int lvalue_p = 1;
struct z_candidate *candidates = 0;
struct z_candidate *cand;
if (!arg2)
{
if (pedantic)
pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
arg1 = arg2 = save_expr (arg1);
}
arg1 = cp_convert (boolean_type_node, arg1);
if (arg1 == error_mark_node
|| arg2 == error_mark_node
|| arg3 == error_mark_node
|| TREE_TYPE (arg1) == error_mark_node
|| TREE_TYPE (arg2) == error_mark_node
|| TREE_TYPE (arg3) == error_mark_node)
return error_mark_node;
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
{
if (!VOID_TYPE_P (arg2_type))
arg2 = decay_conversion (arg2);
if (!VOID_TYPE_P (arg3_type))
arg3 = decay_conversion (arg3);
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
if ((TREE_CODE (arg2) == THROW_EXPR)
^ (TREE_CODE (arg3) == THROW_EXPR))
result_type = ((TREE_CODE (arg2) == THROW_EXPR)
? arg3_type : arg2_type);
else if (VOID_TYPE_P (arg2_type) && VOID_TYPE_P (arg3_type))
result_type = void_type_node;
else
{
error ("`%E' has type `void' and is not a throw-expression",
VOID_TYPE_P (arg2_type) ? arg2 : arg3);
return error_mark_node;
}
lvalue_p = 0;
goto valid_operands;
}
else if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
tree conv2 = conditional_conversion (arg2, arg3);
tree conv3 = conditional_conversion (arg3, arg2);
if ((conv2 && !ICS_BAD_FLAG (conv2)
&& conv3 && !ICS_BAD_FLAG (conv3))
|| (conv2 && TREE_CODE (conv2) == AMBIG_CONV)
|| (conv3 && TREE_CODE (conv3) == AMBIG_CONV))
{
error ("operands to ?: have different types");
return error_mark_node;
}
else if (conv2 && !ICS_BAD_FLAG (conv2))
{
arg2 = convert_like (conv2, arg2);
arg2 = convert_from_reference (arg2);
if (!same_type_p (TREE_TYPE (arg2), arg3_type))
arg2 = build1 (NOP_EXPR, arg3_type, arg2);
arg2_type = TREE_TYPE (arg2);
}
else if (conv3 && !ICS_BAD_FLAG (conv3))
{
arg3 = convert_like (conv3, arg3);
arg3 = convert_from_reference (arg3);
if (!same_type_p (TREE_TYPE (arg3), arg2_type))
arg3 = build1 (NOP_EXPR, arg2_type, arg3);
arg3_type = TREE_TYPE (arg3);
}
}
if (real_lvalue_p (arg2) && real_lvalue_p (arg3) &&
same_type_p (arg2_type, arg3_type))
{
result_type = arg2_type;
goto valid_operands;
}
lvalue_p = 0;
if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
tree args[3];
tree conv;
args[0] = arg2;
args[1] = arg3;
args[2] = arg1;
candidates = add_builtin_candidates (candidates,
COND_EXPR,
NOP_EXPR,
ansi_opname (COND_EXPR),
args,
LOOKUP_NORMAL);
if (!any_viable (candidates))
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
conv = TREE_VEC_ELT (cand->convs, 0);
arg1 = convert_like (conv, arg1);
conv = TREE_VEC_ELT (cand->convs, 1);
arg2 = convert_like (conv, arg2);
conv = TREE_VEC_ELT (cand->convs, 2);
arg3 = convert_like (conv, arg3);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg2)) && real_lvalue_p (arg2))
arg2 = ocp_convert (TREE_TYPE (arg2), arg2,
CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
else
arg2 = decay_conversion (arg2);
arg2_type = TREE_TYPE (arg2);
if (IS_AGGR_TYPE (TREE_TYPE (arg3)) && real_lvalue_p (arg3))
arg3 = ocp_convert (TREE_TYPE (arg3), arg3,
CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
else
arg3 = decay_conversion (arg3);
arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == error_mark_node)
return error_mark_node;
if (same_type_p (arg2_type, arg3_type))
result_type = arg2_type;
else if ((ARITHMETIC_TYPE_P (arg2_type)
|| TREE_CODE (arg2_type) == ENUMERAL_TYPE)
&& (ARITHMETIC_TYPE_P (arg3_type)
|| TREE_CODE (arg3_type) == ENUMERAL_TYPE))
{
result_type = type_after_usual_arithmetic_conversions (arg2_type,
arg3_type);
if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& TREE_CODE (arg3_type) == ENUMERAL_TYPE)
warning ("enumeral mismatch in conditional expression: `%T' vs `%T'",
arg2_type, arg3_type);
else if (extra_warnings
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type, type_promotes_to (arg3_type)))))
warning ("enumeral and non-enumeral type in conditional expression");
arg2 = perform_implicit_conversion (result_type, arg2);
arg3 = perform_implicit_conversion (result_type, arg3);
}
else if ((null_ptr_cst_p (arg2)
&& (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
|| TYPE_PTRMEMFUNC_P (arg3_type)))
|| (null_ptr_cst_p (arg3)
&& (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type)
|| TYPE_PTRMEMFUNC_P (arg2_type)))
|| (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
|| (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
|| (TYPE_PTRMEMFUNC_P (arg2_type)
&& TYPE_PTRMEMFUNC_P (arg3_type)))
{
result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
arg3, "conditional expression");
arg2 = perform_implicit_conversion (result_type, arg2);
arg3 = perform_implicit_conversion (result_type, arg3);
}
if (!result_type)
{
error ("operands to ?: have different types");
return error_mark_node;
}
valid_operands:
result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
if (!lvalue_p && IS_AGGR_TYPE (result_type))
result = build_target_expr_with_type (result, result_type);
if (!lvalue_p && real_lvalue_p (result))
result = build1 (NON_LVALUE_EXPR, result_type, result);
return result;
}
tree
build_new_op (code, flags, arg1, arg2, arg3)
enum tree_code code;
int flags;
tree arg1, arg2, arg3;
{
struct z_candidate *candidates = 0, *cand;
tree fns, mem_arglist = NULL_TREE, arglist, fnname;
enum tree_code code2 = NOP_EXPR;
tree templates = NULL_TREE;
tree conv;
if (arg1 == error_mark_node
|| arg2 == error_mark_node
|| arg3 == error_mark_node)
return error_mark_node;
if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
{
error ("`%D' must be declared before use", arg1);
return error_mark_node;
}
if (code == MODIFY_EXPR)
{
code2 = TREE_CODE (arg3);
arg3 = NULL_TREE;
fnname = ansi_assopname (code2);
}
else
fnname = ansi_opname (code);
if (TREE_CODE (arg1) == OFFSET_REF)
arg1 = resolve_offset_ref (arg1);
arg1 = convert_from_reference (arg1);
switch (code)
{
case NEW_EXPR:
case VEC_NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
my_friendly_abort (981018);
case CALL_EXPR:
return build_object_call (arg1, arg2);
default:
break;
}
if (arg2)
{
if (TREE_CODE (arg2) == OFFSET_REF)
arg2 = resolve_offset_ref (arg2);
arg2 = convert_from_reference (arg2);
}
if (arg3)
{
if (TREE_CODE (arg3) == OFFSET_REF)
arg3 = resolve_offset_ref (arg3);
arg3 = convert_from_reference (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;
}
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);
fns = lookup_function_nonclass (fnname, arglist);
if (fns && TREE_CODE (fns) == TREE_LIST)
fns = TREE_VALUE (fns);
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, fn, templates);
candidates
= add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
candidates = add_function_candidate (candidates, fn, NULL_TREE,
arglist, flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
{
fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
if (fns == error_mark_node)
return fns;
}
else
fns = NULL_TREE;
if (fns)
{
tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree this_arglist;
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
this_arglist = mem_arglist;
else
this_arglist = arglist;
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, fn, templates);
candidates
= add_template_candidate (candidates, fn, basetype, NULL_TREE,
this_arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
candidates = add_function_candidate
(candidates, fn, basetype, this_arglist, flags);
if (candidates)
candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
}
}
{
tree args[3];
if (code == COND_EXPR)
{
args[0] = arg2;
args[1] = arg3;
args[2] = arg1;
}
else
{
args[0] = arg1;
args[1] = arg2;
args[2] = NULL_TREE;
}
candidates = add_builtin_candidates
(candidates, code, code2, fnname, args, flags);
}
if (! any_viable (candidates))
{
switch (code)
{
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
if (flags & LOOKUP_COMPLAIN)
pedwarn ("no `%D(int)' declared for postfix `%s', trying prefix operator instead",
fnname,
operator_name_info[code].name);
if (code == POSTINCREMENT_EXPR)
code = PREINCREMENT_EXPR;
else
code = PREDECREMENT_EXPR;
return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE);
case ADDR_EXPR:
case COMPOUND_EXPR:
case COMPONENT_REF:
return NULL_TREE;
default:
break;
}
if (flags & LOOKUP_COMPLAIN)
{
op_error (code, code2, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
}
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
print_z_candidates (candidates);
}
return error_mark_node;
}
if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{
extern int warn_synth;
if (warn_synth
&& fnname == ansi_assopname (NOP_EXPR)
&& DECL_ARTIFICIAL (cand->fn)
&& candidates->next
&& ! candidates->next->next)
{
warning ("using synthesized `%#D' for copy assignment",
cand->fn);
cp_warning_at (" where cfront would use `%#D'",
cand == candidates
? candidates->next->fn
: candidates->fn);
}
return build_over_call
(cand,
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
? mem_arglist : arglist,
LOOKUP_NORMAL);
}
switch (code)
{
case GT_EXPR:
case LT_EXPR:
case GE_EXPR:
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE
&& (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
!= TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
{
warning ("comparison between `%#T' and `%#T'",
TREE_TYPE (arg1), TREE_TYPE (arg2));
}
break;
default:
break;
}
conv = TREE_VEC_ELT (cand->convs, 0);
if (TREE_CODE (conv) == REF_BIND)
conv = TREE_OPERAND (conv, 0);
arg1 = convert_like (conv, arg1);
if (arg2)
{
conv = TREE_VEC_ELT (cand->convs, 1);
if (TREE_CODE (conv) == REF_BIND)
conv = TREE_OPERAND (conv, 0);
arg2 = convert_like (conv, arg2);
}
if (arg3)
{
conv = TREE_VEC_ELT (cand->convs, 2);
if (TREE_CODE (conv) == REF_BIND)
conv = TREE_OPERAND (conv, 0);
arg3 = convert_like (conv, arg3);
}
builtin:
switch (code)
{
case MODIFY_EXPR:
return build_modify_expr (arg1, code2, arg2);
case INDIRECT_REF:
return build_indirect_ref (arg1, "unary *");
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case GT_EXPR:
case LT_EXPR:
case GE_EXPR:
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case TRUNC_MOD_EXPR:
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
return cp_build_binary_op (code, arg1, arg2);
case CONVERT_EXPR:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case POSTDECREMENT_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
return build_unary_op (code, arg1, candidates != 0);
case ARRAY_REF:
return build_array_ref (arg1, arg2);
case COND_EXPR:
return build_conditional_expr (arg1, arg2, arg3);
case MEMBER_REF:
return build_m_component_ref
(build_indirect_ref (arg1, NULL), arg2);
case ADDR_EXPR:
case COMPONENT_REF:
case COMPOUND_EXPR:
return NULL_TREE;
default:
my_friendly_abort (367);
return NULL_TREE;
}
}
tree
build_op_delete_call (code, addr, size, flags, placement)
enum tree_code code;
tree addr, size, placement;
int flags;
{
tree fn = NULL_TREE;
tree fns, fnname, fntype, argtypes, args, type;
int pass;
if (addr == error_mark_node)
return error_mark_node;
type = TREE_TYPE (TREE_TYPE (addr));
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
fnname = ansi_opname (code);
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
{
fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
if (fns == error_mark_node)
return error_mark_node;
}
else
fns = NULL_TREE;
if (fns == NULL_TREE)
fns = lookup_name_nonclass (fnname);
if (placement)
{
argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
args = TREE_CHAIN (TREE_OPERAND (placement, 1));
}
else
{
argtypes = void_list_node;
args = NULL_TREE;
}
addr = cp_convert (ptr_type_node, addr);
for (pass = 0; pass < (placement ? 1 : 2); ++pass)
{
if (pass == 0)
argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
else
argtypes = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, sizetype,
void_list_node));
fntype = build_function_type (void_type_node, argtypes);
for (fn = BASELINK_P (fns) ? TREE_VALUE (fns) : fns;
fn;
fn = OVL_NEXT (fn))
{
tree t;
t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
NULL_TREE);
if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
break;
}
if (fn)
break;
}
if (fn)
{
fn = OVL_CURRENT (fn);
if (DECL_CLASS_SCOPE_P (fn))
enforce_access (type, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
else
args = tree_cons (NULL_TREE, addr,
build_tree_list (NULL_TREE, size));
return build_function_call (fn, args);
}
if (placement)
return NULL_TREE;
error ("no suitable `operator delete' for `%T'", type);
return error_mark_node;
}
int
enforce_access (basetype_path, decl)
tree basetype_path;
tree decl;
{
int accessible;
accessible = accessible_p (basetype_path, decl);
if (!accessible)
{
if (TREE_PRIVATE (decl))
cp_error_at ("`%+#D' is private", decl);
else if (TREE_PROTECTED (decl))
cp_error_at ("`%+#D' is protected", decl);
else
cp_error_at ("`%+#D' is inaccessible", decl);
error ("within this context");
return 0;
}
return 1;
}
static int really_call_constructor_p (tree, tree, tree);
static int
really_call_constructor_p (expr, convfn, totype)
tree expr, convfn, totype;
{
if (0 && ! NEED_TEMPORARY_P (convfn)
&& TREE_CODE (expr) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (convfn)) == METHOD_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (convfn))) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn)))) == RECORD_TYPE
&& TREE_TYPE (TREE_TYPE (TREE_TYPE (convfn))) == totype
&& TREE_TYPE (expr) == totype)
return 0;
return 1;
}
static tree
convert_like_real (convs, expr, fn, argnum, inner)
tree convs, expr;
tree fn;
int argnum;
int inner;
{
int savew, savee;
tree totype = TREE_TYPE (convs);
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
&& TREE_CODE (convs) != AMBIG_CONV
&& TREE_CODE (convs) != REF_BIND)
{
tree t = convs;
for (; t; t = TREE_OPERAND (t, 0))
{
if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
expr = convert_like_real (t, expr, fn, argnum, 1);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
return convert_like_real (t, expr, fn, argnum, 1);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);
if (fn)
pedwarn (" initializing argument %P of `%D'", argnum, fn);
return cp_convert (totype, expr);
}
if (!inner)
expr = dubious_conversion_warnings
(totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
{
struct z_candidate *cand
= WRAPPER_PTR (TREE_OPERAND (convs, 1));
tree convfn = cand->fn;
tree args;
if (DECL_CONSTRUCTOR_P (convfn))
{
tree t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));
args = build_tree_list (NULL_TREE, expr);
if (DECL_HAS_IN_CHARGE_PARM_P (convfn)
|| DECL_HAS_VTT_PARM_P (convfn))
abort ();
args = tree_cons (NULL_TREE, t, args);
}
else
args = build_this (expr);
expr = build_over_call (cand, args, LOOKUP_NORMAL);
if (DECL_CONSTRUCTOR_P (convfn))
expr = build_cplus_new (totype, expr);
if (IS_AGGR_TYPE (totype)
&& really_call_constructor_p (expr, convfn, totype)
&& (inner >= 0 || !lvalue_p (expr)))
{
savew = warningcount, savee = errorcount;
expr = build_new_method_call
(NULL_TREE, complete_ctor_identifier,
build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION);
if (fn)
{
if (warningcount > savew)
warning
(" initializing argument %P of `%D' from result of `%D'",
argnum, fn, convfn);
else if (errorcount > savee)
error
(" initializing argument %P of `%D' from result of `%D'",
argnum, fn, convfn);
}
else
{
if (warningcount > savew)
warning (" initializing temporary from result of `%D'",
convfn);
else if (errorcount > savee)
error (" initializing temporary from result of `%D'",
convfn);
}
expr = build_cplus_new (totype, expr);
}
return expr;
}
case IDENTITY_CONV:
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, itf_complain);
return expr;
case AMBIG_CONV:
return build_user_type_conversion
(totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
default:
break;
};
expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
TREE_CODE (convs) == REF_BIND ? -1 : 1);
if (expr == error_mark_node)
return error_mark_node;
if (TREE_CODE (convs) != REF_BIND
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
expr = decl_constant_value (expr);
switch (TREE_CODE (convs))
{
case RVALUE_CONV:
if (! IS_AGGR_TYPE (totype))
return expr;
case BASE_CONV:
if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))
{
tree base_ptr = build_pointer_type (totype);
expr = build_unary_op (ADDR_EXPR, expr, 0);
expr = perform_implicit_conversion (base_ptr, expr);
expr = build_indirect_ref (expr, "implicit conversion");
return expr;
}
savew = warningcount, savee = errorcount;
expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
build_tree_list (NULL_TREE, expr),
TYPE_BINFO (totype),
LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
if (fn)
{
if (warningcount > savew)
warning (" initializing argument %P of `%D'", argnum, fn);
else if (errorcount > savee)
error (" initializing argument %P of `%D'", argnum, fn);
}
return build_cplus_new (totype, expr);
case REF_BIND:
{
tree ref_type = totype;
if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
expr = build_target_expr_with_type (expr, type);
}
expr = build_unary_op (ADDR_EXPR, expr, 1);
if (expr == error_mark_node)
return error_mark_node;
expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),
expr);
expr = build1 (NOP_EXPR, ref_type, expr);
return expr;
}
case LVALUE_CONV:
return decay_conversion (expr);
case QUAL_CONV:
string_conv_p (totype, expr, 1);
break;
default:
break;
}
return ocp_convert (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
tree
convert_arg_to_ellipsis (arg)
tree arg;
{
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg))
< TYPE_PRECISION (double_type_node)))
arg = cp_convert (double_type_node, arg);
else
arg = default_conversion (arg);
arg = require_complete_type (arg);
if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
{
warning ("cannot pass objects of non-POD type `%#T' through `...'",
TREE_TYPE (arg));
}
return arg;
}
tree
build_x_va_arg (expr, type)
tree expr;
tree type;
{
if (processing_template_decl)
return build_min (VA_ARG_EXPR, type, expr);
type = complete_type_or_else (type, NULL_TREE);
if (expr == error_mark_node || !type)
return error_mark_node;
if (! pod_type_p (type))
{
warning ("cannot receive objects of non-POD type `%#T' through `...'",
type);
}
return build_va_arg (expr, type);
}
tree
convert_type_from_ellipsis (type)
tree type;
{
tree promote;
if (TREE_CODE (type) == ARRAY_TYPE)
promote = build_pointer_type (TREE_TYPE (type));
else if (TREE_CODE (type) == FUNCTION_TYPE)
promote = build_pointer_type (type);
else
promote = type_promotes_to (type);
return same_type_p (type, promote) ? NULL_TREE : promote;
}
tree
convert_default_arg (type, arg, fn, parmnum)
tree type;
tree arg;
tree fn;
int parmnum;
{
if (TREE_CODE (arg) == DEFAULT_ARG)
{
unprocessed_defarg_fn (fn);
return build1 (NOP_EXPR, type, integer_zero_node);
}
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
arg = break_out_target_exprs (arg);
if (TREE_CODE (arg) == CONSTRUCTOR)
{
arg = digest_init (type, arg, 0);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum);
}
else
{
if (TREE_HAS_CONSTRUCTOR (arg))
arg = copy_node (arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum);
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
arg = default_conversion (arg);
}
return arg;
}
static tree
build_over_call (cand, args, flags)
struct z_candidate *cand;
tree args;
int flags;
{
tree fn = cand->fn;
tree convs = cand->convs;
tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
tree conv, arg, val;
int i = 0;
int is_method = 0;
if (cand->warnings)
for (val = cand->warnings; val; val = TREE_CHAIN (val))
joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
enforce_access (cand->basetype_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
arg = args;
if (DECL_CONSTRUCTOR_P (fn))
{
converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
abort ();
if (DECL_HAS_VTT_PARM_P (fn))
{
converted_args = tree_cons
(NULL_TREE, TREE_VALUE (arg), converted_args);
arg = TREE_CHAIN (arg);
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 t;
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
TREE_TYPE (argtype), fn);
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
TREE_TYPE (parmtype), ba_ignore, NULL);
t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
converted_args = tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
is_method = 1;
}
for (; arg && parm;
parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
{
tree type = TREE_VALUE (parm);
conv = TREE_VEC_ELT (convs, i);
val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method);
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
val = default_conversion (val);
converted_args = tree_cons (NULL_TREE, val, converted_args);
}
for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
converted_args
= tree_cons (NULL_TREE,
convert_default_arg (TREE_VALUE (parm),
TREE_PURPOSE (parm),
fn, i - is_method),
converted_args);
for (; arg; arg = TREE_CHAIN (arg))
converted_args
= tree_cons (NULL_TREE,
convert_arg_to_ellipsis (TREE_VALUE (arg)),
converted_args);
converted_args = nreverse (converted_args);
if (warn_format)
check_function_format (NULL, TYPE_ATTRIBUTES (TREE_TYPE (fn)),
converted_args);
if (! flag_elide_constructors)
;
else if (TREE_VEC_LENGTH (convs) == 1
&& DECL_COPY_CONSTRUCTOR_P (fn))
{
tree targ;
arg = skip_artificial_parms_for (fn, converted_args);
arg = TREE_VALUE (arg);
targ = arg;
while (TREE_CODE (targ) == NOP_EXPR
|| TREE_CODE (targ) == NON_LVALUE_EXPR
|| TREE_CODE (targ) == CONVERT_EXPR)
targ = TREE_OPERAND (targ, 0);
if (TREE_CODE (targ) == ADDR_EXPR)
{
targ = TREE_OPERAND (targ, 0);
if (!same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (TREE_TYPE (arg)), TREE_TYPE (targ)))
targ = NULL_TREE;
}
else
targ = NULL_TREE;
if (targ)
arg = targ;
else
arg = build_indirect_ref (arg, 0);
if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
mark_used (fn);
if (integer_zerop (TREE_VALUE (args)))
{
if (! real_lvalue_p (arg))
return arg;
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
else if ((!real_lvalue_p (arg)
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
&& !is_empty_class (DECL_CONTEXT (fn)))
{
tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
address = build_unary_op (ADDR_EXPR, val, 0);
TREE_USED (address) = 1;
return address;
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
&& copy_fn_p (fn)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0));
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
if (is_empty_class (TREE_TYPE (to)))
{
TREE_USED (arg) = 1;
val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
TREE_SIDE_EFFECTS (val) = 1;
}
else
val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
mark_used (fn);
if (DECL_VINDEX (fn)
&& (flag_indirect_virtual_calls
|| (flags & LOOKUP_NONVIRTUAL) == 0))
{
tree t, *p = &TREE_VALUE (converted_args);
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
DECL_VIRTUAL_CONTEXT (fn),
ba_any, NULL);
my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
*p = build_base_path (PLUS_EXPR, *p, binfo, 1);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
t = build_pointer_type (TREE_TYPE (fn));
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
fn = build_java_interface_fn_ref (fn, *p);
else if (flags & LOOKUP_NONVIRTUAL)
fn = (build_vfn_ref_using_vtable
(DECL_CLASS_CONTEXT (fn),
BINFO_VTABLE (TYPE_BINFO (DECL_CLASS_CONTEXT (fn))),
DECL_VINDEX (fn)));
else
fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else if (DECL_INLINE (fn))
fn = inline_conversion (fn);
else
fn = build_addr_func (fn);
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
{
tree exp;
exp = expand_tree_builtin (TREE_OPERAND (fn, 0), args, converted_args);
if (exp)
return exp;
}
fn = fold (build_call (fn, converted_args));
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
fn = require_complete_type (fn);
if (fn == error_mark_node)
return error_mark_node;
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn);
return convert_from_reference (fn);
}
static tree java_iface_lookup_fn;
static tree
build_java_interface_fn_ref (fn, instance)
tree fn, instance;
{
tree lookup_args, lookup_fn, method, idx;
tree klass_ref, iface, iface_ref;
int i;
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)));
java_iface_lookup_fn
= builtin_function ("_Jv_LookupInterfaceMethodIdx",
build_function_type (ptr_type_node, t),
0, NOT_BUILT_IN, NULL);
ggc_add_tree_root (&java_iface_lookup_fn, 1);
}
klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0),
integer_zero_node);
iface = DECL_CONTEXT (fn);
iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
|| DECL_CONTEXT (iface_ref) != iface)
{
error ("could not find class$ field in java interface type `%T'",
iface);
return error_mark_node;
}
iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
i = 1;
for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
{
if (!DECL_VIRTUAL_P (method))
continue;
if (fn == method)
break;
i++;
}
idx = build_int_2 (i, 0);
lookup_args = tree_cons (NULL_TREE, klass_ref,
tree_cons (NULL_TREE, iface_ref,
build_tree_list (NULL_TREE, idx)));
lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
java_iface_lookup_fn);
return build (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE);
}
tree
in_charge_arg_for_name (name)
tree name;
{
if (name == base_ctor_identifier
|| name == base_dtor_identifier)
return integer_zero_node;
else if (name == complete_ctor_identifier)
return integer_one_node;
else if (name == complete_dtor_identifier)
return integer_two_node;
else if (name == deleting_dtor_identifier)
return integer_three_node;
my_friendly_abort (20000411);
return NULL_TREE;
}
static tree
build_new_method_call (instance, name, args, basetype_path, flags)
tree instance, name, args, basetype_path;
int flags;
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
tree basetype, mem_args = NULL_TREE, fns, instance_ptr;
tree pretty_name;
tree user_args;
tree templates = NULL_TREE;
tree call;
int template_only = 0;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
explicit_targs = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
if (DECL_P (name))
name = DECL_NAME (name);
else
{
if (TREE_CODE (name) == COMPONENT_REF)
name = TREE_OPERAND (name, 1);
if (TREE_CODE (name) == OVERLOAD)
name = DECL_NAME (OVL_CURRENT (name));
}
template_only = 1;
}
user_args = args;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
if (instance == NULL_TREE)
basetype = BINFO_TYPE (basetype_path);
else
{
if (TREE_CODE (instance) == OFFSET_REF)
instance = resolve_offset_ref (instance);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
if (! IS_AGGR_TYPE (basetype))
{
if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
name, instance, basetype);
return error_mark_node;
}
}
if (basetype_path == NULL_TREE)
basetype_path = TYPE_BINFO (basetype);
if (instance)
{
instance_ptr = build_this (instance);
if (! template_only)
{
fns = build_field_call (basetype_path, instance_ptr, name, args);
if (fns)
return fns;
}
}
else
{
instance_ptr = build_int_2 (0, 0);
TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
}
my_friendly_assert (name != ctor_identifier, 20000408);
my_friendly_assert (name != dtor_identifier, 20000408);
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
int constructor_p;
constructor_p = (name == complete_ctor_identifier
|| name == base_ctor_identifier);
pretty_name = (constructor_p
? constructor_name (basetype) : dtor_identifier);
if ((name == base_ctor_identifier
|| name == base_dtor_identifier)
&& TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
tree vtt;
tree sub_vtt;
tree basebinfo = basetype_path;
vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
vtt = decay_conversion (vtt);
vtt = build (COND_EXPR, TREE_TYPE (vtt),
build (EQ_EXPR, boolean_type_node,
current_in_charge_parm, integer_zero_node),
current_vtt_parm,
vtt);
if (TREE_VIA_VIRTUAL (basebinfo))
basebinfo = binfo_for_vbase (basetype, current_class_type);
my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
BINFO_SUBVTT_INDEX (basebinfo));
args = tree_cons (NULL_TREE, sub_vtt, args);
}
}
else
pretty_name = name;
fns = lookup_fnfields (basetype_path, name, 1);
if (fns == error_mark_node)
return error_mark_node;
if (fns)
{
tree base = BINFO_TYPE (TREE_PURPOSE (fns));
tree fn = TREE_VALUE (fns);
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
tree this_arglist;
if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t))
continue;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
this_arglist = mem_args;
else
this_arglist = args;
if (TREE_CODE (t) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, t, templates);
candidates =
add_template_candidate (candidates, t, base, explicit_targs,
this_arglist,
TREE_TYPE (name), flags, DEDUCE_CALL);
}
else if (! template_only)
candidates = add_function_candidate (candidates, t, base,
this_arglist, flags);
if (candidates)
candidates->basetype_path = basetype_path;
}
}
if (! any_viable (candidates))
{
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
incomplete_type_error (instance_ptr, basetype);
else
error ("no matching function for call to `%T::%D(%A)%#V'",
basetype, pretty_name, user_args,
TREE_TYPE (TREE_TYPE (instance_ptr)));
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
user_args);
print_z_candidates (candidates);
return error_mark_node;
}
if (DECL_PURE_VIRTUAL_P (cand->fn)
&& instance == current_class_ref
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl))
&& ! (flags & LOOKUP_NONVIRTUAL)
&& value_member (cand->fn, CLASSTYPE_PURE_VIRTUALS (basetype)))
error ((DECL_CONSTRUCTOR_P (current_function_decl) ?
"abstract virtual `%#D' called from constructor"
: "abstract virtual `%#D' called from destructor"),
cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
&& is_dummy_object (instance_ptr))
{
error ("cannot call member function `%D' without object", cand->fn);
return error_mark_node;
}
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
call = build_over_call (cand, mem_args, flags);
else
{
call = build_over_call (cand, args, flags);
if (TREE_SIDE_EFFECTS (instance))
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
}
return call;
}
static int
is_subseq (ics1, ics2)
tree ics1, ics2;
{
while (TREE_CODE (ics1) == RVALUE_CONV
|| TREE_CODE (ics1) == LVALUE_CONV)
ics1 = TREE_OPERAND (ics1, 0);
while (1)
{
while (TREE_CODE (ics2) == RVALUE_CONV
|| TREE_CODE (ics2) == LVALUE_CONV)
ics2 = TREE_OPERAND (ics2, 0);
if (TREE_CODE (ics2) == USER_CONV
|| TREE_CODE (ics2) == AMBIG_CONV
|| TREE_CODE (ics2) == IDENTITY_CONV)
return 0;
ics2 = TREE_OPERAND (ics2, 0);
if (TREE_CODE (ics2) == TREE_CODE (ics1)
&& same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1))
&& same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)),
TREE_TYPE (TREE_OPERAND (ics1, 0))))
return 1;
}
}
int
is_properly_derived_from (derived, base)
tree derived;
tree base;
{
if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
|| !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
return 0;
return (!same_type_ignoring_top_level_qualifiers_p (derived, base)
&& DERIVED_FROM_P (base, derived));
}
static void
maybe_handle_implicit_object (ics)
tree* ics;
{
if (ICS_THIS_FLAG (*ics))
{
tree t = *ics;
tree reference_type;
reference_type = TREE_TYPE (TREE_TYPE (*ics));
reference_type = build_reference_type (reference_type);
if (TREE_CODE (t) == QUAL_CONV)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == PTR_CONV)
t = TREE_OPERAND (t, 0);
t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
t = direct_reference_binding (reference_type, t);
*ics = t;
}
}
static tree
maybe_handle_ref_bind (ics)
tree* ics;
{
if (TREE_CODE (*ics) == REF_BIND)
{
tree old_ics = *ics;
tree type = TREE_TYPE (TREE_TYPE (old_ics));
*ics = TREE_OPERAND (old_ics, 0);
ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
return type;
}
return NULL_TREE;
}
static int
compare_ics (ics1, ics2)
tree ics1, ics2;
{
tree from_type1;
tree from_type2;
tree to_type1;
tree to_type2;
tree deref_from_type1 = NULL_TREE;
tree deref_from_type2 = NULL_TREE;
tree deref_to_type1 = NULL_TREE;
tree deref_to_type2 = NULL_TREE;
int rank1, rank2;
tree target_type1;
tree target_type2;
maybe_handle_implicit_object (&ics1);
maybe_handle_implicit_object (&ics2);
target_type1 = maybe_handle_ref_bind (&ics1);
target_type2 = maybe_handle_ref_bind (&ics2);
rank1 = ICS_RANK (ics1);
rank2 = ICS_RANK (ics2);
if (rank1 > rank2)
return -1;
else if (rank1 < rank2)
return 1;
if (rank1 == BAD_RANK)
{
if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return -1;
else if (ICS_USER_FLAG (ics1) < ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return 1;
}
if (ICS_ELLIPSIS_FLAG (ics1))
return 0;
if (ICS_USER_FLAG (ics1))
{
tree t1, t2;
for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
if (TREE_CODE (t1) == AMBIG_CONV)
return 0;
for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0))
if (TREE_CODE (t2) == AMBIG_CONV)
return 0;
if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
return 0;
from_type1 = TREE_TYPE (t1);
from_type2 = TREE_TYPE (t2);
}
else
{
from_type1 = ics1;
while (TREE_CODE (from_type1) != IDENTITY_CONV)
from_type1 = TREE_OPERAND (from_type1, 0);
from_type1 = TREE_TYPE (from_type1);
from_type2 = ics2;
while (TREE_CODE (from_type2) != IDENTITY_CONV)
from_type2 = TREE_OPERAND (from_type2, 0);
from_type2 = TREE_TYPE (from_type2);
}
if (same_type_p (from_type1, from_type2))
{
if (is_subseq (ics1, ics2))
return 1;
if (is_subseq (ics2, ics1))
return -1;
}
if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return 1;
else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))
return -1;
to_type1 = TREE_TYPE (ics1);
to_type2 = TREE_TYPE (ics2);
if (TYPE_PTR_P (from_type1)
&& TYPE_PTR_P (from_type2)
&& TYPE_PTR_P (to_type1)
&& TYPE_PTR_P (to_type2))
{
deref_from_type1 = TREE_TYPE (from_type1);
deref_from_type2 = TREE_TYPE (from_type2);
deref_to_type1 = TREE_TYPE (to_type1);
deref_to_type2 = TREE_TYPE (to_type2);
}
else if (TYPE_PTRMEM_P (from_type1)
&& TYPE_PTRMEM_P (from_type2)
&& TYPE_PTRMEM_P (to_type1)
&& TYPE_PTRMEM_P (to_type2))
{
deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
}
else if (TYPE_PTRMEMFUNC_P (from_type1)
&& TYPE_PTRMEMFUNC_P (from_type2)
&& TYPE_PTRMEMFUNC_P (to_type1)
&& TYPE_PTRMEMFUNC_P (to_type2))
{
deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
}
if (deref_from_type1 != NULL_TREE
&& IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))
&& IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))
{
if (TREE_CODE (deref_to_type1) == VOID_TYPE
&& TREE_CODE (deref_to_type2) == VOID_TYPE)
{
if (is_properly_derived_from (deref_from_type1,
deref_from_type2))
return -1;
else if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
return 1;
}
else if (TREE_CODE (deref_to_type1) == VOID_TYPE
|| TREE_CODE (deref_to_type2) == VOID_TYPE)
{
if (same_type_p (deref_from_type1, deref_from_type2))
{
if (TREE_CODE (deref_to_type2) == VOID_TYPE)
{
if (is_properly_derived_from (deref_from_type1,
deref_to_type1))
return 1;
}
else if (is_properly_derived_from (deref_from_type1,
deref_to_type2))
return -1;
}
}
else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))
&& IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))
{
if (same_type_p (deref_from_type1, deref_from_type2))
{
if (is_properly_derived_from (deref_to_type1,
deref_to_type2))
return 1;
else if (is_properly_derived_from (deref_to_type2,
deref_to_type1))
return -1;
}
else if (same_type_p (deref_to_type1, deref_to_type2))
{
if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
return 1;
else if (is_properly_derived_from (deref_from_type1,
deref_from_type2))
return -1;
}
}
}
else if (CLASS_TYPE_P (non_reference (from_type1))
&& same_type_p (from_type1, from_type2))
{
tree from = non_reference (from_type1);
if (is_properly_derived_from (from, to_type1)
&& is_properly_derived_from (from, to_type2))
{
if (is_properly_derived_from (to_type1, to_type2))
return 1;
else if (is_properly_derived_from (to_type2, to_type1))
return -1;
}
}
else if (CLASS_TYPE_P (non_reference (to_type1))
&& same_type_p (to_type1, to_type2))
{
tree to = non_reference (to_type1);
if (is_properly_derived_from (from_type1, to)
&& is_properly_derived_from (from_type2, to))
{
if (is_properly_derived_from (from_type2, from_type1))
return 1;
else if (is_properly_derived_from (from_type1, from_type2))
return -1;
}
}
if (TREE_CODE (ics1) == QUAL_CONV
&& TREE_CODE (ics2) == QUAL_CONV
&& same_type_p (from_type1, from_type2))
return comp_cv_qual_signature (to_type1, to_type2);
if (target_type1 && target_type2
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
return comp_cv_qualification (target_type2, target_type1);
return 0;
}
static tree
source_type (t)
tree t;
{
for (;; t = TREE_OPERAND (t, 0))
{
if (TREE_CODE (t) == USER_CONV
|| TREE_CODE (t) == AMBIG_CONV
|| TREE_CODE (t) == IDENTITY_CONV)
return TREE_TYPE (t);
}
my_friendly_abort (1823);
}
static void
add_warning (winner, loser)
struct z_candidate *winner, *loser;
{
winner->warnings = tree_cons (NULL_TREE,
build_ptr_wrapper (loser),
winner->warnings);
}
static inline int
equal_functions (fn1, fn2)
tree fn1;
tree fn2;
{
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
return decls_match (fn1, fn2);
return fn1 == fn2;
}
static int
joust (cand1, cand2, warn)
struct z_candidate *cand1, *cand2;
int warn;
{
int winner = 0;
int i, off1 = 0, off2 = 0, len;
if (cand1->viable > cand2->viable)
return 1;
if (cand1->viable < cand2->viable)
return -1;
if (cand1->fn == cand2->fn
&& (TYPE_P (cand1->fn) || DECL_P (cand1->fn)))
return 1;
len = TREE_VEC_LENGTH (cand1->convs);
if (len != TREE_VEC_LENGTH (cand2->convs))
{
if (DECL_STATIC_FUNCTION_P (cand1->fn)
&& ! DECL_STATIC_FUNCTION_P (cand2->fn))
off2 = 1;
else if (! DECL_STATIC_FUNCTION_P (cand1->fn)
&& DECL_STATIC_FUNCTION_P (cand2->fn))
{
off1 = 1;
--len;
}
else
my_friendly_abort (42);
}
for (i = 0; i < len; ++i)
{
tree t1 = TREE_VEC_ELT (cand1->convs, i+off1);
tree t2 = TREE_VEC_ELT (cand2->convs, i+off2);
int comp = compare_ics (t1, t2);
if (comp != 0)
{
if (warn_sign_promo
&& ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
&& TREE_CODE (t1) == STD_CONV
&& TREE_CODE (t2) == STD_CONV
&& TREE_CODE (TREE_TYPE (t1)) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (t2)) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (t1))
== TYPE_PRECISION (TREE_TYPE (t2)))
&& (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (t1, 0)))
|| (TREE_CODE (TREE_TYPE (TREE_OPERAND (t1, 0)))
== ENUMERAL_TYPE)))
{
tree type = TREE_TYPE (TREE_OPERAND (t1, 0));
tree type1, type2;
struct z_candidate *w, *l;
if (comp > 0)
type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2),
w = cand1, l = cand2;
else
type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1),
w = cand2, l = cand1;
if (warn)
{
warning ("passing `%T' chooses `%T' over `%T'",
type, type1, type2);
warning (" in call to `%D'", w->fn);
}
else
add_warning (w, l);
}
if (winner && comp != winner)
{
winner = 0;
goto tweak;
}
winner = comp;
}
}
if (winner && cand1->second_conv
&& ((DECL_CONSTRUCTOR_P (cand1->fn)
!= DECL_CONSTRUCTOR_P (cand2->fn))
|| (! DECL_CONSTRUCTOR_P (cand1->fn)
&& ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)),
TREE_TYPE (TREE_TYPE (cand2->fn))))))
{
int comp = compare_ics (cand1->second_conv, cand2->second_conv);
if (comp != winner)
{
struct z_candidate *w, *l;
tree convn;
if (winner == 1)
w = cand1, l = cand2;
else
w = cand2, l = cand1;
if (DECL_CONTEXT (cand1->fn) == DECL_CONTEXT (cand2->fn)
&& ! DECL_CONSTRUCTOR_P (cand1->fn)
&& ! DECL_CONSTRUCTOR_P (cand2->fn)
&& (convn = standard_conversion
(TREE_TYPE (TREE_TYPE (l->fn)),
TREE_TYPE (TREE_TYPE (w->fn)), NULL_TREE))
&& TREE_CODE (convn) == QUAL_CONV)
;
else if (warn)
{
tree source = source_type (TREE_VEC_ELT (w->convs, 0));
if (! DECL_CONSTRUCTOR_P (w->fn))
source = TREE_TYPE (source);
warning ("choosing `%D' over `%D'", w->fn, l->fn);
warning (" for conversion from `%T' to `%T'",
source, TREE_TYPE (w->second_conv));
warning (" because conversion sequence for the argument is better");
}
else
add_warning (w, l);
}
}
if (winner)
return winner;
if (! cand1->template && cand2->template)
return 1;
else if (cand1->template && ! cand2->template)
return -1;
if (cand1->template && cand2->template)
{
winner = more_specialized
(TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
DEDUCE_ORDER,
TREE_VEC_LENGTH (cand1->convs)
- (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
- DECL_CONSTRUCTOR_P (cand1->fn)));
if (winner)
return winner;
}
if (cand1->second_conv)
{
winner = compare_ics (cand1->second_conv, cand2->second_conv);
if (winner)
return winner;
}
if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
|| TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
{
for (i = 0; i < len; ++i)
if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
break;
if (i == TREE_VEC_LENGTH (cand1->convs))
{
if (cand1->fn == cand2->fn)
return 1;
else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
return -1;
else
return 1;
}
}
if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& equal_functions (cand1->fn, cand2->fn))
return 1;
tweak:
if (!pedantic)
{
int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
struct z_candidate *w = 0, *l = 0;
for (i = 0; i < len; ++i)
{
if (ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1)) > rank1)
rank1 = ICS_RANK (TREE_VEC_ELT (cand1->convs, i+off1));
if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2)
rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2));
}
if (rank1 < rank2)
winner = 1, w = cand1, l = cand2;
if (rank1 > rank2)
winner = -1, w = cand2, l = cand1;
if (winner)
{
if (warn)
{
pedwarn ("choosing `%D' over `%D'", w->fn, l->fn);
pedwarn (
" because worst conversion for the former is better than worst conversion for the latter");
}
else
add_warning (w, l);
return winner;
}
}
my_friendly_assert (!winner, 20010121);
return 0;
}
static struct z_candidate *
tourney (candidates)
struct z_candidate *candidates;
{
struct z_candidate *champ = candidates, *challenger;
int fate;
int champ_compared_to_predecessor = 0;
for (challenger = champ->next; challenger; )
{
fate = joust (champ, challenger, 0);
if (fate == 1)
challenger = challenger->next;
else
{
if (fate == 0)
{
champ = challenger->next;
if (champ == 0)
return 0;
champ_compared_to_predecessor = 0;
}
else
{
champ = challenger;
champ_compared_to_predecessor = 1;
}
challenger = champ->next;
}
}
for (challenger = candidates;
challenger != champ
&& !(champ_compared_to_predecessor && challenger->next == champ);
challenger = challenger->next)
{
fate = joust (champ, challenger, 0);
if (fate != 1)
return 0;
}
return champ;
}
int
can_convert (to, from)
tree to, from;
{
return can_convert_arg (to, from, NULL_TREE);
}
int
can_convert_arg (to, from, arg)
tree to, from, arg;
{
tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
return (t && ! ICS_BAD_FLAG (t));
}
int
can_convert_arg_bad (to, from, arg)
tree to, from, arg;
{
tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
return !!t;
}
tree
perform_implicit_conversion (type, expr)
tree type;
tree expr;
{
tree conv;
if (expr == error_mark_node)
return error_mark_node;
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
LOOKUP_NORMAL);
if (!conv)
{
error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
return convert_like (conv, expr);
}
tree
initialize_reference (type, expr)
tree type;
tree expr;
{
tree conv;
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
return convert_like (conv, expr);
}