]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/18681 ([DR 45] template friend declaration not recognized)
authorJason Merrill <jason@redhat.com>
Wed, 5 Jul 2006 20:40:06 +0000 (16:40 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 5 Jul 2006 20:40:06 +0000 (16:40 -0400)
        PR c++/18681
        * friend.c (is_friend): Fix DR 45 implementation.

From-SVN: r115209

gcc/cp/ChangeLog
gcc/cp/friend.c
gcc/cp/search.c
gcc/testsuite/g++.dg/lookup/friend10.C [new file with mode: 0644]

index 1afdbce92355745e33673854d9521359f29aac87..4172661926950b370985b729bcc7488d19bc99c9 100644 (file)
@@ -1,3 +1,8 @@
+2006-07-05  Jason Merrill  <jason@redhat.com>
+
+       PR c++/18681
+       * friend.c (is_friend): Fix DR 45 implementation.
+
 2006-06-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/26577
index 8203dbb3b6f66eab27aae95098e00f37730ea1c6..13fac00c079854d5c84f7a8841550ad162f3bd93 100644 (file)
@@ -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)
index 8a91d9a5ae73baca1515d77c71e63d6c3d1d290e..d706ee11e1b715144425c1b22c61a60a1cb43ed8 100644 (file)
@@ -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 (file)
index 0000000..fa2eccb
--- /dev/null
@@ -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;
+}