This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH for crash with incomplete types



Here's a patch for the crash on the enclosed testcase.  Jason, OK?

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-06-07  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.h (ICS_USER_FLAG): Move here from call.c
	(ICS_ELLIPSIS_FLAG): Likewise.
	(ICS_THIS_FLAG): Likewise.
	(ICS_BAD_FLAG): Likewise.
	(convert_like): Declare.
	(convert_arguments): Change interface.
	* typeck.c (build_function_call_real): Use new interface to
	convert_arguments.
	(convert_arguments): Merge in code from build_over_call.
	* call.c (convert_default_arg): Remove.
	(convert_like): Make global, not static.
	(ICS_USER_FLAG): Remove.
	(ICS_ELLIPSIS_FLAG): Likewise.
	(ICS_THIS_FLAG): Likewise.
	(ICS_BAD_FLAG): Likewise.
	(build_over_call): Use convert_arguments rather than duplicating
	inline.

Index: testsuite/g++.old-deja/g++.pt/crash9.C
===================================================================
RCS file: crash9.C
diff -N crash9.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- crash9.C	Sun Jun  7 19:15:02 1998
***************
*** 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
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.79
diff -c -p -r1.79 cp-tree.h
*** cp-tree.h	1998/06/05 02:26:44	1.79
--- cp-tree.h	1998/06/08 02:15:47
*************** Boston, MA 02111-1307, USA.  */
*** 34,39 ****
--- 34,40 ----
        LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
        TREE_NEGATED_INT (in INTEGER_CST).
        (TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
+       ICS_USER_FLAG (in a _CONV).
     1:  IDENTIFIER_VIRTUAL_P.
        TI_PENDING_TEMPLATE_FLAG.
        TI_PENDING_SPECIALIZATION_FLAG.
*************** Boston, MA 02111-1307, USA.  */
*** 42,54 ****
--- 43,58 ----
        (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
        TYPE_USES_COMPLEX_INHERITANCE (in _TYPE).
        C_DECLARED_LABEL_FLAG.
+       ICS_ELLIPSIS_FLAG (in a _CONV).
     2: IDENTIFIER_OPNAME_P.
        BINFO_FIELDS_MARKED.
        TYPE_VIRTUAL_P.
        PARM_DECL_EXPR (in SAVE_EXPR).
+       ICS_BAD_FLAG (in a _CONV).
     3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
        BINFO_VTABLE_PATH_MARKED.
        (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
+       ICS_BAD_FLAG (in a _CONV).
     4: BINFO_NEW_VTABLE_MARKED.
        TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
            or FIELD_DECL).
*************** extern tree current_class_type;	/* _TYPE
*** 2194,2199 ****
--- 2198,2214 ----
  #define CONV_C_CAST      (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
  			  | CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
  
+ /* These flags are used by the conversion code.
+    ICS_USER_FLAG     : A user-defined conversion.
+    ICS_ELLIPSIS_FLAG : An ellipsis conversion.
+    ICS_THIS_FLAG     : A conversion of `this'.
+    ICS_BAD_FLAG      : An invalid conversion.  */
+ 
+ #define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
+ #define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+ #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
+ #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
+ 
  /* Used by build_expr_type_conversion to indicate which types are
     acceptable as arguments to the expression under consideration.  */
  
*************** extern tree build_op_delete_call		PROTO(
*** 2252,2257 ****
--- 2267,2273 ----
  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_like                        PROTO((tree, tree));
  
  /* in class.c */
  extern tree build_vbase_path			PROTO((enum tree_code, tree, tree, tree, int));
*************** extern tree get_member_function_from_ptr
*** 2921,2927 ****
  extern tree build_function_call_real		PROTO((tree, tree, int, int));
  extern tree build_function_call			PROTO((tree, tree));
  extern tree build_function_call_maybe		PROTO((tree, tree));
! extern tree convert_arguments			PROTO((tree, tree, tree, tree, int));
  extern tree build_x_binary_op			PROTO((enum tree_code, tree, tree));
  extern tree build_binary_op			PROTO((enum tree_code, tree, tree, int));
  extern tree build_binary_op_nodefault		PROTO((enum tree_code, tree, tree, enum tree_code));
--- 2937,2943 ----
  extern tree build_function_call_real		PROTO((tree, tree, int, int));
  extern tree build_function_call			PROTO((tree, tree));
  extern tree build_function_call_maybe		PROTO((tree, tree));
! extern tree convert_arguments			PROTO((tree, tree, tree, tree, int, tree, int));
  extern tree build_x_binary_op			PROTO((enum tree_code, tree, tree));
  extern tree build_binary_op			PROTO((enum tree_code, tree, tree, int));
  extern tree build_binary_op_nodefault		PROTO((enum tree_code, tree, tree, enum tree_code));
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.76
diff -c -p -r1.76 typeck.c
*** typeck.c	1998/06/07 12:13:52	1.76
--- typeck.c	1998/06/08 02:15:25
*************** build_function_call_real (function, para
*** 2803,2812 ****
  
    if (flags & LOOKUP_COMPLAIN)
      coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! 					params, fndecl, LOOKUP_NORMAL);
    else
      coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! 					params, fndecl, 0);
  
    if (coerced_params == error_mark_node)
      {
--- 2803,2813 ----
  
    if (flags & LOOKUP_COMPLAIN)
      coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! 					params, fndecl, LOOKUP_NORMAL,
! 					NULL_TREE, 0);
    else
      coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! 					params, fndecl, 0, NULL_TREE, 0);
  
    if (coerced_params == error_mark_node)
      {
*************** build_function_call (function, params)
*** 2877,2884 ****
     value directly.  If we are not eliding constructors, then we set this
     to NULL_TREE to avoid this avoidance.
  
!    NAME is an IDENTIFIER_NODE or 0.  It is used only for error messages.
  
     This is also where warnings about wrong number of args are generated.
     
     Return a list of expressions for the parameters as converted.
--- 2878,2891 ----
     value directly.  If we are not eliding constructors, then we set this
     to NULL_TREE to avoid this avoidance.
  
!    FNDECL is the function being called.
  
+    The CONVS, if non-NULL, are a vector of conversions computed during
+    overload resolution, and used to direct the conversion of the
+    arguments.  
+ 
+    I is the index of the first argument, starting from zero.
+ 
     This is also where warnings about wrong number of args are generated.
     
     Return a list of expressions for the parameters as converted.
*************** build_function_call (function, params)
*** 2890,2903 ****
     default arguments, if such were specified.  Do so here.  */
  
  tree
! convert_arguments (return_loc, typelist, values, fndecl, flags)
       tree return_loc, typelist, values, fndecl;
       int flags;
  {
    register tree typetail, valtail;
    register tree result = NULL_TREE;
    char *called_thing = 0;
!   int i = 0;
  
    if (! flag_elide_constructors)
      return_loc = 0;
--- 2897,2912 ----
     default arguments, if such were specified.  Do so here.  */
  
  tree
! convert_arguments (return_loc, typelist, values, fndecl, flags, convs, i)
       tree return_loc, typelist, values, fndecl;
       int flags;
+      tree convs;
+      int i;
  {
    register tree typetail, valtail;
    register tree result = NULL_TREE;
    char *called_thing = 0;
!   int is_method = 0;
  
    if (! flag_elide_constructors)
      return_loc = 0;
*************** convert_arguments (return_loc, typelist,
*** 2912,2919 ****
  	  if (DECL_NAME (fndecl) == NULL_TREE
  	      || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
  	    called_thing = "constructor";
! 	  else
! 	    called_thing = "member function";
  	}
        else
  	called_thing = "function";
--- 2921,2931 ----
  	  if (DECL_NAME (fndecl) == NULL_TREE
  	      || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
  	    called_thing = "constructor";
! 	  else 
! 	    {
! 	      called_thing = "member function";
! 	      is_method = 1;
! 	    }
  	}
        else
  	called_thing = "function";
*************** convert_arguments (return_loc, typelist,
*** 3000,3013 ****
  
  	  if (TYPE_SIZE (complete_type (type)) == 0)
  	    {
! 	      error ("parameter type of called function is incomplete");
  	      parmval = val;
  	    }
  	  else
  	    {
! 	      parmval = convert_for_initialization
! 		(return_loc, type, val, flags,
! 		 "argument passing", fndecl, i);
  #ifdef PROMOTE_PROTOTYPES
  	      if ((TREE_CODE (type) == INTEGER_TYPE
  		   || TREE_CODE (type) == ENUMERAL_TYPE)
--- 3012,3051 ----
  
  	  if (TYPE_SIZE (complete_type (type)) == 0)
  	    {
! 	      if (fndecl) 
! 		cp_error ("parameter type `%T' of called %s `%D' is incomplete",
! 			  type, called_thing, fndecl);
! 	      else
! 		cp_error ("parameter type `%T' of called function is incomplete",
! 			  type);
  	      parmval = val;
  	    }
  	  else
  	    {
! 	      tree conv = convs ? TREE_VEC_ELT (convs, i) : NULL_TREE;
! 	      
! 	      if (!conv || ICS_BAD_FLAG (conv))
! 		{
! 		  tree t = conv;
! 		  
! 		  for (; t; t = TREE_OPERAND (t, 0))
! 		    {
! 		      if (TREE_CODE (t) == USER_CONV
! 			  || TREE_CODE (t) == AMBIG_CONV)
! 			{
! 			  parmval = convert_like (t, val);
! 			  break;
! 			}
! 		      else if (TREE_CODE (t) == IDENTITY_CONV)
! 			break;
! 		    }
! 		  parmval = convert_for_initialization
! 		    (return_loc, type, val, flags,
! 		     "argument passing", fndecl, i - is_method);
! 		}
! 	      else
! 		parmval = convert_like (conv, val);
! 
  #ifdef PROMOTE_PROTOTYPES
  	      if ((TREE_CODE (type) == INTEGER_TYPE
  		   || TREE_CODE (type) == ENUMERAL_TYPE)
*************** convert_arguments (return_loc, typelist,
*** 3056,3067 ****
        /* See if there are default arguments that can be used */
        if (TREE_PURPOSE (typetail))
  	{
! 	  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)
--- 3094,3131 ----
        /* See if there are default arguments that can be used */
        if (TREE_PURPOSE (typetail))
  	{
! 	  for (; typetail && typetail != void_list_node; 
! 	       typetail = TREE_CHAIN (typetail), ++i) 
  	    {
  	      tree type = TREE_VALUE (typetail);
! 	      tree val = TREE_PURPOSE (typetail);
  	      tree parmval;
  
+ 	      if (fndecl && DECL_TEMPLATE_INFO (fndecl))
+ 		{
+ 		  /* This came from a template.  Instantiate the
+ 		     default arg here, not in tsubst.  In the case of
+ 		     something like:
+ 		     
+ 		     template <class T>
+ 		       struct S {
+ 		       static T t();
+ 		       void f(T = t());
+ 		     };
+ 
+ 		     we must be careful to do name lookup in the scope of
+ 		     S<T>, rather than in the current class.  */
+ 		  if (DECL_CLASS_SCOPE_P (fndecl))
+ 		    pushclass (DECL_REAL_CONTEXT (fndecl), 2);
+ 		  
+ 		  val = tsubst_expr (val, DECL_TI_ARGS (fndecl), NULL_TREE);
+ 		  
+ 		  if (DECL_CLASS_SCOPE_P (fndecl))
+ 		    popclass (0);
+ 		}
+ 	      
+ 	      val = break_out_target_exprs (val);
+ 	      
  	      if (val == NULL_TREE)
  		parmval = error_mark_node;
  	      else if (TREE_CODE (val) == CONSTRUCTOR)
*************** convert_arguments (return_loc, typelist,
*** 3069,3075 ****
  		  parmval = digest_init (type, val, (tree *)0);
  		  parmval = convert_for_initialization (return_loc, type,
  							parmval, flags,
! 							"default constructor",
  							fndecl, i);
  		}
  	      else
--- 3133,3139 ----
  		  parmval = digest_init (type, val, (tree *)0);
  		  parmval = convert_for_initialization (return_loc, type,
  							parmval, flags,
! 							"default argument",
  							fndecl, i);
  		}
  	      else
*************** convert_arguments (return_loc, typelist,
*** 3090,3104 ****
  		    parmval = default_conversion (parmval);
  #endif
  		}
- 
- 	      if (parmval == error_mark_node)
- 		return error_mark_node;
  
! 	      result = expr_tree_cons (0, parmval, result);
! 	      typetail = TREE_CHAIN (typetail);
! 	      /* ends with `...'.  */
! 	      if (typetail == NULL_TREE)
! 		break;
  	    }
  	}
        else
--- 3154,3161 ----
  		    parmval = default_conversion (parmval);
  #endif
  		}
  
! 	      result = expr_tree_cons (NULL_TREE, parmval, result);
  	    }
  	}
        else
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.85
diff -c -p -r1.85 call.c
*** call.c	1998/06/05 23:03:33	1.85
--- call.c	1998/06/08 02:15:36
*************** static struct z_candidate * tourney PROT
*** 47,54 ****
  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 *));
  static tree build_object_call PROTO((tree, tree));
--- 47,52 ----
*************** struct z_candidate {
*** 719,729 ****
  
  #define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE)
  
- #define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
- #define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
- #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
- #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
- 
  #define USER_CONV_CAND(NODE) \
    ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
  #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
--- 717,722 ----
*************** enforce_access (basetype_path, decl)
*** 3069,3075 ****
  
  /* Perform the conversions in CONVS on the expression EXPR.  */
  
! static tree
  convert_like (convs, expr)
       tree convs, expr;
  {
--- 3062,3068 ----
  
  /* Perform the conversions in CONVS on the expression EXPR.  */
  
! tree
  convert_like (convs, expr)
       tree convs, expr;
  {
*************** convert_like (convs, expr)
*** 3169,3205 ****
  }
  
  static tree
- convert_default_arg (type, arg)
-      tree type, arg;
- {
-   arg = break_out_target_exprs (arg);
- 
-   if (TREE_CODE (arg) == CONSTRUCTOR)
-     {
-       arg = digest_init (type, arg, 0);
-       arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- 					"default argument", 0, 0);
-     }
-   else
-     {
-       /* This could get clobbered by the following call.  */
-       if (TREE_HAS_CONSTRUCTOR (arg))
- 	arg = copy_node (arg);
- 
-       arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- 					"default argument", 0, 0);
- #ifdef PROMOTE_PROTOTYPES
-       if ((TREE_CODE (type) == INTEGER_TYPE
- 	   || TREE_CODE (type) == ENUMERAL_TYPE)
- 	  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- 	arg = default_conversion (arg);
- #endif
-     }
- 
-   return arg;
- }
- 
- static tree
  build_over_call (cand, args, flags)
       struct z_candidate *cand;
       tree args;
--- 3162,3167 ----
*************** build_over_call (cand, args, flags)
*** 3209,3217 ****
    tree convs = cand->convs;
    tree converted_args = NULL_TREE;
    tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
!   tree conv, arg, val;
    int i = 0;
-   int is_method = 0;
  
    /* Give any warnings we noticed during overload resolution.  */
    if (cand->warnings)
--- 3171,3178 ----
    tree convs = cand->convs;
    tree converted_args = NULL_TREE;
    tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
!   tree arg, val;
    int i = 0;
  
    /* Give any warnings we noticed during overload resolution.  */
    if (cand->warnings)
*************** build_over_call (cand, args, flags)
*** 3263,3362 ****
        parm = TREE_CHAIN (parm);
        arg = TREE_CHAIN (arg);
        ++i;
-       is_method = 1;
-     }
- 
-   for (; arg && parm;
-        parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
-     {
-       tree type = TREE_VALUE (parm);
- 
-       conv = TREE_VEC_ELT (convs, i);
-       if (ICS_BAD_FLAG (conv))
- 	{
- 	  tree t = conv;
- 	  val = TREE_VALUE (arg);
- 
- 	  for (; t; t = TREE_OPERAND (t, 0))
- 	    {
- 	      if (TREE_CODE (t) == USER_CONV
- 		  || TREE_CODE (t) == AMBIG_CONV)
- 		{
- 		  val = convert_like (t, val);
- 		  break;
- 		}
- 	      else if (TREE_CODE (t) == IDENTITY_CONV)
- 		break;
- 	    }
- 	  val = convert_for_initialization
- 	    (NULL_TREE, type, val, LOOKUP_NORMAL,
- 	     "argument passing", fn, i - is_method);
- 	}
-       else
- 	val = convert_like (conv, TREE_VALUE (arg));
- 
- #ifdef PROMOTE_PROTOTYPES
-       if ((TREE_CODE (type) == INTEGER_TYPE
- 	   || TREE_CODE (type) == ENUMERAL_TYPE)
- 	  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- 	val = default_conversion (val);
- #endif
-       converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
-     }
- 
-   /* Default arguments */
-   for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
-     {
-       tree arg = TREE_PURPOSE (parm);
- 
-       if (DECL_TEMPLATE_INFO (fn))
- 	{
- 	  /* This came from a template.  Instantiate the default arg here,
- 	     not in tsubst.  In the case of something like:
- 
- 	       template <class T>
- 	       struct S {
- 	         static T t();
- 		 void f(T = t());
- 	       };
- 
- 	     we must be careful to do name lookup in the scope of
- 	     S<T>, rather than in the current class.  */
- 	  if (DECL_CLASS_SCOPE_P (fn))
- 	    pushclass (DECL_REAL_CONTEXT (fn), 2);
- 
- 	  arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
- 
- 	  if (DECL_CLASS_SCOPE_P (fn))
- 	    popclass (0);
- 	}
-       converted_args = expr_tree_cons
- 	(NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
- 	 converted_args);
-     }
- 
-   /* 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);
  
    /* Avoid actually calling copy constructors and copy assignment operators,
       if possible.  */
--- 3224,3235 ----
        parm = TREE_CHAIN (parm);
        arg = TREE_CHAIN (arg);
        ++i;
      }
  
!   converted_args = 
!     chainon (nreverse (converted_args),
! 	     convert_arguments (NULL_TREE, parm, arg, fn, 
! 				LOOKUP_NORMAL, convs, i));
  
    /* Avoid actually calling copy constructors and copy assignment operators,
       if possible.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]