convert_arguments (was Re: PATCH for crash with incomplete types)

Mark Mitchell mark@markmitchell.com
Wed Jun 10 17:06:00 GMT 1998


>>>>> "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;



More information about the Gcc-patches mailing list