Commit 41efda8f by Mark Mitchell Committed by Mark Mitchell

call.c (convert_default_arg): Make global, not static.

	* call.c (convert_default_arg): Make global, not static.
	(convert_arg_for_ellipsis): Split out from ...
	(build_over_call): Here.
	* cp-tree.h (convert_default_arg); Declare.
	(convert_arg_to_ellipsis): Likewise.
	(do_member_init): Remove.
	* init.c (do_member_init): Remove; this code is dead.
	(expand_member_init): Remove much of this code; it is dead.
	* typeck.c (convert_arguments): Use convert_default_arg and
	convert_arg_for_ellipsis, rather than duplicating here.
	* call.c (convert_like): Don't fail silently if
	build_user_type_conversion fails.  Always return error_mark_node
	for failure.

From-SVN: r20424
parent 8358a974
1998-06-10 Mark Mitchell <mark@markmitchell.com>
* call.c (convert_default_arg): Make global, not static.
(convert_arg_for_ellipsis): Split out from ...
(build_over_call): Here.
* cp-tree.h (convert_default_arg); Declare.
(convert_arg_to_ellipsis): Likewise.
(do_member_init): Remove.
* init.c (do_member_init): Remove; this code is dead.
(expand_member_init): Remove much of this code; it is dead.
* typeck.c (convert_arguments): Use convert_default_arg and
convert_arg_for_ellipsis, rather than duplicating here.
* call.c (convert_like): Don't fail silently if
build_user_type_conversion fails. Always return error_mark_node
for failure.
1998-06-10 Jason Merrill <jason@yorick.cygnus.com> 1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
* search.c (covariant_return_p): Complain about ambiguous base. * search.c (covariant_return_p): Complain about ambiguous base.
......
...@@ -47,7 +47,6 @@ static struct z_candidate * tourney PROTO((struct z_candidate *)); ...@@ -47,7 +47,6 @@ static struct z_candidate * tourney PROTO((struct z_candidate *));
static int joust PROTO((struct z_candidate *, struct z_candidate *, int)); static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PROTO((tree, tree)); static int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int)); static tree build_over_call PROTO((struct z_candidate *, tree, int));
static tree convert_default_arg PROTO((tree, tree));
static tree convert_like PROTO((tree, tree)); static tree convert_like PROTO((tree, tree));
static void op_error PROTO((enum tree_code, enum tree_code, tree, tree, static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
tree, char *)); tree, char *));
...@@ -3155,8 +3154,32 @@ convert_like (convs, expr) ...@@ -3155,8 +3154,32 @@ convert_like (convs, expr)
return expr; return expr;
/* else fall through */ /* else fall through */
case BASE_CONV: case BASE_CONV:
return build_user_type_conversion {
(TREE_TYPE (convs), expr, LOOKUP_NORMAL); tree cvt_expr = build_user_type_conversion
(TREE_TYPE (convs), expr, LOOKUP_NORMAL);
if (!cvt_expr)
{
/* This can occur if, for example, the EXPR has incomplete
type. We can't check for that before attempting the
conversion because the type might be an incomplete
array type, which is OK if some constructor for the
destination type takes a pointer argument. */
if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
{
if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
incomplete_type_error (expr, TREE_TYPE (expr));
else
cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
expr, TREE_TYPE (expr), TREE_TYPE (convs));
}
else
cp_error ("could not convert `%E' to `%T'",
expr, TREE_TYPE (convs));
return error_mark_node;
}
return cvt_expr;
}
case REF_BIND: case REF_BIND:
return convert_to_reference return convert_to_reference
(TREE_TYPE (convs), expr, (TREE_TYPE (convs), expr,
...@@ -3172,7 +3195,34 @@ convert_like (convs, expr) ...@@ -3172,7 +3195,34 @@ convert_like (convs, expr)
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
} }
static tree /* ARG is being passed to a varargs function. Perform any conversions
required. Return the converted value. */
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)))
/* Convert `float' to `double'. */
arg = cp_convert (double_type_node, arg);
else if (IS_AGGR_TYPE (TREE_TYPE (arg))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg)))
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (arg));
else
/* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg);
return arg;
}
/* ARG is a default argument expression being passed to a parameter of
the indicated TYPE. Do any required conversions. Return the
converted value. */
tree
convert_default_arg (type, arg) convert_default_arg (type, arg)
tree type, arg; tree type, arg;
{ {
...@@ -3341,24 +3391,10 @@ build_over_call (cand, args, flags) ...@@ -3341,24 +3391,10 @@ build_over_call (cand, args, flags)
/* Ellipsis */ /* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg)) for (; arg; arg = TREE_CHAIN (arg))
{ converted_args
val = TREE_VALUE (arg); = expr_tree_cons (NULL_TREE,
convert_arg_to_ellipsis (TREE_VALUE (arg)),
if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE converted_args);
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)))
/* Convert `float' to `double'. */
val = cp_convert (double_type_node, val);
else if (IS_AGGR_TYPE (TREE_TYPE (val))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val));
else
/* Convert `short' and `char' to full-size `int'. */
val = default_conversion (val);
converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
}
converted_args = nreverse (converted_args); converted_args = nreverse (converted_args);
......
...@@ -2254,6 +2254,8 @@ extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int)); ...@@ -2254,6 +2254,8 @@ extern tree build_op_delete_call PROTO((enum tree_code, tree, tree, int));
extern int can_convert PROTO((tree, tree)); extern int can_convert PROTO((tree, tree));
extern int can_convert_arg PROTO((tree, tree, tree)); extern int can_convert_arg PROTO((tree, tree, tree));
extern void enforce_access PROTO((tree, tree)); extern void enforce_access PROTO((tree, tree));
extern tree convert_default_arg PROTO((tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree));
/* in class.c */ /* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
...@@ -2532,7 +2534,6 @@ extern void init_init_processing PROTO((void)); ...@@ -2532,7 +2534,6 @@ extern void init_init_processing PROTO((void));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree)); extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
extern void emit_base_init PROTO((tree, int)); extern void emit_base_init PROTO((tree, int));
extern void check_base_init PROTO((tree)); extern void check_base_init PROTO((tree));
extern void do_member_init PROTO((tree, tree, tree));
extern void expand_member_init PROTO((tree, tree, tree)); extern void expand_member_init PROTO((tree, tree, tree));
extern void expand_aggr_init PROTO((tree, tree, int, int)); extern void expand_aggr_init PROTO((tree, tree, int, int));
extern int is_aggr_typedef PROTO((tree, int)); extern int is_aggr_typedef PROTO((tree, int));
......
...@@ -832,34 +832,6 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list) ...@@ -832,34 +832,6 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
} }
} }
/* Subroutine to perform parser actions for member initialization.
S_ID is the scoped identifier.
NAME is the name of the member.
INIT is the initializer, or `void_type_node' if none. */
void
do_member_init (s_id, name, init)
tree s_id, name, init;
{
tree binfo, base;
if (current_class_type == NULL_TREE
|| ! is_aggr_typedef (s_id, 1))
return;
binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
current_class_type, 1);
if (binfo == error_mark_node)
return;
if (binfo == 0)
{
error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
return;
}
base = convert_pointer_to (binfo, current_class_ptr);
expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
}
/* Find the context in which this FIELD can be initialized. */ /* Find the context in which this FIELD can be initialized. */
static tree static tree
...@@ -958,151 +930,84 @@ expand_member_init (exp, name, init) ...@@ -958,151 +930,84 @@ expand_member_init (exp, name, init)
return; return;
} }
if (init) my_friendly_assert (init != NULL_TREE, 0);
{
/* The grammar should not allow fields which have names
that are TYPENAMEs. Therefore, if the field has
a non-NULL TREE_TYPE, we may assume that this is an
attempt to initialize a base class member of the current
type. Otherwise, it is an attempt to initialize a
member field. */
if (init == void_type_node) /* The grammar should not allow fields which have names that are
init = NULL_TREE; TYPENAMEs. Therefore, if the field has a non-NULL TREE_TYPE, we
may assume that this is an attempt to initialize a base class
member of the current type. Otherwise, it is an attempt to
initialize a member field. */
if (name == NULL_TREE || basetype) if (init == void_type_node)
{ init = NULL_TREE;
tree base_init;
if (name == NULL_TREE) if (name == NULL_TREE || basetype)
{ {
#if 0 tree base_init;
if (basetype)
name = TYPE_IDENTIFIER (basetype);
else
{
error ("no base class to initialize");
return;
}
#endif
}
else if (basetype != type
&& ! current_template_parms
&& ! vec_binfo_member (basetype,
TYPE_BINFO_BASETYPES (type))
&& ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
{
if (IDENTIFIER_CLASS_VALUE (name))
goto try_member;
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
basetype, type);
else
cp_error ("type `%T' is not an immediate basetype for `%T'",
basetype, type);
return;
}
if (purpose_member (basetype, current_base_init_list)) if (name == NULL_TREE)
{
#if 0
if (basetype)
name = TYPE_IDENTIFIER (basetype);
else
{ {
cp_error ("base class `%T' already initialized", basetype); error ("no base class to initialize");
return; return;
} }
#endif
if (warn_reorder && current_member_init_list)
{
cp_warning ("base initializer for `%T'", basetype);
warning (" will be re-ordered to precede member initializations");
}
base_init = build_tree_list (basetype, init);
current_base_init_list = chainon (current_base_init_list, base_init);
} }
else else if (basetype != type
&& ! current_template_parms
&& ! vec_binfo_member (basetype,
TYPE_BINFO_BASETYPES (type))
&& ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
{ {
tree member_init; if (IDENTIFIER_CLASS_VALUE (name))
goto try_member;
try_member: if (TYPE_USES_VIRTUAL_BASECLASSES (type))
field = lookup_field (type, name, 1, 0); cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
basetype, type);
if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) else
return; cp_error ("type `%T' is not an immediate basetype for `%T'",
basetype, type);
if (purpose_member (name, current_member_init_list)) return;
{
cp_error ("field `%D' already initialized", field);
return;
}
member_init = build_tree_list (name, init);
current_member_init_list = chainon (current_member_init_list, member_init);
} }
return;
}
else if (name == NULL_TREE)
{
compiler_error ("expand_member_init: name == NULL_TREE");
return;
}
basetype = type; if (purpose_member (basetype, current_base_init_list))
field = lookup_field (basetype, name, 0, 0);
if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
return;
/* now see if there is a constructor for this type
which will take these args. */
if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
{
tree parmtypes, fndecl;
if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
{ {
/* just know that we've seen something for this node */ cp_error ("base class `%T' already initialized", basetype);
DECL_INITIAL (exp) = error_mark_node; return;
TREE_USED (exp) = 1;
} }
type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
parm = build_component_ref (exp, name, NULL_TREE, 0);
/* Now get to the constructors. */ if (warn_reorder && current_member_init_list)
fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0); {
cp_warning ("base initializer for `%T'", basetype);
warning (" will be re-ordered to precede member initializations");
}
if (fndecl) base_init = build_tree_list (basetype, init);
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209); current_base_init_list = chainon (current_base_init_list, base_init);
}
else
{
tree member_init;
parmtypes = NULL_TREE; try_member:
fndecl = NULL_TREE; field = lookup_field (type, name, 1, 0);
init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL); if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
rval = build_method_call (NULL_TREE, ctor_identifier, init,
TYPE_BINFO (type), LOOKUP_NORMAL);
else
return; return;
if (rval != error_mark_node) if (purpose_member (name, current_member_init_list))
{ {
/* Now, fill in the first parm with our guy */ cp_error ("field `%D' already initialized", field);
TREE_VALUE (TREE_OPERAND (rval, 1)) return;
= build_unary_op (ADDR_EXPR, parm, 0);
TREE_TYPE (rval) = ptr_type_node;
TREE_SIDE_EFFECTS (rval) = 1;
} }
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
parm = build_component_ref (exp, name, NULL_TREE, 0);
expand_aggr_init (parm, NULL_TREE, 0, 0);
rval = error_mark_node;
}
/* Now initialize the member. It does not have to member_init = build_tree_list (name, init);
be of aggregate type to receive initialization. */ current_member_init_list = chainon (current_member_init_list, member_init);
if (rval != error_mark_node) }
expand_expr_stmt (rval);
} }
/* This is like `expand_member_init', only it stores one aggregate /* This is like `expand_member_init', only it stores one aggregate
......
...@@ -3037,24 +3037,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) ...@@ -3037,24 +3037,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
val = convert_from_reference (val); val = convert_from_reference (val);
if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE result = expr_tree_cons (NULL_TREE,
&& (TYPE_PRECISION (TREE_TYPE (val)) convert_arg_to_ellipsis (val),
< TYPE_PRECISION (double_type_node))) result);
/* Convert `float' to `double'. */
result = expr_tree_cons (NULL_TREE,
cp_convert (double_type_node, val),
result);
else if (IS_AGGR_TYPE (TREE_TYPE (val))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
{
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val));
result = expr_tree_cons (NULL_TREE, val, result);
}
else
/* Convert `short' and `char' to full-size `int'. */
result = expr_tree_cons (NULL_TREE, default_conversion (val),
result);
} }
if (typetail) if (typetail)
...@@ -3069,37 +3054,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) ...@@ -3069,37 +3054,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
for (; typetail != void_list_node; ++i) for (; typetail != void_list_node; ++i)
{ {
tree type = TREE_VALUE (typetail); tree type = TREE_VALUE (typetail);
tree val = break_out_target_exprs (TREE_PURPOSE (typetail)); tree val = TREE_PURPOSE (typetail);
tree parmval; tree parmval = convert_default_arg (type, val);
if (val == NULL_TREE)
parmval = error_mark_node;
else if (TREE_CODE (val) == CONSTRUCTOR)
{
parmval = digest_init (type, val, (tree *)0);
parmval = convert_for_initialization (return_loc, type,
parmval, flags,
"default constructor",
fndecl, i);
}
else
{
/* This could get clobbered by the following call. */
if (TREE_HAS_CONSTRUCTOR (val))
val = copy_node (val);
parmval = convert_for_initialization (return_loc, type,
val, flags,
"default argument",
fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& (TYPE_PRECISION (type)
< TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
#endif
}
if (parmval == error_mark_node) if (parmval == error_mark_node)
return error_mark_node; return error_mark_node;
......
// Build don't link:
template <class T>
void f(T) {} // ERROR - parameter has incomplete type
class C;
void g(const C& c)
{
f(c); // ERROR - invalid use of undefined type
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment