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 PR6620


Hi

The appended patch fixes a partial specialization bug involving
template parameter dependent expression.  This has been reported
in GNATS as PR6620.  The problem is when gcc is deciding
whether
        template <int N> struct Add<HoldInt<N>, HoldInt<-N> >
or
        template <int N, int M> struct Add<HoldInt<N>, HoldInt<M> >
is more specialized.  Current gcc has 2 different bugs that cause
the partial ordering of the above templates to fail.

The case when PARM is M, and ARG is -N.  In function unify(),
ARG is a template parameter dependent expression.  So its TREE_TYPE is
NULL_TREE.  Attempt to call same_type_p in this case produces a segfault.

On the other hand, when PARM is -N and ARG is M.  The function
verify_class_unification think that M and -N are equivalent due to the
uses_template_parms function call.  The code no longer applies now and
is simplified in the patch.

Bootstrapped and tested with no regressions.  Ok to commit to the main
trunk?

--Kriang


2002-05-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

        PR c++/6620
        * pt.c (verify_class_unification): Don't check if PARM is template
        parameter dependent.  Simplify.
        (unify) [TEMPLATE_PARM_INDEX]: Handle when ARG is a template
        parameter dependent expression.


diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c   Fri May 10 22:36:23 2002
--- gcc-main-new/gcc/cp/pt.c    Wed May 15 22:03:28 2002
*************** static int
*** 8307,8335 ****
  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),
!                          tf_none, 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
--- 8307,8318 ----
  verify_class_unification (targs, parms, args)
       tree targs, parms, args;
  {
!   parms = tsubst (parms, add_outermost_template_args (args, targs),
!                 tf_none, NULL_TREE);
!   if (parms == error_mark_node)
      return 1;
  
!   return !comp_template_args (parms, INNERMOST_TEMPLATE_ARGS (args));
  }
  
  /* PARM is a template class (perhaps with unbound template
*************** unify (tparms, targs, parm, arg, strict)
*** 8812,8819 ****
         deduced from an array bound may be of any integral type. 
         The non-type parameter might use already deduced type parameters.  */
        tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
!       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))
--- 8795,8806 ----
         deduced from an array bound may be of any integral type. 
         The non-type parameter might use already deduced type parameters.  */
        tparm = tsubst (TREE_TYPE (parm), targs, 0, NULL_TREE);
!       if (!TREE_TYPE (arg))
!       /* Template-parameter dependent expression.  Just accept it for now.
!          It will later be processed in convert_template_argument.  */
!       ;
!       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))
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/partial1.C gcc-main-new/gcc/testsuite/g++.dg/template/partial1.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/partial1.C      Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/partial1.C       Wed May 15 22:00:51 2002
***************
*** 0 ****
--- 1,36 ----
+ // { dg-do run }
+ // Origin: Jo Totland <jototland@hotmail.com>
+ 
+ // PR c++/6620
+ // Partial specialization involving expression of non-type template
+ // parameter causes ICE.
+ 
+ extern "C" void abort();
+ 
+ template <int N> struct HoldInt
+ {
+ };
+ 
+ template <class A, class B> struct Add
+ {
+ };
+ 
+ template <int N> struct Add<HoldInt<N>, HoldInt<-N> >
+ {
+   typedef int type;
+   int f() { return 0; }
+ };
+ 
+ template <int N, int M> 
+ struct Add<HoldInt<N>, HoldInt<M> >
+ {
+   typedef HoldInt<N+M> type;
+   int f() { return 1; }
+ };
+ 
+ int main() {
+   Add<HoldInt<1>, HoldInt<-1> > a;
+   Add<HoldInt<1>, HoldInt<-2> > b;
+   if (a.f() != 0 || b.f() != 1)
+     abort();
+ }


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