From: Jason Merrill Date: Wed, 5 Jul 2006 20:40:06 +0000 (-0400) Subject: re PR c++/18681 ([DR 45] template friend declaration not recognized) X-Git-Tag: releases/gcc-4.0.4~557 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac0b36aeb9ff387420d7a3da891dca6b61cb2c00;p=thirdparty%2Fgcc.git re PR c++/18681 ([DR 45] template friend declaration not recognized) PR c++/18681 * friend.c (is_friend): Fix DR 45 implementation. From-SVN: r115209 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1afdbce92355..417266192695 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2006-07-05 Jason Merrill + + PR c++/18681 + * friend.c (is_friend): Fix DR 45 implementation. + 2006-06-30 Jason Merrill PR c++/26577 diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 8203dbb3b6f6..13fac00c0798 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -78,13 +78,8 @@ is_friend (tree type, tree supplicant) else /* It's a type. */ { - /* Nested classes are implicitly friends of their enclosing types, as - per core issue 45 (this is a change from the standard). */ - for (context = supplicant; - context && TYPE_P (context); - context = TYPE_CONTEXT (context)) - if (type == context) - return 1; + if (same_type_p (supplicant, type)) + return 1; list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type))); for (; list ; list = TREE_CHAIN (list)) @@ -98,13 +93,24 @@ is_friend (tree type, tree supplicant) } } - if (declp && DECL_FUNCTION_MEMBER_P (supplicant)) - context = DECL_CONTEXT (supplicant); - else if (! declp) - /* Local classes have the same access as the enclosing function. */ - context = decl_function_context (TYPE_MAIN_DECL (supplicant)); + if (declp) + { + if (DECL_FUNCTION_MEMBER_P (supplicant)) + context = DECL_CONTEXT (supplicant); + else + context = NULL_TREE; + } else - context = NULL_TREE; + { + if (TYPE_CONTEXT (supplicant) + && TYPE_P (TYPE_CONTEXT (supplicant))) + /* Nested classes get the same access as their enclosing types, as + per DR 45 (this is a change from the standard). */ + context = TYPE_CONTEXT (supplicant); + else + /* Local classes have the same access as the enclosing function. */ + context = decl_function_context (TYPE_MAIN_DECL (supplicant)); + } /* A namespace is not friend to anybody. */ if (context && TREE_CODE (context) == NAMESPACE_DECL) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 8a91d9a5ae73..d706ee11e1b7 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -793,8 +793,8 @@ friend_accessible_p (tree scope, tree decl, tree binfo) if (protected_accessible_p (decl, TREE_VALUE (t), binfo)) return 1; - /* Nested classes are implicitly friends of their enclosing types, as - per core issue 45 (this is a change from the standard). */ + /* Nested classes have the same access as their enclosing types, as + per DR 45 (this is a change from the standard). */ if (TYPE_P (scope)) for (t = TYPE_CONTEXT (scope); t && TYPE_P (t); t = TYPE_CONTEXT (t)) if (protected_accessible_p (decl, t, binfo)) diff --git a/gcc/testsuite/g++.dg/lookup/friend10.C b/gcc/testsuite/g++.dg/lookup/friend10.C new file mode 100644 index 000000000000..fa2eccbea741 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/friend10.C @@ -0,0 +1,22 @@ +// PR c++/18681 +// Bug: The friend declaration in A failed to give C::D access to A::B +// as specified in DR 45. + +class A +{ + struct B; + friend class C; +}; + +class C +{ + struct D + { + void f(); + }; +}; + +void C::D::f() +{ + A::B* p; +}