OSDN Git Service

PR c++/18681
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Jul 2006 19:44:28 +0000 (19:44 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Jul 2006 19:44:28 +0000 (19:44 +0000)
        * friend.c (is_friend): Fix DR 45 implementation.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115208 138bc75d-0d04-0410-961f-82ee72b054a4

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

index d2c0562..b1a1cbd 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-07-05  Richard Guenther  <rguenther@suse.de>
        Andrew Pinski  <pinskia@gcc.gnu.org>
 
index ac73e5f..0c9712e 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,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)
index 21d1b77..0682ff2 100644 (file)
@@ -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 (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;
+}