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
This commit is contained in:
Mark Mitchell 1998-06-11 00:07:24 +00:00 committed by Mark Mitchell
parent 8358a974b5
commit 41efda8f53
6 changed files with 151 additions and 225 deletions

View File

@ -1,3 +1,20 @@
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>
* search.c (covariant_return_p): Complain about ambiguous base.

View File

@ -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 compare_ics PROTO((tree, tree));
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 void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
tree, char *));
@ -3155,8 +3154,32 @@ convert_like (convs, expr)
return expr;
/* else fall through */
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:
return convert_to_reference
(TREE_TYPE (convs), expr,
@ -3172,7 +3195,34 @@ convert_like (convs, expr)
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)
tree type, arg;
{
@ -3341,24 +3391,10 @@ build_over_call (cand, args, flags)
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
{
val = TREE_VALUE (arg);
if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (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
= expr_tree_cons (NULL_TREE,
convert_arg_to_ellipsis (TREE_VALUE (arg)),
converted_args);
converted_args = nreverse (converted_args);

View File

@ -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_arg PROTO((tree, 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 */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
@ -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 emit_base_init PROTO((tree, int));
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_aggr_init PROTO((tree, tree, int, int));
extern int is_aggr_typedef PROTO((tree, int));

View File

@ -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. */
static tree
@ -958,151 +930,84 @@ expand_member_init (exp, name, init)
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)
init = NULL_TREE;
if (name == NULL_TREE || basetype)
{
/* 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. */
tree base_init;
if (init == void_type_node)
init = NULL_TREE;
if (name == NULL_TREE || basetype)
if (name == NULL_TREE)
{
tree base_init;
if (name == NULL_TREE)
{
#if 0
if (basetype)
name = TYPE_IDENTIFIER (basetype);
else
{
error ("no base class to initialize");
return;
}
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))
{
cp_error ("base class `%T' already initialized", basetype);
return;
}
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;
try_member:
field = lookup_field (type, name, 1, 0);
if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
return;
if (purpose_member (name, current_member_init_list))
{
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);
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;
}
return;
}
else if (name == NULL_TREE)
{
compiler_error ("expand_member_init: name == NULL_TREE");
return;
}
basetype = type;
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)
if (purpose_member (basetype, current_base_init_list))
{
/* just know that we've seen something for this node */
DECL_INITIAL (exp) = error_mark_node;
TREE_USED (exp) = 1;
cp_error ("base class `%T' already initialized", basetype);
return;
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
parm = build_component_ref (exp, name, NULL_TREE, 0);
/* Now get to the constructors. */
fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
if (warn_reorder && current_member_init_list)
{
cp_warning ("base initializer for `%T'", basetype);
warning (" will be re-ordered to precede member initializations");
}
if (fndecl)
my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
base_init = build_tree_list (basetype, init);
current_base_init_list = chainon (current_base_init_list, base_init);
}
else
{
tree member_init;
parmtypes = NULL_TREE;
fndecl = NULL_TREE;
try_member:
field = lookup_field (type, name, 1, 0);
init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
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
if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
return;
if (rval != error_mark_node)
if (purpose_member (name, current_member_init_list))
{
/* Now, fill in the first parm with our guy */
TREE_VALUE (TREE_OPERAND (rval, 1))
= build_unary_op (ADDR_EXPR, parm, 0);
TREE_TYPE (rval) = ptr_type_node;
TREE_SIDE_EFFECTS (rval) = 1;
cp_error ("field `%D' already initialized", field);
return;
}
}
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
be of aggregate type to receive initialization. */
if (rval != error_mark_node)
expand_expr_stmt (rval);
member_init = build_tree_list (name, init);
current_member_init_list = chainon (current_member_init_list, member_init);
}
}
/* This is like `expand_member_init', only it stores one aggregate

View File

@ -3037,24 +3037,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
val = convert_from_reference (val);
if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)))
/* 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);
result = expr_tree_cons (NULL_TREE,
convert_arg_to_ellipsis (val),
result);
}
if (typetail)
@ -3069,37 +3054,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
for (; typetail != void_list_node; ++i)
{
tree type = TREE_VALUE (typetail);
tree val = break_out_target_exprs (TREE_PURPOSE (typetail));
tree parmval;
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
}
tree val = TREE_PURPOSE (typetail);
tree parmval = convert_default_arg (type, val);
if (parmval == error_mark_node)
return error_mark_node;

View File

@ -0,0 +1,11 @@
// 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
}