This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
convert_arguments (was Re: PATCH for crash with incomplete types)
>>>>> "Jason" == Jason Merrill <jason@cygnus.com> writes:
Jason> I don't think there's any useful way to share the code that
Jason> should be shared. I think we can just make a note in both
Jason> places that people changing one should check the other to
Jason> see if the same change would be useful.
I don't like such comments. How about this patch, instead?
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
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.
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.88
diff -c -p -r1.88 call.c
*** call.c 1998/06/10 10:50:44 1.88
--- call.c 1998/06/10 23:05:55
*************** static struct z_candidate * tourney PROT
*** 47,53 ****
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 *));
--- 47,52 ----
*************** convert_like (convs, expr)
*** 3172,3178 ****
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
! static tree
convert_default_arg (type, arg)
tree type, arg;
{
--- 3195,3228 ----
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
! /* 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;
{
*************** build_over_call (cand, args, flags)
*** 3341,3364 ****
/* 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 = nreverse (converted_args);
--- 3391,3400 ----
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
! converted_args
! = expr_tree_cons (NULL_TREE,
! convert_arg_to_ellipsis (TREE_VALUE (arg)),
! converted_args);
converted_args = nreverse (converted_args);
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.82
diff -c -p -r1.82 cp-tree.h
*** cp-tree.h 1998/06/10 10:16:42 1.82
--- cp-tree.h 1998/06/10 23:06:24
*************** extern tree build_op_delete_call PROTO(
*** 2254,2259 ****
--- 2254,2261 ----
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));
*************** extern void init_init_processing PROTO(
*** 2532,2538 ****
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));
--- 2534,2539 ----
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.44
diff -c -p -r1.44 init.c
*** init.c 1998/06/10 03:13:11 1.44
--- init.c 1998/06/10 23:06:34
*************** expand_aggr_vbase_init (binfo, exp, addr
*** 832,865 ****
}
}
- /* 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
--- 832,837 ----
*************** expand_member_init (exp, name, init)
*** 957,1108 ****
cp_error ("(type `%T' uses multiple inheritance)", type);
return;
}
-
- if (init)
- {
- /* 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)
! {
! tree base_init;
! if (name == NULL_TREE)
! {
! #if 0
! 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
{
! 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);
}
! 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)
{
! /* just know that we've seen something for this node */
! DECL_INITIAL (exp) = error_mark_node;
! 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. */
! fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
! if (fndecl)
! my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
! parmtypes = NULL_TREE;
! fndecl = NULL_TREE;
! 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
return;
! if (rval != error_mark_node)
{
! /* 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;
}
- }
- 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);
}
/* This is like `expand_member_init', only it stores one aggregate
--- 929,1013 ----
cp_error ("(type `%T' uses multiple inheritance)", type);
return;
}
! 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)
! {
! tree base_init;
! if (name == NULL_TREE)
{
! #if 0
! 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
! {
! 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);
! }
}
/* This is like `expand_member_init', only it stores one aggregate
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.78
diff -c -p -r1.78 typeck.c
*** typeck.c 1998/06/10 10:01:13 1.78
--- typeck.c 1998/06/10 23:06:57
*************** convert_arguments (return_loc, typelist,
*** 3038,3061 ****
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);
}
if (typetail)
--- 3038,3046 ----
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
val = convert_from_reference (val);
! result = expr_tree_cons (NULL_TREE,
! convert_arg_to_ellipsis (val),
! result);
}
if (typetail)
*************** convert_arguments (return_loc, typelist,
*** 3070,3106 ****
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
! }
if (parmval == error_mark_node)
return error_mark_node;
--- 3055,3062 ----
for (; typetail != void_list_node; ++i)
{
tree type = TREE_VALUE (typetail);
! tree val = TREE_PURPOSE (typetail);
! tree parmval = convert_default_arg (type, val);
if (parmval == error_mark_node)
return error_mark_node;