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]

C++ PATCH: Fix template unification regression


This patch fixes a template argument deduction regression with array
types.  Tested on i686-pc-linux-gnu, applied on the mainline and on
the 3.4 branch.  The 3.4 version of the patch contains only the hunk
that converts the type of the argument; the remainder is just cleanup.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-08-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16246
	* pt.c (unify): Tidy ARRAY_TYPE handling.  Make sure that non-type
	arguments have the same type as the corresponding parameter.

2004-08-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16246
	* g++.dg/template/array7.C: New test.

Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.906
diff -c -5 -p -r1.906 pt.c
*** cp/pt.c	17 Aug 2004 17:32:34 -0000	1.906
--- cp/pt.c	18 Aug 2004 02:47:00 -0000
*************** check_cv_quals_for_unify (int strict, tr
*** 9639,9656 ****
       UNIFY_ALLOW_OUTER_MORE_CV_QUAL:
         This is the outermost level of a deduction, and PARM can be more CV
         qualified at this point.
       UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
         This is the outermost level of a deduction, and PARM can be less CV
!        qualified at this point.
!      UNIFY_ALLOW_MAX_CORRECTION:
!        This is an INTEGER_TYPE's maximum value.  Used if the range may
!        have been derived from a size specification, such as an array size.
!        If the size was given by a nontype template parameter N, the maximum
!        value will have the form N-1.  The flag says that we can (and indeed
!        must) unify N with (ARG + 1), an exception to the normal rules on
!        folding PARM.  */
  
  static int
  unify (tree tparms, tree targs, tree parm, tree arg, int strict)
  {
    int idx;
--- 9639,9649 ----
       UNIFY_ALLOW_OUTER_MORE_CV_QUAL:
         This is the outermost level of a deduction, and PARM can be more CV
         qualified at this point.
       UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
         This is the outermost level of a deduction, and PARM can be less CV
!        qualified at this point.  */
  
  static int
  unify (tree tparms, tree targs, tree parm, tree arg, int strict)
  {
    int idx;
*************** unify (tree tparms, tree targs, tree par
*** 9700,9710 ****
      strict &= ~UNIFY_ALLOW_MORE_CV_QUAL;
    strict &= ~UNIFY_ALLOW_OUTER_LEVEL;
    strict &= ~UNIFY_ALLOW_DERIVED;
    strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
    strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
-   strict &= ~UNIFY_ALLOW_MAX_CORRECTION;
    
    switch (TREE_CODE (parm))
      {
      case TYPENAME_TYPE:
      case SCOPE_REF:
--- 9693,9702 ----
*************** unify (tree tparms, tree targs, tree par
*** 9862,9872 ****
        else if (same_type_p (TREE_TYPE (arg), tparm))
  	/* OK */;
        else if ((strict & UNIFY_ALLOW_INTEGER)
  	       && (TREE_CODE (tparm) == INTEGER_TYPE
  		   || TREE_CODE (tparm) == BOOLEAN_TYPE))
! 	/* OK */;
        else if (uses_template_parms (tparm))
  	/* We haven't deduced the type of this parameter yet.  Try again
  	   later.  */
  	return 0;
        else
--- 9854,9867 ----
        else if (same_type_p (TREE_TYPE (arg), tparm))
  	/* OK */;
        else if ((strict & UNIFY_ALLOW_INTEGER)
  	       && (TREE_CODE (tparm) == INTEGER_TYPE
  		   || TREE_CODE (tparm) == BOOLEAN_TYPE))
! 	/* Convert the ARG to the type of PARM; the deduced non-type
! 	   template argument must exactly match the types of the
! 	   corresponding parameter.  */
! 	arg = fold (build_nop (TREE_TYPE (parm), arg));
        else if (uses_template_parms (tparm))
  	/* We haven't deduced the type of this parameter yet.  Try again
  	   later.  */
  	return 0;
        else
*************** unify (tree tparms, tree targs, tree par
*** 9930,9943 ****
        if (TREE_CODE (arg) != ARRAY_TYPE)
  	return 1;
        if ((TYPE_DOMAIN (parm) == NULL_TREE)
  	  != (TYPE_DOMAIN (arg) == NULL_TREE))
  	return 1;
!       if (TYPE_DOMAIN (parm) != NULL_TREE
! 	  && unify (tparms, targs, TYPE_DOMAIN (parm),
! 		    TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE) != 0)
! 	return 1;
        return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
  		    strict & UNIFY_ALLOW_MORE_CV_QUAL);
  
      case REAL_TYPE:
      case COMPLEX_TYPE:
--- 9925,9957 ----
        if (TREE_CODE (arg) != ARRAY_TYPE)
  	return 1;
        if ((TYPE_DOMAIN (parm) == NULL_TREE)
  	  != (TYPE_DOMAIN (arg) == NULL_TREE))
  	return 1;
!       if (TYPE_DOMAIN (parm) != NULL_TREE)
! 	{
! 	  tree parm_max;
! 	  tree arg_max;
! 
! 	  parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
! 	  arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
! 
! 	  /* Our representation of array types uses "N - 1" as the
! 	     TYPE_MAX_VALUE for an array with "N" elements, if "N" is
! 	     not an integer constant.  */
! 	  if (TREE_CODE (parm_max) == MINUS_EXPR)
! 	    {
! 	      arg_max = fold (build2 (PLUS_EXPR, 
! 				      integer_type_node,
! 				      arg_max,
! 				      TREE_OPERAND (parm_max, 1)));
! 	      parm_max = TREE_OPERAND (parm_max, 0);
! 	    }
! 
! 	  if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
! 	    return 1;
! 	}
        return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
  		    strict & UNIFY_ALLOW_MORE_CV_QUAL);
  
      case REAL_TYPE:
      case COMPLEX_TYPE:
*************** unify (tree tparms, tree targs, tree par
*** 9945,9971 ****
      case INTEGER_TYPE:
      case BOOLEAN_TYPE:
      case VOID_TYPE:
        if (TREE_CODE (arg) != TREE_CODE (parm))
  	return 1;
! 
!       if (TREE_CODE (parm) == INTEGER_TYPE
! 	  && TREE_CODE (TYPE_MAX_VALUE (parm)) != INTEGER_CST)
! 	{
! 	  if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
! 	      && unify (tparms, targs, TYPE_MIN_VALUE (parm),
! 			TYPE_MIN_VALUE (arg), UNIFY_ALLOW_INTEGER))
! 	    return 1;
! 	  if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
! 	      && unify (tparms, targs, TYPE_MAX_VALUE (parm),
! 			TYPE_MAX_VALUE (arg),
! 			UNIFY_ALLOW_INTEGER | UNIFY_ALLOW_MAX_CORRECTION))
! 	    return 1;
! 	}
        /* We have already checked cv-qualification at the top of the
  	 function.  */
!       else if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
  	return 1;
  
        /* As far as unification is concerned, this wins.	 Later checks
  	 will invalidate it if necessary.  */
        return 0;
--- 9959,9972 ----
      case INTEGER_TYPE:
      case BOOLEAN_TYPE:
      case VOID_TYPE:
        if (TREE_CODE (arg) != TREE_CODE (parm))
  	return 1;
!       
        /* We have already checked cv-qualification at the top of the
  	 function.  */
!       if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
  	return 1;
  
        /* As far as unification is concerned, this wins.	 Later checks
  	 will invalidate it if necessary.  */
        return 0;
*************** unify (tree tparms, tree targs, tree par
*** 10087,10117 ****
      case FIELD_DECL:
      case TEMPLATE_DECL:
        /* Matched cases are handled by the ARG == PARM test above.  */
        return 1;
  
-     case MINUS_EXPR:
-       if (tree_int_cst_equal (TREE_OPERAND (parm, 1), integer_one_node)
- 	  && (strict_in & UNIFY_ALLOW_MAX_CORRECTION))
- 	{
- 	  /* We handle this case specially, since it comes up with
- 	     arrays.  In particular, something like:
- 
- 	     template <int N> void f(int (&x)[N]);
- 
- 	     Here, we are trying to unify the range type, which
- 	     looks like [0 ... (N - 1)].  */
- 	  tree t, t1, t2;
- 	  t1 = TREE_OPERAND (parm, 0);
- 	  t2 = TREE_OPERAND (parm, 1);
- 
- 	  t = fold (build2 (PLUS_EXPR, integer_type_node, arg, t2));
- 
- 	  return unify (tparms, targs, t1, t, strict);
- 	}
-       /* Else fall through.  */
- 
      default:
        if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
  	{
  
  	  /* We're looking at an expression.  This can happen with
--- 10088,10097 ----
Index: testsuite/g++.dg/template/array7.C
===================================================================
RCS file: testsuite/g++.dg/template/array7.C
diff -N testsuite/g++.dg/template/array7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/array7.C	18 Aug 2004 02:47:01 -0000
***************
*** 0 ****
--- 1,11 ----
+ // PR c++/16246
+ 
+ template <typename T> void foo (T, T); 
+  
+ template <unsigned N, unsigned M>  
+ int bar( const char(&val)[M] ) 
+ { 
+   foo (N,M); 
+ } 
+  
+ int i = bar<10>("1234"); 


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