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