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]

Re: [C++ PATCH]Fix for bug 29,g++.oliva/partspec1.C (revised)



On 4 Dec 2000, Jason Merrill wrote:

> > ! 	  if (!uses_template_parms (parm))
> > ! 	    {
> > ! 	      while (TREE_CODE (arg) == NOP_EXPR)
> > ! 		arg = TREE_OPERAND (arg, 0);
> > ! 
> > ! 	      if (!template_args_equal (parm, arg))
> > ! 		return 1;
> > ! 	    }
> 
> Rather than strip the NOP_EXPR here, fix template_args_equal to deal
> properly.
> 
> Jason
> 

How about this version?  Since we are only dealing with nontype template
arguments here, template_args_equal always calls cp_tree_equal.  
We can just call cp_tree_equal in the code above.  cp_tree_equal already 
knows how to deal with this extra NOP_EXPR.  This change is made to patch
below.  OK to commit this version?  (Tested on i586-pc-linux-gnu)

--Kriang

====================

ChangeLog for cp:

2000-12-04  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* pt.c (verify_class_unification): New function.
	(get_class_bindings): Use it.
	(try_class_unification): Tidy.
	(unify): Handle when argument of a template-id is not
	template parameter dependent.

ChangeLog for testsuite:

2000-12-04  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.
	* g++.old-deja/g++.pt/partial4.C: New test.

====================

diff -cprN gcc-old/gcc/cp/pt.c gcc-new/gcc/cp/pt.c
*** gcc-old/gcc/cp/pt.c	Fri Dec  1 17:34:26 2000
--- gcc-new/gcc/cp/pt.c	Mon Dec  4 18:06:36 2000
*************** static tree tsubst_call_declarator_parms
*** 157,162 ****
--- 157,163 ----
  static tree get_template_base_recursive PARAMS ((tree, tree,
  					       tree, tree, tree, int)); 
  static tree get_template_base PARAMS ((tree, tree, tree, tree));
+ static int verify_class_unification PARAMS ((tree, tree, tree));
  static tree try_class_unification PARAMS ((tree, tree, tree, tree));
  static int coerce_template_template_parms PARAMS ((tree, tree, int,
  						 tree, tree));
*************** try_one_overload (tparms, orig_targs, ta
*** 8038,8043 ****
--- 8039,8090 ----
    return 1;
  }
  
+ /* Verify that nondeduce template argument agrees with the type
+    obtained from argument deduction.  Return nonzero if the
+    verification fails.
+ 
+    For example:
+ 
+      struct A { typedef int X; };
+      template <class T, class U> struct C {};
+      template <class T> struct C<T, typename T::X> {};
+ 
+    Then with the instantiation `C<A, int>', we can deduce that
+    `T' is `A' but unify () does not check whether `typename T::X'
+    is `int'.  This function ensure that they agree.
+ 
+    TARGS, PARMS are the same as the arguments of unify.
+    ARGS contains template arguments from all levels.  */
+ 
+ static int
+ verify_class_unification (targs, parms, args)
+      tree targs, parms, args;
+ {
+   int i;
+   int nparms = TREE_VEC_LENGTH (parms);
+   tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
+   			   /*complain=*/0, NULL_TREE);
+   if (new_parms == error_mark_node)
+     return 1;
+ 
+   args = INNERMOST_TEMPLATE_ARGS (args);
+ 
+   for (i = 0; i < nparms; i++)
+     {
+       tree parm = TREE_VEC_ELT (new_parms, i);
+       tree arg = TREE_VEC_ELT (args, i);
+ 
+       /* In case we are deducing from a function argument of a function
+ 	 templates, some parameters may not be deduced yet.  So we
+ 	 make sure that only fully substituted elements of PARM are
+ 	 compared below.  */
+ 
+       if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
+ 	return 1;
+     }
+   return 0;
+ }
+ 
  /* PARM is a template class (perhaps with unbound template
     parameters).  ARG is a fully instantiated type.  If ARG can be
     bound to PARM, return ARG, otherwise return NULL_TREE.  TPARMS and
*************** try_class_unification (tparms, targs, pa
*** 8050,8056 ****
       tree parm;
       tree arg;
  {
-   int i;
    tree copy_of_targs;
  
    if (!CLASSTYPE_TEMPLATE_INFO (arg)
--- 8097,8102 ----
*************** try_class_unification (tparms, targs, pa
*** 8088,8101 ****
       with S<I, I, I>.  If we kept the already deduced knowledge, we
       would reject the possibility I=1.  */
    copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
-   i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
- 	     CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
    
    /* If unification failed, we're done.  */
!   if (i != 0)
      return NULL_TREE;
!   else
!     return arg;
  }
  
  /* Subroutine of get_template_base.  RVAL, if non-NULL, is a base we
--- 8134,8146 ----
       with S<I, I, I>.  If we kept the already deduced knowledge, we
       would reject the possibility I=1.  */
    copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
    
    /* If unification failed, we're done.  */
!   if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
! 	     CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
      return NULL_TREE;
! 
!   return arg;
  }
  
  /* Subroutine of get_template_base.  RVAL, if non-NULL, is a base we
*************** unify (tparms, targs, parm, arg, strict)
*** 8697,8721 ****
  
      default:
        if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
! 	/* We're looking at an expression.  This can happen with
! 	   something like: 
  	   
! 	     template <int I>
! 	     void foo(S<I>, S<I + 2>);
  
! 	   This is a "nondeduced context":
  
! 	     [deduct.type]
  	   
! 	     The nondeduced contexts are:
  
! 	     --A type that is a template-id in which one or more of
! 	       the template-arguments is an expression that references
! 	       a template-parameter.  
  
! 	   In these cases, we assume deduction succeeded, but don't
! 	   actually infer any unifications.  */
! 	return 0;
        else
  	sorry ("use of `%s' in template type unification",
  	       tree_code_name [(int) TREE_CODE (parm)]);
--- 8742,8774 ----
  
      default:
        if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
! 	{
! 
! 	  /* We're looking at an expression.  This can happen with
! 	     something like: 
  	   
! 	       template <int I>
! 	       void foo(S<I>, S<I + 2>);
  
! 	     This is a "nondeduced context":
  
! 	       [deduct.type]
  	   
! 	       The nondeduced contexts are:
  
! 	       --A type that is a template-id in which one or more of
! 	         the template-arguments is an expression that references
! 	         a template-parameter.  
  
! 	     In these cases, we assume deduction succeeded, but don't
! 	     actually infer any unifications.  */
! 
! 	  if (!uses_template_parms (parm) &&
! 	      cp_tree_equal (parm, arg) <= 0)
! 	    return 1;
! 	  else
! 	    return 0;
! 	}
        else
  	sorry ("use of `%s' in template type unification",
  	       tree_code_name [(int) TREE_CODE (parm)]);
*************** get_class_bindings (tparms, parms, args)
*** 8921,8934 ****
    int i, ntparms = TREE_VEC_LENGTH (tparms);
    tree vec = make_tree_vec (ntparms);
  
!   args = INNERMOST_TEMPLATE_ARGS (args);
! 
!   if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
      return NULL_TREE;
  
    for (i =  0; i < ntparms; ++i)
      if (! TREE_VEC_ELT (vec, i))
        return NULL_TREE;
  
    return vec;
  }
--- 8974,8989 ----
    int i, ntparms = TREE_VEC_LENGTH (tparms);
    tree vec = make_tree_vec (ntparms);
  
!   if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
!   	     UNIFY_ALLOW_NONE))
      return NULL_TREE;
  
    for (i =  0; i < ntparms; ++i)
      if (! TREE_VEC_ELT (vec, i))
        return NULL_TREE;
+ 
+   if (verify_class_unification (vec, parms, args))
+     return NULL_TREE;
  
    return vec;
  }
diff -cprN gcc-old/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C gcc-new/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C
*** gcc-old/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C	Sat Sep  4 08:09:04 1999
--- gcc-new/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C	Mon Dec  4 18:03:31 2000
*************** template <typename A, int* P> struct X;
*** 10,20 ****
  int a;
  
  template <typename A>
! struct X<A,&a> {}; // gets bogus error - candidate - XFAIL *-*-*
  
  int b;
  
  template <typename A>
! struct X<A,&b> {}; // gets bogus error - candidate - XFAIL *-*-*
  
! X<int,&a> x; // gets bogus error - ambiguous - XFAIL *-*-*
--- 10,20 ----
  int a;
  
  template <typename A>
! struct X<A,&a> {};
  
  int b;
  
  template <typename A>
! struct X<A,&b> {};
  
! X<int,&a> x;
diff -cprN gcc-old/gcc/testsuite/g++.old-deja/g++.pt/partial4.C gcc-new/gcc/testsuite/g++.old-deja/g++.pt/partial4.C
*** gcc-old/gcc/testsuite/g++.old-deja/g++.pt/partial4.C	Wed Dec 31 16:00:00 1969
--- gcc-new/gcc/testsuite/g++.old-deja/g++.pt/partial4.C	Mon Dec  4 18:03:32 2000
***************
*** 0 ****
--- 1,24 ----
+ // Build don't link:
+ // Origin: Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
+ 
+ // Bug 29.  We failed to verify that template argument deduction
+ // produces a valid result in nondeduce context.
+ 
+ template<class T> struct Y { typedef T X; };
+ 
+ template<class T, class U> struct Base {};
+ 
+ template<class T> struct Base<T, typename T::X> {};
+ 
+ template<class T> struct Base<typename T::X, T> {};
+ 
+ template<class T, class U> struct Derived : Base <T, U> {};
+ 
+ struct A {};
+ 
+ template<class T> struct Derived<A, T> : Base< Y<T>, Y<T> > {};
+ 
+ int main()
+ {
+   Derived<A, int> d;
+ }


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