C++ PATCH: PR6492

Mark Mitchell mark@codesourcery.com
Mon Apr 29 07:59:00 GMT 2002


My recent change to tsubst_friend_class wasn't correct enough.

Here's another try, which fixes PR6492.

Bootstrapped, tested on i686-pc-linux-gnu; applied on the mainline
and on the branch.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2002-04-29  Mark Mitchell  <mark@codesourcery.com>

	PR c++/6492
	* pt.c (tsubst_friend_class): If the friend has an explicit scope,
	enter that scope before name lookup.

2002-04-29  Mark Mitchell  <mark@codesourcery.com>

	PR c++/6492
	* g++.dg/init/copy1.C: New test.

Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.578.2.3
diff -c -p -r1.578.2.3 pt.c
*** gcc/cp/pt.c	23 Apr 2002 08:34:44 -0000	1.578.2.3
--- gcc/cp/pt.c	29 Apr 2002 14:45:30 -0000
*************** tsubst_friend_class (friend_tmpl, args)
*** 4796,4825 ****
  {
    tree friend_type;
    tree tmpl;
  
!   /* First, we look for a class template.  */
!   if (DECL_CONTEXT (friend_tmpl))
!     tmpl = friend_tmpl;
!   else
      {
!       tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0); 
  
!       /* But, if we don't find one, it might be because we're in a
! 	 situation like this:
  
! 	   template <class T>
! 	   struct S {
! 	     template <class U>
! 	     friend struct S;
! 	   };
! 
! 	 Here, in the scope of (say) S<int>, `S' is bound to a TYPE_DECL
! 	 for `S<int>', not the TEMPLATE_DECL.  */
!       if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
! 	{
! 	  tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/1);
! 	  tmpl = maybe_get_template_decl_from_type_decl (tmpl);
! 	}
      }
  
    if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
--- 4796,4831 ----
  {
    tree friend_type;
    tree tmpl;
+   tree context;
  
!   context = DECL_CONTEXT (friend_tmpl);
! 
!   if (context)
      {
!       if (TREE_CODE (context) == NAMESPACE_DECL)
! 	push_nested_namespace (context);
!       else
! 	push_nested_class (context, 2);
!     }
  
!   /* First, we look for a class template.  */
!   tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0); 
  
!   /* But, if we don't find one, it might be because we're in a
!      situation like this:
! 
!        template <class T>
!        struct S {
! 	 template <class U>
! 	 friend struct S;
!        };
! 
!      Here, in the scope of (say) S<int>, `S' is bound to a TYPE_DECL
!      for `S<int>', not the TEMPLATE_DECL.  */
!   if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
!     {
!       tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/1);
!       tmpl = maybe_get_template_decl_from_type_decl (tmpl);
      }
  
    if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
*************** tsubst_friend_class (friend_tmpl, args)
*** 4830,4841 ****
  	 of course.  We only need the innermost template parameters
  	 because that is all that redeclare_class_template will look
  	 at.  */
!       tree parms 
! 	= tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
! 				 args, tf_error | tf_warning);
!       if (!parms)
!         return error_mark_node;
!       redeclare_class_template (TREE_TYPE (tmpl), parms);
        friend_type = TREE_TYPE (tmpl);
      }
    else
--- 4836,4850 ----
  	 of course.  We only need the innermost template parameters
  	 because that is all that redeclare_class_template will look
  	 at.  */
!       if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl))
! 	  > TMPL_ARGS_DEPTH (args))
! 	{
! 	  tree parms;
! 	  parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl),
! 					 args, tf_error | tf_warning);
! 	  redeclare_class_template (TREE_TYPE (tmpl), parms);
! 	}
! 
        friend_type = TREE_TYPE (tmpl);
      }
    else
*************** tsubst_friend_class (friend_tmpl, args)
*** 4855,4860 ****
--- 4864,4877 ----
  
        /* Inject this template into the global scope.  */
        friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
+     }
+ 
+   if (context) 
+     {
+       if (TREE_CODE (context) == NAMESPACE_DECL)
+ 	pop_nested_namespace (context);
+       else
+ 	pop_nested_class ();
      }
  
    return friend_type;

Index: gcc/testsuite/g++.dg/template/friend6.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/friend6.C
diff -N gcc/testsuite/g++.dg/template/friend6.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/friend6.C	29 Apr 2002 14:45:31 -0000
***************
*** 0 ****
--- 1,53 ----
+ // { dg-do compile }
+ 
+ namespace boost_no_member_template_friends{
+ 
+ template <class T>
+ class foobar;
+ 
+ template <class T>
+ class foo
+ {
+ private:
+    template<typename Y> friend class foobar;
+    template<typename Y> friend class foo;
+    template<typename Y> friend bool must_be_friend_proc(const foo<Y>& f);
+    int i;
+ public:
+    foo(){ i = 0; }
+    template <class U>
+    foo(const foo<U>& f){ i = f.i; }
+ };
+ 
+ template <class T>
+ class foo;
+ 
+ template <class T>
+ bool must_be_friend_proc(const foo<T>& f);
+ 
+ template <class T>
+ bool must_be_friend_proc(const foo<T>& f)
+ { return f.i != 0; }
+ 
+ template <class T>
+ class foobar
+ {
+    int i;
+ public:
+    template <class U>
+    foobar(const foo<U>& f)
+    { i = f.i; }
+ };
+ 
+ 
+ int test()
+ {
+    foo<int> fi;



More information about the Gcc-patches mailing list