tree ttl = TYPE_METHOD_BASETYPE (type);
tree ttr = TYPE_METHOD_BASETYPE (parmtype);
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
h.code = 0;
else
{
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
if (TREE_CODE (ttl) != VOID_TYPE
&& (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
{
- if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
- {
- ttl = unsigned_type (ttl);
- ttr = unsigned_type (ttr);
- penalty = 10;
- }
if (comp_target_types (type, parmtype, 1) <= 0)
return EVIL_RETURN (h);
}
return EVIL_RETURN (h);
#endif
- if (penalty == 10 || ttr == ttl)
+ if (ttr == ttl)
{
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- /* If one was unsigned but the other wasn't, then we need to
- do a standard conversion from T to unsigned T. */
- if (penalty == 10)
- h.code = PROMO_CODE; /* was STD_CODE */
- else
- h.code = 0;
-
+ h.code = 0;
/* Note conversion from `T*' to `const T*',
or `T*' to `volatile T*'. */
- if (ttl == ttr
- && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+ h.code = EVIL_CODE;
+ else if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE;
h.distance = 0;
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ int b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
if (ttl != ttr)
{
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
- || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+ h.code = EVIL_CODE;
+ else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE;
}
return h;
if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{
- int b_or_d = get_base_distance (type, parmtype, 0, 0);
+ int b_or_d = get_base_distance (type, parmtype, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (parmtype, type, 0, 0);
+ b_or_d = get_base_distance (parmtype, type, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
{
struct harshness_code tmp;
+ tree cand = TREE_VALUE (conv);
- if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+ if (winner && winner == cand)
continue;
- if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
- (tmp.code < USER_CODE) && (tmp.distance >= 0))
+ tmp = convert_harshness (type, TREE_TYPE (TREE_TYPE (cand)), NULL_TREE);
+ if ((tmp.code < USER_CODE) && (tmp.distance >= 0))
{
if (winner)
return EVIL_CODE;
else
{
- winner = conv;
+ winner = cand;
code = tmp.code;
}
}
rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),
datum, CLASSTYPE_VFIELD (type));
else
- rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);
+ rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
flag_assume_nonnull_objects = old_assume_nonnull_objects;
return rval;
{
tree field, instance;
- if (instance_ptr == current_class_decl)
+ if (instance_ptr == current_class_ptr)
{
/* Check to see if we really have a reference to an instance variable
with `operator()()' overloaded. */
{
/* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */
- instance = build_component_ref_1 (C_C_D, field, 0);
+ instance = build_component_ref_1 (current_class_ref, field, 0);
if (instance == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
return build_function_call (instance, parms);
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
- return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));
+ return build_function_call (instance, tree_cons (NULL_TREE, current_class_ptr, parms));
}
}
return NULL_TREE;
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, 0);
+ return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
cp_error_at (" %D", candidates[i].function);
}
+/* We want the address of a function or method. We avoid creating a
+ pointer-to-member function. */
+tree
+build_addr_func (function)
+ tree function;
+{
+ tree type = TREE_TYPE (function);
+
+ /* We have to do these by hand to avoid real pointer to member
+ functions. */
+ 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);
+
+ /* Address of a static or external variable or function counts
+ as a constant */
+ if (staticp (function))
+ TREE_CONSTANT (addr) = 1;
+
+ function = addr;
+ }
+ else
+ function = default_conversion (function);
+
+ return function;
+}
+
+/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
+ POINTER_TYPE to those. Note, pointer to member function types
+ (TYPE_PTRMEMFUNC_P) must be handled by our callers. */
+tree
+build_call (function, result_type, parms)
+ tree function, result_type, parms;
+{
+ int is_constructor = 0;
+
+ 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;
+ }
+
+ if (TREE_CODE (function) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+ is_constructor = 1;
+
+ 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;
+
+ return function;
+}
+
+static tree
+default_parm_conversions (parms, last)
+ tree parms, *last;
+{
+ tree parm, parmtypes = NULL_TREE;
+
+ *last = NULL_TREE;
+
+ for (parm = parms; parm; parm = TREE_CHAIN (parm))
+ {
+ tree t = TREE_TYPE (TREE_VALUE (parm));
+
+ if (TREE_CODE (t) == OFFSET_TYPE
+ || TREE_CODE (t) == METHOD_TYPE
+ || TREE_CODE (t) == FUNCTION_TYPE)
+ {
+ TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
+ t = TREE_TYPE (TREE_VALUE (parm));
+ }
+
+ if (t == error_mark_node)
+ return error_mark_node;
+
+ *last = build_tree_list (NULL_TREE, t);
+ parmtypes = chainon (parmtypes, *last);
+ }
+
+ return parmtypes;
+}
+
+
/* Build something of the form ptr->method (args)
or object.method (args). This can also build
calls to constructors, and find friends.
name = build_min_nt (BIT_NOT_EXPR, type);
}
- return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, 0);
+ return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
}
/* This is the logic that magically deletes the second argument to
return error_mark_node;
}
}
- else if (instance == C_C_D || instance == current_class_decl)
+ else if (instance == current_class_ref || instance == current_class_ptr)
{
/* When doing initialization, we side-effect the TREE_TYPE of
- C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
- basetype = TREE_TYPE (C_C_D);
+ current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
+ basetype = TREE_TYPE (current_class_ref);
/* Anything manifestly `this' in constructors and destructors
has a known type, so virtual function tables are not needed. */
}
else
{
- instance = C_C_D;
- instance_ptr = current_class_decl;
+ instance = current_class_ref;
+ instance_ptr = current_class_ptr;
basetype_path = TYPE_BINFO (current_class_type);
}
result = build_field_call (basetype_path, instance_ptr, name, parms);
save_basetype = TYPE_MAIN_VARIANT (basetype);
- last = NULL_TREE;
- for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))
+ parmtypes = default_parm_conversions (parms, &last);
+ if (parmtypes == error_mark_node)
{
- tree t = TREE_TYPE (TREE_VALUE (parm));
- if (TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Convert OFFSET_TYPE entities to their normal selves. */
- TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
- && TREE_CODE (t) == METHOD_TYPE)
- {
- TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
- }
-#if 0
- /* This breaks reference-to-array parameters. */
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
-#endif
- if (t == error_mark_node)
- return error_mark_node;
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
+ return error_mark_node;
}
if (instance && IS_SIGNATURE (basetype))
cp->harshness = (struct harshness_code *)
alloca ((len + 1) * sizeof (struct harshness_code));
- result = build_overload_call (name, friend_parms, 0, cp);
+ result = build_overload_call_real (name, friend_parms, 0, cp, 1);
+
/* If it turns out to be the one we were actually looking for
(it was probably a friend function), the return the
good result. */
type (if it exists) is a pointer to. */
if (DECL_ABSTRACT_VIRTUAL_P (function)
- && instance == C_C_D
+ && instance == current_class_ref
&& DECL_CONSTRUCTOR_P (current_function_decl)
&& ! (flags & LOOKUP_NONVIRTUAL)
&& value_member (function, get_abstract_virtuals (basetype)))
cp_error ("abstract virtual `%#D' called from constructor", function);
- if (IS_SIGNATURE (basetype) && static_call_context)
+ if (IS_SIGNATURE (basetype))
{
- cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
- basetype, save_name);
- return error_mark_node;
+ if (static_call_context)
+ {
+ cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
+ basetype, save_name);
+ return error_mark_node;
}
- else if (IS_SIGNATURE (basetype))
- return build_signature_method_call (basetype, instance, function, parms);
+ return build_signature_method_call (basetype, instance, function, parms);
+ }
function = DECL_MAIN_VARIANT (function);
mark_used (function);
synthesize_method (function);
if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
- && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
+ && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)
+ && ! (DECL_TEMPLATE_INFO (function)
+ && TREE_LANG_FLAG_0 (DECL_TEMPLATE_INFO (function))))
cp_warning ("inline function `%#D' called before definition", function);
fntype = TREE_TYPE (function);
{
/* Let's be nasty to the user now, and give reasonable
error messages. */
- instance_ptr = current_class_decl;
+ instance_ptr = current_class_ptr;
if (instance_ptr)
{
if (basetype != current_class_type)
{
int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
basetype = TREE_TYPE (instance);
- if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ if (TYPE_METHOD_BASETYPE (TREE_TYPE (function))
+ != TYPE_MAIN_VARIANT (basetype))
{
basetype = DECL_CLASS_CONTEXT (function);
instance_ptr = convert_pointer_to (basetype, instance_ptr);
GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
- {
- int is_constructor;
-
- if (TREE_CODE (function) == FUNCTION_DECL)
- {
- is_constructor = DECL_CONSTRUCTOR_P (function);
- function = default_conversion (function);
- }
- else
- {
- is_constructor = 0;
- function = default_conversion (function);
- }
-
- result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
- TREE_TYPE (result) = value_type;
- TREE_SIDE_EFFECTS (result) = 1;
- TREE_HAS_CONSTRUCTOR (result) = is_constructor;
- result = convert_from_reference (result);
- return result;
- }
+ result = build_call (function, value_type, parms);
+ result = convert_from_reference (result);
+ return result;
}
/* Similar to `build_method_call', but for overloaded non-member functions.
function's new name. */
tree
-build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
+build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
tree fnname, parms;
int flags;
struct candidate *final_cp;
- int buildxxx;
+ int require_complete;
{
/* must check for overloading here */
tree functions, function, parm;
- tree parmtypes = NULL_TREE, last = NULL_TREE;
+ tree parmtypes, last;
register tree outer;
int length;
int parmlength = list_length (parms);
final_cp[1].h.code = EVIL_CODE;
}
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
+ parmtypes = default_parm_conversions (parms, &last);
+ if (parmtypes == error_mark_node)
{
- register tree t = TREE_TYPE (TREE_VALUE (parm));
-
- if (t == error_mark_node)
- {
- if (final_cp)
- final_cp->h.code = EVIL_CODE;
- return error_mark_node;
- }
- if (TREE_CODE (t) == OFFSET_TYPE)
-#if 0
- /* This breaks reference-to-array parameters. */
- || TREE_CODE (t) == ARRAY_TYPE
-#endif
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- Also convert OFFSET_TYPE entities to their normal selves.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
+ if (final_cp)
+ final_cp->h.code = EVIL_CODE;
+ return error_mark_node;
}
+
if (last)
TREE_CHAIN (last) = void_list_node;
else
if (final_cp)
return rval;
- return buildxxx ? build_function_call_real (rval, parms, 0, flags)
- : build_function_call_real (rval, parms, 1, flags);
+ return build_function_call_real (rval, parms, require_complete, flags);
}
if (flags & LOOKUP_SPECULATIVELY)
return error_mark_node;
}
+/* This requires a complete type on the result of the call. */
tree
-build_overload_call (fnname, parms, flags, final_cp)
+build_overload_call (fnname, parms, flags)
tree fnname, parms;
int flags;
- struct candidate *final_cp;
-{
- return build_overload_call_real (fnname, parms, flags, final_cp, 0);
-}
-
-tree
-build_overload_call_maybe (fnname, parms, flags, final_cp)
- tree fnname, parms;
- int flags;
- struct candidate *final_cp;
{
- return build_overload_call_real (fnname, parms, flags, final_cp, 1);
+ return build_overload_call_real (fnname, parms, flags, (struct candidate *)0, 1);
}