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 PR18825 (forget to complete type used in friend declaration)


Hi

This patch fixes PR18825. In the following example:

 template<class T> class B
   {
     friend void A<T>::f ();
   };

after 'T' has been substituted, for example with 'int', we fail to complete the type of 'A<int>' in order to obtain 'A<int>::f()'. There are some more explanation about when
the context must be complete in the comment of 'tsubst_friend_function' in the attached patch.


Furthermore, the line number of error message produced by
'add_friend' is wrong. In 'instantiate_class_template', we
call 'tsubst_friend_function' and later 'add_friend'.
The function 'tsubst_friend_function' set and restore the 'input_location', leaving the subsequent function call to 'add_friend' the wrong 'input_location'. This is also
fixed.


Tested on i686-pc-linux-gnu. OK for mainline?

--Kriang


2004-12-08  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/18825
	* pt.c (instantiate_class_template): Set input_location for
	friend function.
	(tsubst_friend_function): Don't set input_location here.
	Make sure the context is complete if necessary.

2004-12-08  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/18825
	* g++.dg/template/friend32.C: New test.


diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c	Sat Dec  4 13:37:22 2004
--- gcc-main-new/gcc/cp/pt.c	Wed Dec  8 15:22:18 2004
*************** static tree
*** 5098,5106 ****
  tsubst_friend_function (tree decl, tree args)
  {
    tree new_friend;
-   location_t saved_loc = input_location;
- 
-   input_location = DECL_SOURCE_LOCATION (decl);
  
    if (TREE_CODE (decl) == FUNCTION_DECL 
        && DECL_TEMPLATE_INSTANTIATION (decl)
--- 5098,5103 ----
*************** tsubst_friend_function (tree decl, tree 
*** 5135,5142 ****
  				       &new_args, 
  				       /*need_member_template=*/0,
  				       TREE_VEC_LENGTH (args));
!       new_friend = instantiate_template (tmpl, new_args, tf_error);
!       goto done;
      }
  
    new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
--- 5132,5138 ----
  				       &new_args, 
  				       /*need_member_template=*/0,
  				       TREE_VEC_LENGTH (args));
!       return instantiate_template (tmpl, new_args, tf_error);
      }
  
    new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
*************** tsubst_friend_function (tree decl, tree 
*** 5299,5317 ****
  	  new_friend = old_decl;
  	}
      }
!   else if (COMPLETE_TYPE_P (DECL_CONTEXT (new_friend)))
      {
!       /* Check to see that the declaration is really present, and,
! 	 possibly obtain an improved declaration.  */
!       tree fn = check_classfn (DECL_CONTEXT (new_friend), 
! 			       new_friend, NULL_TREE);
!       
!       if (fn)
! 	new_friend = fn;
      }
  
-  done:
-   input_location = saved_loc;
    return new_friend;
  }
  
--- 5295,5334 ----
  	  new_friend = old_decl;
  	}
      }
!   else
      {
!       tree context = DECL_CONTEXT (new_friend);
!       bool dependent_p;
! 
!       /* In the code
! 	   template <class T> class C {
! 	     template <class U> friend void C1<U>::f (); // case 1
! 	     friend void C2<T>::f ();			 // case 2
! 	   };
! 	 we only need to make sure CONTEXT is a complete type for
! 	 case 2.  To distinguish between the two cases, we note that
! 	 CONTEXT of case 1 remains dependent type after tsubst while
! 	 this isn't true for case 2.  */
!       ++processing_template_decl;
!       dependent_p = dependent_type_p (context);
!       --processing_template_decl;
! 
!       if (!dependent_p
! 	  && !complete_type_or_else (context, NULL_TREE))
! 	return error_mark_node;
! 
!       if (COMPLETE_TYPE_P (context))
! 	{
! 	  /* Check to see that the declaration is really present, and,
! 	     possibly obtain an improved declaration.  */
! 	  tree fn = check_classfn (context,
! 				   new_friend, NULL_TREE);
! 
! 	  if (fn)
! 	    new_friend = fn;
! 	}
      }
  
    return new_friend;
  }
  
*************** instantiate_class_template (tree type)
*** 5816,5821 ****
--- 5833,5844 ----
  	      /* Build new DECL_FRIENDLIST.  */
  	      tree r;
  
+ 	      /* The the file and line for this declaration, to
+ 		 assist in error message reporting.  Since we
+ 		 called push_tinst_level above, we don't need to
+ 		 restore these.  */
+ 	      input_location = DECL_SOURCE_LOCATION (t);
+ 
  	      if (TREE_CODE (t) == TEMPLATE_DECL)
  		{
  		  ++processing_template_decl;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/friend32.C gcc-main-new/gcc/testsuite/g++.dg/template/friend32.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/friend32.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/friend32.C	Wed Dec  8 15:07:16 2004
***************
*** 0 ****
--- 1,21 ----
+ // { dg-do compile }
+ 
+ // Origin: Steven Bosscher <steven@gcc.gnu.org>
+ //	   Serge Belyshev <belyshev@lubercy.com>
+ 
+ // PR c++/18825: ICE member as friend
+ 
+ template<class T> class A
+ {
+   void f ();			// { dg-error "private" }
+ };
+ 
+ template<class T> class B
+ {
+   friend void A<T>::f ();	// { dg-error "this context" }
+ };
+ 
+ int f ()
+ {
+   B<int> b;			// { dg-error "instantiated" }
+ }

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