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 Re: infinite loop in most_general_template



Brendan --

  I checked in the following patch for your problem.  Your test-case
still doesn't compile, because the compiler is now (correctly)
checking for re-declarations of template parameters, thanks to 
Benjamin Kosnik.

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

1998-08-24  Mark Mitchell  <mark@markmitchell.com>

	* pt.c (tsubst_decl): Move special case code for dealing with
	tricky friend templates here from ...
	(regenerate_decl_from_template): Here.

Index: testsuite/g++.old-deja/g++.pt/friend32.C
===================================================================
RCS file: friend32.C
diff -N friend32.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- friend32.C	Mon Aug 24 19:23:26 1998
***************
*** 0 ****
--- 1,16 ----
+ // Build don't link:
+ 
+ template <class T, class U>
+ struct S {
+   template <class X, class Y, class Z>
+   friend X f(X, Y, Z);
+ };
+ 
+ template class S<int, double>;
+ template char f(char, long, short);
+ template char* f(char*, long*, short*);
+ 
+ template <class X, class Y, class Z>
+ X f(X x, Y, Z) {
+   return x;
+ }
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.185
diff -c -p -r1.185 pt.c
*** pt.c	1998/08/24 12:07:58	1.185
--- pt.c	1998/08/25 02:23:50
*************** tsubst_decl (t, args, type, in_decl)
*** 4863,4868 ****
--- 4863,4870 ----
  	tree argvec;
  	tree gen_tmpl;
  	int member;
+ 	int args_depth;
+ 	int parms_depth;
  
  	/* Nobody should be tsubst'ing into non-template functions.  */
  	my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
*************** tsubst_decl (t, args, type, in_decl)
*** 4885,4890 ****
--- 4887,4933 ----
  		r = spec;
  		break;
  	      }
+ 
+ 	    /* Here, we deal with the peculiar case:
+ 
+ 		 template <class T> struct S { 
+ 		   template <class U> friend void f();
+ 		 };
+ 		 template <class U> friend void f() {}
+ 		 template S<int>;
+ 		 template void f<double>();
+ 
+ 	       Here, the ARGS for the instantiation of will be {int,
+ 	       double}.  But, we only need as many ARGS as there are
+ 	       levels of template parameters in CODE_PATTERN.  We are
+ 	       careful not to get fooled into reducing the ARGS in
+ 	       situations like:
+ 
+ 		 template <class T> struct S { template <class U> void f(U); }
+ 		 template <class T> template <> void S<T>::f(int) {}
+ 
+ 	       which we can spot because the pattern will be a
+ 	       specialization in this case.  */
+ 	    args_depth = TMPL_ARGS_DEPTH (args);
+ 	    parms_depth = 
+ 	      TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); 
+ 	    if (args_depth > parms_depth
+ 		&& !DECL_TEMPLATE_SPECIALIZATION (t))
+ 	      {
+ 		my_friendly_assert (DECL_FRIEND_P (t), 0);
+ 
+ 		if (parms_depth > 1)
+ 		  {
+ 		    int i;
+ 
+ 		    args = make_temp_vec (parms_depth);
+ 		    for (i = 0; i < parms_depth; ++i)
+ 		      TREE_VEC_ELT (args, i) = 
+ 			TREE_VEC_ELT (args, i + (args_depth - parms_depth));
+ 		  }
+ 		else
+ 		  args = TREE_VEC_ELT (args, args_depth - parms_depth);
+ 	      }
  	  }
  	else
  	  {
*************** regenerate_decl_from_template (decl, tmp
*** 7739,7747 ****
    tree code_pattern;
    tree new_decl;
    tree gen_tmpl;
-   tree subst_args;
-   int args_depth;
-   int parms_depth;
    int unregistered;
  
    args = DECL_TI_ARGS (decl);
--- 7782,7787 ----
*************** regenerate_decl_from_template (decl, tmp
*** 7759,7810 ****
       happening: we created a specialization but did not call
       register_specialization for it.  */
    my_friendly_assert (unregistered, 0);
- 
-   /* Do the substitution to get the new declaration.  Normally, of
-      course, we want the full set of ARGS.  However, one peculiar case
-      is code like this: 
- 
-        template <class T> struct S { 
- 	 template <class U> friend void f();
-        };
-        template <class U> friend void f() {}
-        template S<int>;
-        template void f<double>();
- 
-      Here, the ARGS for the instantiation of will be {int, double}.
-      But, we only need as many ARGS as there are levels of template
-      parameters in CODE_PATTERN.  We are careful not to get fooled
-      into reducing the ARGS in situations like:
- 
-        template <class T> struct S { template <class U> void f(U); }
-        template <class T> template <> void S<T>::f(int) {}
- 
-      which we can spot because the innermost template args for the
-      CODE_PATTERN don't use any template parameters.  */
-   args_depth = TMPL_ARGS_DEPTH (args);
-   parms_depth = 
-     TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (code_pattern)));
-   if (args_depth > parms_depth
-       && !DECL_TEMPLATE_SPECIALIZATION (code_pattern))
-     {
-       int i;
- 
-       subst_args = make_temp_vec (parms_depth);
-       for (i = 0; i < parms_depth; ++i)
- 	TREE_VEC_ELT (subst_args, i) = 
- 	  TREE_VEC_ELT (args, i + (args_depth - parms_depth));
-     }
-   else
-     subst_args = args;
  
!   new_decl = tsubst (code_pattern, subst_args, NULL_TREE);
  
    if (TREE_CODE (decl) == VAR_DECL)
      {
        /* Set up DECL_INITIAL, since tsubst doesn't.  */
        pushclass (DECL_CONTEXT (decl), 2);
        DECL_INITIAL (new_decl) = 
! 	tsubst_expr (DECL_INITIAL (code_pattern), subst_args, 
  		     DECL_TI_TEMPLATE (decl));
        popclass (1);
      }
--- 7799,7814 ----
       happening: we created a specialization but did not call
       register_specialization for it.  */
    my_friendly_assert (unregistered, 0);
  
!   /* Do the substitution to get the new declaration.  */
!   new_decl = tsubst (code_pattern, args, NULL_TREE);
  
    if (TREE_CODE (decl) == VAR_DECL)
      {
        /* Set up DECL_INITIAL, since tsubst doesn't.  */
        pushclass (DECL_CONTEXT (decl), 2);
        DECL_INITIAL (new_decl) = 
! 	tsubst_expr (DECL_INITIAL (code_pattern), args, 
  		     DECL_TI_TEMPLATE (decl));
        popclass (1);
      }


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