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]
Other format: [Raw text]

[lto] Unify type_unification_real_args and type_unification_real_parms.


Hi,

Attached is a patch to unify type_unification_real_args and
type_unification_real_parms.

The complication associated with type_unification_real was more than I
expected.  Two places call type_unification_real.  One is from
fn_type_unification.  The other is from unify.  I thought the former
would always pass a list of function arguments the fifth argument
XARGS, but that turned out to be false.  Depending on what function
calls fn_type_unification, XARGS could be either a list of function
arguments or a list of parameter types.

This patch unifies type_unification_real_args and
type_unification_real_parms and changes all callers of
type_unification_real and fn_type_unification so that XARGS is a an
instance of VEC(tree,heap).  This VEC instance may represent either a
list of function arguments or a list of parameter types.  By passing
an instance of VEC to type_unification_real, the function can be
independent of the internal representation of TYPE_ARG_TYPES and a
list of function arguments.

The instance of VEC is allocated in heap, so the memory usage should
stay faily minimal.

Tested on x86_64-pc-linux-gnu.  OK to apply to the LTO branch?

Kazu Hirata

2006-08-15  Kazu Hirata  <kazu@codesourcery.com>

	* call.c (add_template_candidate_real): Pass an instance of
	VEC to fn_type_unification.
	* class.c (resolve_address_of_overloaded_function): Likewise.
	* pt.c (fn_type_unification): Change the type of ARGS to
	VEC(tree,heap) **. Call type_unification_real instead of
	type_unification_real_args.
	(type_unification_real_args): Remove.
	(type_unification_real_parms): Rename to
	type_unification_real.  Change the type of XARGS to
	VEC(tree,heap) *.
	(unify): Call type_unification_real instead of
	type_unification_real_parms.  Pass an intance of VEC to
	type_unification_real.
	(get_bindings): Pass an instance of VEC to
	fn_type_unification.
	* cp-tree.h: Update the prototype of fn_type_unification.

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 116137)
+++ cp/call.c	(working copy)
@@ -2205,6 +2205,7 @@ add_template_candidate_real (struct z_ca
   struct z_candidate *cand;
   int i;
   tree fn;
+  VEC(tree,heap) *v = NULL;
 
   /* We don't do deduction on the in-charge parameter, the VTT
      parameter or 'this'.  */
@@ -2216,10 +2217,15 @@ add_template_candidate_real (struct z_ca
       && CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl)))
     args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
 
+  /* Copy ARGS_WITHOUT_IN_CHRG to an instance of VEC.  */
+  for (;
+       args_without_in_chrg;
+       args_without_in_chrg = TREE_CHAIN (args_without_in_chrg))
+    VEC_safe_push (tree, heap, v, TREE_VALUE (args_without_in_chrg));
   i = fn_type_unification (tmpl, explicit_targs, targs,
-			   args_without_in_chrg,
+			   &v,
 			   return_type, strict, flags);
-
+  VEC_free (tree, heap, v);
   if (i != 0)
     return NULL;
 
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 116137)
+++ cp/class.c	(working copy)
@@ -5765,6 +5765,10 @@ resolve_address_of_overloaded_function (
 	  tree instantiation;
 	  tree instantiation_type;
 	  tree targs;
+	  VEC(tree,heap) *v;
+	  int result;
+	  int len;
+	  int i;
 
 	  if (TREE_CODE (fn) != TEMPLATE_DECL)
 	    /* We're only looking for templates.  */
@@ -5778,9 +5782,17 @@ resolve_address_of_overloaded_function (
 
 	  /* Try to do argument deduction.  */
 	  targs = make_tree_vec (DECL_NTPARMS (fn));
-	  if (fn_type_unification (fn, explicit_targs, targs,
-				   target_arg_types, target_ret_type,
-				   DEDUCE_EXACT, LOOKUP_NORMAL))
+
+	  /* Copy TARGET_ARG_TYPES to an instance of VEC.  */
+	  len = num_parm_types (target_arg_types);
+	  v = VEC_alloc (tree, heap, len);
+	  for (i = 0; i < len; i++)
+	    VEC_quick_push (tree, v, nth_parm_type (target_arg_types, i));
+	  result = fn_type_unification (fn, explicit_targs, targs,
+					&v, target_ret_type,
+					DEDUCE_EXACT, LOOKUP_NORMAL);
+	  VEC_free (tree, heap, v);
+	  if (result)
 	    /* Argument deduction failed.  */
 	    continue;
 
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 116137)
+++ cp/cp-tree.h	(working copy)
@@ -4105,7 +4105,7 @@ extern int uses_template_parms			(tree);
 extern int uses_template_parms_level		(tree, int);
 extern tree instantiate_class_template		(tree);
 extern tree instantiate_template		(tree, tree, tsubst_flags_t);
-extern int fn_type_unification			(tree, tree, tree, tree,
+extern int fn_type_unification			(tree, tree, tree, VEC(tree,heap) **,
 						 tree, unification_kind_t, int);
 extern void mark_decl_instantiated		(tree, int);
 extern int more_specialized_fn			(tree, tree, int);
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 116137)
+++ cp/pt.c	(working copy)
@@ -111,10 +111,8 @@ static tree add_to_template_args (tree, 
 static tree add_outermost_template_args (tree, tree);
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
-static int  type_unification_real_args (tree, tree, tree, tree, tree,
-					int, unification_kind_t, int);
-static int  type_unification_real_parms (tree, tree, tree, tree, tree,
-					 int, unification_kind_t, int);
+static int type_unification_real (tree, tree, tree, tree, VEC(tree,heap) *,
+				  int, unification_kind_t, int);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
 static tree convert_nontype_argument (tree, tree);
@@ -9272,7 +9270,7 @@ int
 fn_type_unification (tree fn,
 		     tree explicit_targs,
 		     tree targs,
-		     tree args,
+		     VEC(tree,heap) **args,
 		     tree return_type,
 		     unification_kind_t strict,
 		     int flags)
@@ -9340,21 +9338,30 @@ fn_type_unification (tree fn,
   parms = TYPE_ARG_TYPES (fntype);
   /* Never do unification on the 'this' parameter.  */
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
-    parms = TREE_CHAIN (parms);
+    parms = copy_type_arg_types_skip (parms, 1);
 
   if (return_type)
     {
-      parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
-      args = tree_cons (NULL_TREE, return_type, args);
+      int len = num_parm_types (parms);
+      tree new_parms = alloc_parm_types (1 + len);
+      int i;
+
+      *(nth_parm_type_ptr (new_parms, 0)) = TREE_TYPE (fntype);
+      for (i = 0; i < len; i++)
+	*(nth_parm_type_ptr (new_parms, 1 + i))
+	  = nth_parm_type (parms, i);
+      parms = new_parms;
+
+      VEC_safe_insert (tree, heap, *args, 0, return_type);
     }
 
   /* We allow incomplete unification without an error message here
      because the standard doesn't seem to explicitly prohibit it.  Our
      callers must be ready to deal with unification failures in any
      event.  */
-  result = type_unification_real_args (fn, DECL_INNERMOST_TEMPLATE_PARMS (fn),
-				       targs, parms, args, /*subr=*/0,
-				       strict, flags);
+  result = type_unification_real (fn, DECL_INNERMOST_TEMPLATE_PARMS (fn),
+				  targs, parms, *args, /*subr=*/0,
+				  strict, flags);
 
   if (result == 0)
     /* All is well so far.  Now, check:
@@ -9465,197 +9472,14 @@ maybe_adjust_types_for_deduction (unific
    template). */
 
 static int
-type_unification_real_args (tree fn,
-			    tree tparms,
-			    tree targs,
-			    tree xparms,
-			    tree xargs,
-			    int subr,
-			    unification_kind_t strict,
-			    int flags)
-{
-  int i;
-  int ntparms = TREE_VEC_LENGTH (tparms);
-  int sub_strict;
-  int saw_undeduced = 0;
-  tree args;
-  tree xparmdecls, parmdecls;
-  int parms_len;
-
-  gcc_assert (TREE_CODE (tparms) == TREE_VEC);
-  gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
-  gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
-  gcc_assert (ntparms > 0);
-
-  if (fn)
-    {
-      if (DECL_FUNCTION_TEMPLATE_P (fn))
-	fn = DECL_TEMPLATE_RESULT (fn);
-      gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
-
-      xparmdecls = DECL_ARGUMENTS (fn);
-
-      /* Never do unification on the 'this' parameter.  */
-      if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
-	xparmdecls = TREE_CHAIN (xparmdecls);
-    }
-  else
-    xparmdecls = NULL_TREE;
-
-  switch (strict)
-    {
-    case DEDUCE_CALL:
-      sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
-		    | UNIFY_ALLOW_DERIVED);
-      break;
-
-    case DEDUCE_CONV:
-      sub_strict = UNIFY_ALLOW_LESS_CV_QUAL;
-      break;
-
-    case DEDUCE_EXACT:
-      sub_strict = UNIFY_ALLOW_NONE;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
-
- again:
-  parms_len = num_parm_types (xparms);
-  args = xargs;
-  parmdecls = xparmdecls;
-
-  for (i = 0; (i < parms_len
-	       && !(i + 1 == parms_len
-		    && nth_parm_type (xparms, i) == void_type_node)
-	       && args
-	       && !(args
-		    && TREE_VALUE (args) == void_type_node
-		    && TREE_CHAIN (args) == NULL_TREE));
-       i++)
-    {
-      tree parm = nth_parm_type (xparms, i);
-      tree arg = TREE_VALUE (args);
-      args = TREE_CHAIN (args);
-      if (parmdecls)
-	parmdecls = TREE_CHAIN (parmdecls);
-
-      if (arg == error_mark_node)
-	return 1;
-      if (arg == unknown_type_node)
-	/* We can't deduce anything from this, but we might get all the
-	   template args from other function args.  */
-	continue;
-
-      /* Conversions will be performed on a function argument that
-	 corresponds with a function parameter that contains only
-	 non-deducible template parameters and explicitly specified
-	 template parameters.  */
-      if (!uses_template_parms (parm))
-	{
-	  tree type;
-
-	  if (!TYPE_P (arg))
-	    type = TREE_TYPE (arg);
-	  else
-	    type = arg;
-
-	  if (same_type_p (parm, type))
-	    continue;
-	  if (strict != DEDUCE_EXACT
-	      && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg, 
-				  flags))
-	    continue;
-	  
-	  return 1;
-	}
-
-      if (!TYPE_P (arg))
-	{
-	  gcc_assert (TREE_TYPE (arg) != NULL_TREE);
-	  if (type_unknown_p (arg))
-	    {
-	      /* [temp.deduct.type] A template-argument can be deduced from
-		 a pointer to function or pointer to member function
-		 argument if the set of overloaded functions does not
-		 contain function templates and at most one of a set of
-		 overloaded functions provides a unique match.  */
-
-	      if (resolve_overloaded_unification
-		  (tparms, targs, parm, arg, strict, sub_strict)
-		  != 0)
-		return 1;
-	      continue;
-	    }
-	  arg = TREE_TYPE (arg);
-	  if (arg == error_mark_node)
-	    return 1;
-	}
-
-      {
-	int arg_strict = sub_strict;
-
-	if (!subr)
-	  arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
-
-	if (unify (tparms, targs, parm, arg, arg_strict))
-	  return 1;
-      }
-    }
-
-  /* Fail if we've reached the end of the parm list, and more args
-     are present, and the parm list isn't variadic.  */
-  if (args
-      && !(args
-	   && TREE_VALUE (args) == void_type_node
-	   && TREE_CHAIN (args) == NULL_TREE)
-      && (i + 1 == parms_len
-	  && nth_parm_type (xparms, i) == void_type_node))
-    return 1;
-  /* Fail if parms are left and they don't have default values.  */
-  if (i < parms_len
-      && !(i + 1 == parms_len
-	   && nth_parm_type (xparms, i) == void_type_node)
-      && parmdecls && DECL_INITIAL (parmdecls) == NULL_TREE)
-    return 1;
-
-  if (!subr)
-    for (i = 0; i < ntparms; i++)
-      if (!TREE_VEC_ELT (targs, i))
-	{
-	  tree tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
-
-	  /* If this is an undeduced nontype parameter that depends on
-	     a type parameter, try another pass; its type may have been
-	     deduced from a later argument than the one from which
-	     this parameter can be deduced.  */
-	  if (TREE_CODE (tparm) == PARM_DECL
-	      && uses_template_parms (TREE_TYPE (tparm))
-	      && !saw_undeduced++)
-	    goto again;
-
-	  return 2;
-	}
-
-  return 0;
-}
-
-/* Most parms like fn_type_unification.
-
-   If SUBR is 1, we're being called recursively (to unify the
-   arguments of a function or method parameter of a function
-   template). */
-
-static int
-type_unification_real_parms (tree fn,
-			     tree tparms,
-			     tree targs,
-			     tree xparms,
-			     tree xargs,
-			     int subr,
-			     unification_kind_t strict,
-			     int flags)
+type_unification_real (tree fn,
+		       tree tparms,
+		       tree targs,
+		       tree xparms,
+		       VEC(tree,heap) *xargs,
+		       int subr,
+		       unification_kind_t strict,
+		       int flags)
 {
   int i;
   int ntparms = TREE_VEC_LENGTH (tparms);
@@ -9666,7 +9490,6 @@ type_unification_real_parms (tree fn,
 
   gcc_assert (TREE_CODE (tparms) == TREE_VEC);
   gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
-  gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
   gcc_assert (ntparms > 0);
 
   if (fn)
@@ -9707,14 +9530,14 @@ type_unification_real_parms (tree fn,
   parmdecls = xparmdecls;
 
   parms_len = num_parm_types (xparms);
-  args_len = num_parm_types (xargs);
+  args_len = VEC_length (tree, xargs);
 
   {
     int parms_arity = parms_len;
     int args_arity = args_len;
 
     if (args_len
-	&& nth_parm_type (xargs, args_len - 1) == void_type_node)
+	&& VEC_index (tree, xargs, args_len - 1) == void_type_node)
       args_arity--;
 
     if (parms_len
@@ -9734,7 +9557,7 @@ type_unification_real_parms (tree fn,
   for (i = 0; i < arity; i++)
     {
       tree parm = nth_parm_type (xparms, i);
-      tree arg = nth_parm_type (xargs, i);
+      tree arg = VEC_index (tree, xargs, i);
 
       if (parmdecls)
 	parmdecls = TREE_CHAIN (parmdecls);
@@ -9831,12 +9654,11 @@ type_unification_real_parms (tree fn,
   return 0;
 }
 
-/* Subroutine of type_unification_real_args and
-   type_unificaiton_real_parms.  Args are like the variables at the
-   call site.  ARG is an overloaded function (or template-id); we try
-   deducing template args from each of the overloads, and if only one
-   succeeds, we go with that.  Modifies TARGS and returns 0 on
-   success.  */
+/* Subroutine of type_unification_real.  Args are like the variables
+   at the call site.  ARG is an overloaded function (or template-id);
+   we try deducing template args from each of the overloads, and if
+   only one succeeds, we go with that.  Modifies TARGS and returns 0
+   on success.  */
 
 static int
 resolve_overloaded_unification (tree tparms,
@@ -10654,7 +10476,7 @@ unify (tree tparms, tree targs, tree par
 
       /* CV qualifications for methods can never be deduced, they must
   	 match exactly.  We need to check them explicitly here,
-  	 because type_unification_real_parms treats them as any other
+  	 because type_unification_real treats them as any other
   	 cvqualified parameter.  */
       if (TREE_CODE (parm) == METHOD_TYPE
 	  && (!check_cv_quals_for_unify
@@ -10666,9 +10488,23 @@ unify (tree tparms, tree targs, tree par
       if (unify (tparms, targs, TREE_TYPE (parm),
 		 TREE_TYPE (arg), UNIFY_ALLOW_NONE))
 	return 1;
-      return type_unification_real_parms (NULL, tparms, targs, TYPE_ARG_TYPES (parm),
-					  TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
-					  LOOKUP_NORMAL);
+
+      {
+	tree parm_types = TYPE_ARG_TYPES (arg);
+	int len = num_parm_types (parm_types);
+	VEC(tree,heap) *v = VEC_alloc (tree, heap, len);
+	int i;
+	int result;
+
+	/* Copy PARM_TYPES to an instance of VEC.  */
+	for (i = 0; i < len; i++)
+	  VEC_quick_push (tree, v, nth_parm_type (parm_types, i));
+	result = type_unification_real (NULL, tparms, targs, TYPE_ARG_TYPES (parm),
+					v, 1, DEDUCE_EXACT,
+					LOOKUP_NORMAL);
+	VEC_free (tree, heap, v);
+	return result;
+      }
 
     case OFFSET_TYPE:
       /* Unify a pointer to member with a pointer to member function, which
@@ -11056,6 +10892,11 @@ get_bindings (tree fn, tree decl, tree e
   tree targs = make_tree_vec (ntparms);
   tree decl_type;
   tree decl_arg_types;
+  int skip = 0;
+  int len;
+  int i;
+  VEC(tree,heap) *v;
+  int result;
 
   /* Substitute the explicit template arguments into the type of DECL.
      The call to fn_type_unification will handle substitution into the
@@ -11089,14 +10930,21 @@ get_bindings (tree fn, tree decl, tree e
   decl_arg_types = TYPE_ARG_TYPES (decl_type);
   /* Never do unification on the 'this' parameter.  */
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
-    decl_arg_types = TREE_CHAIN (decl_arg_types);
+    skip++;
 
-  if (fn_type_unification (fn, explicit_args, targs,
-			   decl_arg_types,
-			   (check_rettype || DECL_CONV_FN_P (fn)
-			    ? TREE_TYPE (decl_type) : NULL_TREE),
-			   DEDUCE_EXACT, LOOKUP_NORMAL))
-    return NULL_TREE;
+  /* Copy DECL_ARG_TYPES to an instance of VEC.  */
+  len = num_parm_types (decl_arg_types);
+  v = VEC_alloc (tree, heap, len - skip);
+  for (i = skip; i < len; i++)
+    VEC_quick_push (tree, v, nth_parm_type (decl_arg_types, i));
+  result = fn_type_unification (fn, explicit_args, targs,
+				&v,
+				(check_rettype || DECL_CONV_FN_P (fn)
+				 ? TREE_TYPE (decl_type) : NULL_TREE),
+				DEDUCE_EXACT, LOOKUP_NORMAL);
+  VEC_free (tree, heap, v);
+  if (result)
+     return NULL_TREE;
 
   return targs;
 }


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