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 to fix some template problems



Here's a patch that fixes a couple of problems reported earlier today,
as well as increasing the amount of error-checking we do for template
class declarations slightly.

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

1998-07-31  Mark Mitchell  <mark@markmitchell.com>

	* cp-tree.h (PROCESSING_REAL_TEMPLATE_DECL_P): New macro.
	(maybe_check_template_type): New function.
	* decl.c (maybe_process_template_type_declaration): New function,
	split out from pushtag  Call maybe_check_template_type.
	(pushtag): Use it.  Use PROCESSING_REAL_TEMPLATE_DECL_P.
	(xref_tag): Use PROCESSING_REAL_TEMPLATE_DECL_P.
	* friend.c (do_friend): Use PROCESSING_REAL_TEMPLATE_DECL_P.
	* pt.c (template_class_depth_real): Generalization of ...
	(template_class_depth): Use it.
	(register_specialization): Use duplicate_decls for duplicate
	declarations of specializations.
	(maybe_check_template_type): New function.
	(push_template_decl_real): Fix comment.
	(convert_nontype_argument): Likewise.
	(lookup_template_class): Likewise.  Avoid an infinite loop on
	erroneous code.
	(tsubst_friend_function): Fix comment.
	(tsubst, case FUNCTION_DECL): Deal with a DECL_TI_TEMPLATE that is
	an IDENTIFIER_NODE.
	* semantics.c (begin_function_definition): Use
	reset_specialization to note that template headers don't apply
	directly to declarations after the opening curly for a function.
  
Index: testsuite/g++.old-deja/g++.pt/crash15.C
===================================================================
RCS file: crash15.C
diff -N crash15.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- crash15.C	Fri Jul 31 14:45:04 1998
***************
*** 0 ****
--- 1,10 ----
+ // Build don't link:
+ 
+ template <class T>
+ template <class U>
+ struct A { // ERROR - too many template parameter lists
+ public:
+   A() {}
+ 
+   A(const A<T>& b) {} // ERROR - invalid use of template
+ };
Index: testsuite/g++.old-deja/g++.pt/explicit34.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/explicit34.C,v
retrieving revision 1.2
diff -c -p -r1.2 explicit34.C
*** explicit34.C	1998/01/20 00:57:36	1.2
--- explicit34.C	1998/07/31 21:45:04
*************** template <class T>
*** 4,10 ****
  void foo(T t);
  
  template <>
! void foo(int) {}; 
  
  template <>
  void foo<int>(int) {} // ERROR - duplicate specialization.
--- 4,10 ----
  void foo(T t);
  
  template <>
! void foo(int) {}; // ERROR - previously defined here.
  
  template <>
  void foo<int>(int) {} // ERROR - duplicate specialization.
Index: testsuite/g++.old-deja/g++.pt/friend28.C
===================================================================
RCS file: friend28.C
diff -N friend28.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- friend28.C	Fri Jul 31 14:45:04 1998
***************
*** 0 ****
--- 1,22 ----
+ // Build don't link:
+ 
+ class mystream;
+ 
+ template <class T> class a {
+ public:
+ 	friend mystream& operator>> <>( mystream&, a<T>& thea );
+ private:
+ 	T amember;
+ };
+ 
+ template <class T> mystream& operator>>( mystream& s, a<T>& thea );
+ 
+ template<> mystream& operator>> <int>( mystream& s, a<int>& thea );
+ 
+ template class a<int>;
+ 
+ template<> mystream& operator>> <int>( mystream& s, a<int>& thea )
+ {
+ 	thea.amember = 0;
+ 	return s;
+ }
Index: testsuite/g++.old-deja/g++.pt/friend29.C
===================================================================
RCS file: friend29.C
diff -N friend29.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- friend29.C	Fri Jul 31 14:45:04 1998
***************
*** 0 ****
--- 1,16 ----
+ // Build don't link:
+ 
+ template <class T> class a {
+ public:
+ 	friend void foo<>( a<T>& thea );
+ private:
+ 	T amember;
+ };
+ 
+ template <class T> void foo( a<T>& thea )
+ {
+ 	thea.amember = 0;
+ }
+ 
+ template class a<int>;
+ 
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.104
diff -c -p -r1.104 cp-tree.h
*** cp-tree.h	1998/07/28 01:02:48	1.104
--- cp-tree.h	1998/07/31 21:43:16
*************** extern int flag_new_for_scope;
*** 1692,1697 ****
--- 1692,1703 ----
  #define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
    (CLASSTYPE_USE_TEMPLATE(NODE) = 3)
  
+ /* Non-zero iff we are currently processing a declaration for an
+    entity with its own template parameter list, and which is not a
+    full specialization.  */
+ #define PROCESSING_REAL_TEMPLATE_DECL_P() \
+   (processing_template_decl > template_class_depth (current_class_type))
+ 
  /* This function may be a guiding decl for a template.  */
  #define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
  /* We know what we're doing with this decl now.  */
*************** extern int template_class_depth         
*** 2794,2799 ****
--- 2800,2806 ----
  extern int is_specialization_of                 PROTO((tree, tree));
  extern int comp_template_args                   PROTO((tree, tree));
  extern void maybe_process_partial_specialization PROTO((tree));
+ extern void maybe_check_template_type           PROTO((tree));
  
  extern int processing_specialization;
  extern int processing_explicit_instantiation;
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.172
diff -c -p -r1.172 decl.c
*** decl.c	1998/07/29 14:56:33	1.172
--- decl.c	1998/07/31 21:43:58
*************** static int member_function_or_else PROTO
*** 176,181 ****
--- 176,182 ----
  static void bad_specifiers PROTO((tree, char *, int, int, int, int,
  				  int));
  static void lang_print_error_function PROTO((char *));
+ static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
  
  #if defined (DEBUG_CP_BINDING_LEVELS)
  static void indent PROTO((void));
*************** pop_everything ()
*** 2223,2228 ****
--- 2224,2311 ----
  #endif
  }
  
+ /* The type TYPE is being declared.  If it is a class template, or a
+    specialization of a class template, do any processing required and
+    perform error-checking.  If IS_FRIEND is non-zero, this TYPE is
+    being declared a friend.  B is the binding level at which this TYPE
+    should be bound.
+ 
+    Returns the TYPE_DECL for TYPE, which may have been altered by this
+    processing.  */
+ 
+ static tree 
+ maybe_process_template_type_declaration (type, globalize, b)
+      tree type;
+      int globalize;
+      struct binding_level* b;
+ {
+   tree decl = TYPE_NAME (type);
+  
+   if (processing_template_parmlist)
+     /* You can't declare a new template type in a template parameter
+        list.  But, you can declare a non-template type:
+        
+          template <class A*> struct S;
+        
+        is a forward-declaration of `A'.  */
+     ;
+   else 
+     {
+       maybe_check_template_type (type);
+ 
+       if (IS_AGGR_TYPE (type)
+ 	  && (/* If !GLOBALIZE then we are looking at a definition.
+ 		 It may not be a primary template.  (For example, in:
+ 		  
+ 		 template <class T>
+ 		 struct S1 { class S2 {}; }
+ 		  
+ 		 we have to push_template_decl for S2.)  */
+ 	      (processing_template_decl && !globalize)
+ 	      /* If we are declaring a friend template class, we will
+ 		 have GLOBALIZE set, since something like:
+ 
+ 		 template <class T>
+ 		 struct S1 {
+ 		   template <class U>
+ 		   friend class S2; 
+ 		 };
+ 
+ 		 declares S2 to be at global scope.  */
+ 	      || PROCESSING_REAL_TEMPLATE_DECL_P ()))
+ 	{
+ 	  /* This may change after the call to
+ 	     push_template_decl_real, but we want the original value.  */
+ 	  tree name = DECL_NAME (decl);
+ 
+ 	  decl = push_template_decl_real (decl, globalize);
+ 	  /* If the current binding level is the binding level for the
+ 	     template parameters (see the comment in
+ 	     begin_template_parm_list) and the enclosing level is a class
+ 	     scope, and we're not looking at a friend, push the
+ 	     declaration of the member class into the class scope.  In the
+ 	     friend case, push_template_decl will already have put the
+ 	     friend into global scope, if appropriate.  */
+ 	  if (!globalize && b->pseudo_global
+ 	      && b->level_chain->parm_flag == 2)
+ 	    {
+ 	      pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
+ 				   b->level_chain);
+ 	      /* Put this tag on the list of tags for the class, since
+ 		 that won't happen below because B is not the class
+ 		 binding level, but is instead the pseudo-global level.  */
+ 	      b->level_chain->tags = 
+ 		saveable_tree_cons (name, type, b->level_chain->tags);
+ 	      TREE_NONLOCAL_FLAG (type) = 1;
+ 	      if (TYPE_SIZE (current_class_type) == NULL_TREE)
+ 		CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+ 	    }
+ 	}
+     }
+ 
+   return decl;
+ }
+ 
  /* Push a tag name NAME for struct/class/union/enum type TYPE.
     Normally put it into the inner-most non-tag-transparent scope,
     but if GLOBALIZE is true, put it in the inner-most non-class scope.
*************** pushtag (name, type, globalize)
*** 2297,2360 ****
  
  	  TYPE_NAME (type) = d;
  	  DECL_CONTEXT (d) = FROB_CONTEXT (context);
- 
- 	  if (processing_template_parmlist)
- 	    /* You can't declare a new template type in a template
- 	       parameter list.  But, you can declare a non-template
- 	       type:
- 
- 	         template <class A*> struct S;
- 
- 	       is a forward-declaration of `A'.  */
- 	    ;
- 	  else if (IS_AGGR_TYPE (type)
- 	      && (/* If !GLOBALIZE then we are looking at a
- 		     definition.  It may not be a primary template.
- 		     (For example, in:
- 		  
- 		       template <class T>
- 		       struct S1 { class S2 {}; }
- 		  
- 		     we have to push_template_decl for S2.)  */
- 		  (processing_template_decl && !globalize)
- 		  /* If we are declaring a friend template class, we
- 		     will have GLOBALIZE set, since something like:
- 
- 		       template <class T>
- 		       struct S1 {
- 		         template <class U>
- 		         friend class S2; 
- 		       };
  
! 		     declares S2 to be at global scope.  */
! 		  || (processing_template_decl > 
! 		      template_class_depth (current_class_type))))
! 	    {
! 	      d = push_template_decl_real (d, globalize);
! 	      /* If the current binding level is the binding level for
! 		 the template parameters (see the comment in
! 		 begin_template_parm_list) and the enclosing level is
! 		 a class scope, and we're not looking at a friend,
! 		 push the declaration of the member class into the
! 		 class scope.  In the friend case, push_template_decl
! 		 will already have put the friend into global scope,
! 		 if appropriate.  */ 
! 	      if (!globalize && b->pseudo_global
! 		  && b->level_chain->parm_flag == 2)
! 		{
! 		  pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
! 				       b->level_chain);
! 		  /* Put this tag on the list of tags for the class,
! 		     since that won't happen below because B is not
! 		     the class binding level, but is instead the
! 		     pseudo-global level.  */
! 		  b->level_chain->tags = 
! 		    saveable_tree_cons (name, type, b->level_chain->tags);
! 		  TREE_NONLOCAL_FLAG (type) = 1;
! 		  if (TYPE_SIZE (current_class_type) == NULL_TREE)
! 		    CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
! 		}
! 	    }
  
  	  if (b->parm_flag == 2)
  	    d = pushdecl_class_level (d);
--- 2380,2388 ----
  
  	  TYPE_NAME (type) = d;
  	  DECL_CONTEXT (d) = FROB_CONTEXT (context);
  
! 	  d = maybe_process_template_type_declaration (type,
! 						       globalize, b);
  
  	  if (b->parm_flag == 2)
  	    d = pushdecl_class_level (d);
*************** xref_tag (code_type_node, name, binfo, g
*** 11349,11356 ****
      {
        if (current_class_type 
  	  && template_class_depth (current_class_type) 
! 	  && (processing_template_decl 
! 	      > template_class_depth (current_class_type)))
        /* Since GLOBALIZE is non-zero, we are not looking at a
  	 definition of this tag.  Since, in addition, we are currently
  	 processing a (member) template declaration of a template
--- 11387,11393 ----
      {
        if (current_class_type 
  	  && template_class_depth (current_class_type) 
! 	  && PROCESSING_REAL_TEMPLATE_DECL_P ())
        /* Since GLOBALIZE is non-zero, we are not looking at a
  	 definition of this tag.  Since, in addition, we are currently
  	 processing a (member) template declaration of a template
Index: cp/friend.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/friend.c,v
retrieving revision 1.23
diff -c -p -r1.23 friend.c
*** friend.c	1998/07/28 16:50:12	1.23
--- friend.c	1998/07/31 21:44:00
*************** do_friend (ctype, declarator, decl, parm
*** 354,361 ****
      }
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
!     is_friend_template = processing_template_decl >
!       template_class_depth (current_class_type);
  
    if (ctype)
      {
--- 354,360 ----
      }
  
    if (TREE_CODE (decl) == FUNCTION_DECL)
!     is_friend_template = PROCESSING_REAL_TEMPLATE_DECL_P ();
  
    if (ctype)
      {
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.170
diff -c -p -r1.170 pt.c
*** pt.c	1998/07/28 01:02:58	1.170
--- pt.c	1998/07/31 21:44:56
*************** static tree most_specialized PROTO((tree
*** 121,126 ****
--- 121,127 ----
  static tree most_specialized_class PROTO((tree, tree));
  static tree most_general_template PROTO((tree));
  static void set_mangled_name_for_template_decl PROTO((tree));
+ static int template_class_depth_real PROTO((tree, int));
  
  /* We use TREE_VECs to hold template arguments.  If there is only one
     level of template arguments, then the TREE_VEC contains the
*************** finish_member_template_decl (template_pa
*** 234,245 ****
         struct B {};
       };
  
!    A<T>::B<U> has depth two, while A<T> has depth one.  Also,
!    both A<T>::B<int> and A<int>::B<U> have depth one.  */
  
  int 
! template_class_depth (type)
       tree type;
  {
    int depth;
  
--- 235,253 ----
         struct B {};
       };
  
!    A<T>::B<U> has depth two, while A<T> has depth one.  
!    Both A<T>::B<int> and A<int>::B<U> have depth one, if
!    COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not
!    specializations.  
! 
!    This function is guaranteed to return 0 if passed NULL_TREE so
!    that, for example, `template_class_depth (current_class_type)' is
!    always safe.  */
  
  int 
! template_class_depth_real (type, count_specializations)
       tree type;
+      int count_specializations;
  {
    int depth;
  
*************** template_class_depth (type)
*** 249,260 ****
         type = TYPE_CONTEXT (type))
      if (CLASSTYPE_TEMPLATE_INFO (type)
  	&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
! 	&& uses_template_parms (CLASSTYPE_TI_ARGS (type)))
        ++depth;
  
    return depth;
  }
  
  /* Returns 1 if processing DECL as part of do_pending_inlines
     needs us to push template parms.  */
  
--- 257,281 ----
         type = TYPE_CONTEXT (type))
      if (CLASSTYPE_TEMPLATE_INFO (type)
  	&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
! 	&& ((count_specializations
! 	     && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
! 	    || uses_template_parms (CLASSTYPE_TI_ARGS (type))))
        ++depth;
  
    return depth;
  }
  
+ /* Returns the template nesting level of the indicated class TYPE.
+    Like template_class_depth_real, but instantiations do not count in
+    the depth.  */
+ 
+ int 
+ template_class_depth (type)
+      tree type;
+ {
+   return template_class_depth_real (type, /*count_specializations=*/0);
+ }
+ 
  /* Returns 1 if processing DECL as part of do_pending_inlines
     needs us to push template parms.  */
  
*************** register_specialization (spec, tmpl, arg
*** 742,752 ****
  	      }
  	    else if (DECL_TEMPLATE_SPECIALIZATION (fn))
  	      {
! 		if (DECL_INITIAL (fn))
! 		  cp_error ("duplicate specialization of %D", fn);
! 
! 		TREE_VALUE (s) = spec;
! 		return spec;
  	      }
  	  }
        }
--- 763,770 ----
  	      }
  	    else if (DECL_TEMPLATE_SPECIALIZATION (fn))
  	      {
! 		duplicate_decls (spec, TREE_VALUE (s));
! 		return TREE_VALUE (s);
  	      }
  	  }
        }
*************** check_explicit_specialization (declarato
*** 1300,1305 ****
--- 1318,1370 ----
    return decl;
  }
  
+ /* TYPE is being declared.  Verify that the use of template headers
+    and such is reasonable.  Issue error messages if not.  */
+ 
+ void
+ maybe_check_template_type (type)
+      tree type;
+ {
+   if (template_header_count)
+     {
+       /* We are in the scope of some `template <...>' header.  */
+ 
+       int context_depth 
+ 	= template_class_depth_real (TYPE_CONTEXT (type),
+ 				     /*count_specializations=*/1);
+ 
+       if (template_header_count <= context_depth)
+ 	/* This is OK; the template headers are for the context.  We
+ 	   are actually too lenient here; like
+ 	   check_explicit_specialization we should consider the number
+ 	   of template types included in the actual declaration.  For
+ 	   example, 
+ 
+ 	     template <class T> struct S {
+ 	       template <class U> template <class V>
+ 	       struct I {};
+ 	     }; 
+ 
+ 	   is illegal, but:
+ 
+ 	     template <class T> struct S {
+ 	       template <class U> struct I;
+ 	     }; 
+ 
+ 	     template <class T> template <class U.
+ 	     struct S<T>::I {};
+ 
+ 	   is not.  */
+ 	; 
+       else if (template_header_count > context_depth + 1)
+ 	/* There are two many template parameter lists.  */
+ 	cp_error ("too many template parameter lists in declaration of `%T'", type); 
+ 
+       else if (TREE_CODE (type) == ENUMERAL_TYPE)
+ 	cp_error ("template declaration of `%#T'", type);
+     }
+ }
+ 
  /* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
     parameters.  These are represented in the same format used for
     DECL_TEMPLATE_PARMS.  */
*************** push_template_decl_real (decl, is_friend
*** 1951,1959 ****
    /* Push template declarations for global functions and types.  Note
       that we do not try to push a global template friend declared in a
       template class; such a thing may well depend on the template
!      parameters of the class.  With guiding declarations, however, we
!      push the template so that subsequent declarations of the template
!      will match this one.  */
    if (! ctx 
        && !(is_friend && template_class_depth (current_class_type) > 0))
      tmpl = pushdecl_namespace_level (tmpl);
--- 2016,2022 ----
    /* Push template declarations for global functions and types.  Note
       that we do not try to push a global template friend declared in a
       template class; such a thing may well depend on the template
!      parameters of the class.  */
    if (! ctx 
        && !(is_friend && template_class_depth (current_class_type) > 0))
      tmpl = pushdecl_namespace_level (tmpl);
*************** convert_nontype_argument (type, expr)
*** 2278,2287 ****
  	if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
  	  {
  	    /* For a non-type template-parameter of type reference to
! 	      function, no conversions apply.  If the
! 	      template-argument represents a set of overloaded
! 	      functions, the matching function is selected from the
! 	      set (_over.over_).  */
  	    tree fns = expr;
  	    tree fn;
  
--- 2341,2350 ----
  	if (TREE_CODE (type_referred_to) == FUNCTION_TYPE)
  	  {
  	    /* For a non-type template-parameter of type reference to
! 	       function, no conversions apply.  If the
! 	       template-argument represents a set of overloaded
! 	       functions, the matching function is selected from the
! 	       set (_over.over_).  */
  	    tree fns = expr;
  	    tree fn;
  
*************** lookup_template_class (d1, arglist, in_d
*** 3096,3102 ****
  
        if (arg_depth == 1 && parm_depth > 1)
  	{
! 	  /* We've been with an incomplete set of template arguments.
  	     For example, given:
  
  	       template <class T> struct S1 {
--- 3159,3165 ----
  
        if (arg_depth == 1 && parm_depth > 1)
  	{
! 	  /* We've been given an incomplete set of template arguments.
  	     For example, given:
  
  	       template <class T> struct S1 {
*************** lookup_template_class (d1, arglist, in_d
*** 3109,3116 ****
  	     <class U> struct S1<T>::S2'.  We must fill in the missing
  	     arguments.  */
  	  my_friendly_assert (context != NULL_TREE, 0);
! 	  while (!IS_AGGR_TYPE_CODE (TREE_CODE (context)))
  	    context = DECL_REAL_CONTEXT (context);
  	  arglist = add_to_template_args (CLASSTYPE_TI_ARGS (context),
  					  arglist);
  	  arg_depth = TMPL_ARGS_DEPTH (arglist);
--- 3172,3199 ----
  	     <class U> struct S1<T>::S2'.  We must fill in the missing
  	     arguments.  */
  	  my_friendly_assert (context != NULL_TREE, 0);
! 	  while (!IS_AGGR_TYPE_CODE (TREE_CODE (context))
! 		 && context != global_namespace)
  	    context = DECL_REAL_CONTEXT (context);
+ 
+ 	  if (context == global_namespace)
+ 	    /* This is bad.  We cannot get enough arguments, even from
+ 	       the surrounding context, to resolve this class.  One
+ 	       case where this might happen is (illegal) code like:
+ 
+ 	           template <class U> 
+ 		   template <class T>
+ 		   struct S { 
+ 		     A(const A<T>& a) {}
+ 		   };  
+ 	    
+ 	       We should catch this error sooner (at the opening curly
+ 	       for `S', but it is better to be safe than sorry here.  */
+ 	    {
+ 	      cp_error ("invalid use of `%D'", template);
+ 	      return error_mark_node;
+ 	    }
+ 
  	  arglist = add_to_template_args (CLASSTYPE_TI_ARGS (context),
  					  arglist);
  	  arg_depth = TMPL_ARGS_DEPTH (arglist);
*************** tsubst_friend_function (decl, args)
*** 3667,3674 ****
  						 args, NULL_TREE),
  				    tsubst (DECL_TI_ARGS (decl),
  					    args, NULL_TREE));
!       /* FIXME: The decl we create via the next tsubst be created on a
! 	 temporary obstack.  */
        new_friend = tsubst (decl, args, NULL_TREE);
        tmpl = determine_specialization (template_id, new_friend,
  				       &new_args, 
--- 3750,3757 ----
  						 args, NULL_TREE),
  				    tsubst (DECL_TI_ARGS (decl),
  					    args, NULL_TREE));
!       /* FIXME: The decl we create via the next tsubst could be
! 	 created on a temporary obstack.  */
        new_friend = tsubst (decl, args, NULL_TREE);
        tmpl = determine_specialization (template_id, new_friend,
  				       &new_args, 
*************** tsubst (t, args, in_decl)
*** 4833,4844 ****
  		 };
  
  	       Here, the DECL_TI_TEMPLATE for the friend declaration
! 	       will be a LOOKUP_EXPR.  We are being called from
! 	       tsubst_friend_function, and we want only to create a
! 	       new decl (R) with appropriate types so that we can call
! 	       determine_specialization.  */
! 	    my_friendly_assert (TREE_CODE (DECL_TI_TEMPLATE (t)) 
! 				== LOOKUP_EXPR, 0);
  	    gen_tmpl = NULL_TREE;
  	  }
  
--- 4916,4929 ----
  		 };
  
  	       Here, the DECL_TI_TEMPLATE for the friend declaration
! 	       will be a LOOKUP_EXPR or an IDENTIFIER_NODE.  We are
! 	       being called from tsubst_friend_function, and we want
! 	       only to create a new decl (R) with appropriate types so
! 	       that we can call determine_specialization.  */
! 	    my_friendly_assert ((TREE_CODE (DECL_TI_TEMPLATE (t)) 
! 				 == LOOKUP_EXPR)
! 				|| (TREE_CODE (DECL_TI_TEMPLATE (t))
! 				    == IDENTIFIER_NODE), 0);
  	    gen_tmpl = NULL_TREE;
  	  }
  
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.21
diff -c -p -r1.21 semantics.c
*** semantics.c	1998/07/28 01:03:00	1.21
--- semantics.c	1998/07/31 21:45:00
*************** begin_function_definition (decl_specs, d
*** 1098,1103 ****
--- 1094,1103 ----
      return 0;
    
    reinit_parse_for_function ();
+   /* The things we're about to see are not directly qualified by any
+      template headers we've seen thus far.  */
+   reset_specialization ();
+ 
    return 1;
  }


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