aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2006-07-05 15:44:28 -0400
committerJason Merrill <jason@gcc.gnu.org>2006-07-05 15:44:28 -0400
commit03b1c2062ba9877841bc9b8553cf069bed7e33bf (patch)
tree05e265b45537a3c04e8ec138ba9dd7850fe1ccb7
parentad6d4e435e96bddcf72757a4e5df802e6c447922 (diff)
downloadgcc-03b1c2062ba9877841bc9b8553cf069bed7e33bf.zip
gcc-03b1c2062ba9877841bc9b8553cf069bed7e33bf.tar.gz
gcc-03b1c2062ba9877841bc9b8553cf069bed7e33bf.tar.bz2
re PR c++/18681 ([DR 45] template friend declaration not recognized)
PR c++/18681 * friend.c (is_friend): Fix DR 45 implementation. From-SVN: r115208
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/friend.c31
-rw-r--r--gcc/cp/search.c4
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend10.C22
4 files changed, 47 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d2c0562..b1a1cbd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2006-07-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/18681
+ * friend.c (is_friend): Fix DR 45 implementation.
+
2006-07-05 Richard Guenther <rguenther@suse.de>
Andrew Pinski <pinskia@gcc.gnu.org>
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index ac73e5f..0c9712e 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,23 @@ 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_CLASS_SCOPE_P (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 21d1b77..0682ff2 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -792,8 +792,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 0000000..fa2eccb
--- /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;
+}