Implement DR 209
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 26 Mar 2001 08:37:27 +0000 (08:37 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 26 Mar 2001 08:37:27 +0000 (08:37 +0000)
cp:
Implement DR 209
* cp-tree.h (skip_type_access_control,
reset_type_access_control): Prototype.
* decl.c (grokdeclarator): Access of friends is not checked.
* parse.y (component_decl_list): Reset type access control.
* semantics.c (decl_type_access_control): Clear
current_type_lookups.
(save_type_access_control): Don't save if not deferring.
(skip_type_access_control, reset_type_access_control): New
functions.
(begin_class_definition): Do type access control for basetypes.
Start deferred access control.
(finish_class_definition): Resume immediate access control if
this is a local class.
testsuite:
* g++.old-deja/g++.other/friend12.C: New test.
* g++.old-deja/g++.other/friend9.C: Expect no errors.
* g++.old-deja/g++.robertl/eb56.C: Make typedef public.

From-SVN: r40841

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parse.y
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/friend12.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/friend9.C
gcc/testsuite/g++.old-deja/g++.robertl/eb56.C

index 63ce6c9ba60476aebe123420a7384bea083d9539..3b89a973e06739fa5686555a423896cab97107ee 100644 (file)
@@ -1,3 +1,20 @@
+2001-03-26  Nathan Sidwell  <nathan@codesourcery.com>
+
+       Implement DR 209
+       * cp-tree.h (skip_type_access_control,
+       reset_type_access_control): Prototype.
+       * decl.c (grokdeclarator): Access of friends is not checked.
+       * parse.y (component_decl_list): Reset type access control.
+       * semantics.c (decl_type_access_control): Clear
+       current_type_lookups.
+       (save_type_access_control): Don't save if not deferring.
+       (skip_type_access_control, reset_type_access_control): New
+       functions.
+       (begin_class_definition): Do type access control for basetypes.
+       Start deferred access control.
+       (finish_class_definition): Resume immediate access control if
+       this is a local class.
+
 2001-03-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * class.c (add_method): Use memcpy/memmove, not bcopy.
index 28f519dd29be1ca1c01fd5f9bc29e6863cc4a9b1..5015349156af6f960a39413c79b1f9634ddc014f 100644 (file)
@@ -4175,6 +4175,8 @@ extern tree get_binfo                             PARAMS ((tree, tree, int));
 extern int get_base_distance                   PARAMS ((tree, tree, int, tree *));
 extern tree get_dynamic_cast_base_type          PARAMS ((tree, tree));
 extern void type_access_control                        PARAMS ((tree, tree));
+extern void skip_type_access_control            PARAMS ((void));
+extern void reset_type_access_control           PARAMS ((void));
 extern int accessible_p                         PARAMS ((tree, tree));
 extern tree lookup_field                       PARAMS ((tree, tree, int, int));
 extern int lookup_fnfields_1                    PARAMS ((tree, tree));
index 04d4c4ffc59b6382de332451d48e39b65ff951ea..03f94a35fa112596efc24286ac8bc92a1d731e2f 100644 (file)
@@ -11131,7 +11131,9 @@ friend declaration requires class-key, i.e. `friend %#T'",
          /* Only try to do this stuff if we didn't already give up.  */
          if (type != integer_type_node)
            {
-             decl_type_access_control (TYPE_NAME (type));
+             /* DR 209. The friendly class does not need to be accessible
+                 in the scope of the class granting friendship. */
+             skip_type_access_control ();
 
              /* A friendly class?  */
              if (current_class_type)
@@ -11393,32 +11395,33 @@ friend declaration requires class-key, i.e. `friend %#T'",
        if (friendp)
          {
            /* Friends are treated specially.  */
+            tree t = NULL_TREE;
+           
+           /* DR 209. The friend does not need to be accessible at this
+               point. */
+           skip_type_access_control ();
+           
            if (ctype == current_class_type)
              warning ("member functions are implicitly friends of their class");
-           else
-             {
-               tree t = NULL_TREE;
-               if (decl && DECL_NAME (decl))
-                 {
-                   if (template_class_depth (current_class_type) == 0)
-                     {
-                       decl
-                         = check_explicit_specialization
-                         (declarator, decl,
-                          template_count, 2 * (funcdef_flag != 0) + 4);
-                       if (decl == error_mark_node)
-                         return error_mark_node;
-                     }
 
-                   t = do_friend (ctype, declarator, decl,
-                                  last_function_parms, attrlist, flags, quals,
-                                  funcdef_flag);
-                 }
-               if (t && funcdef_flag)
-                 return t;
-
-               return void_type_node;
-             }
+            if (decl && DECL_NAME (decl))
+              {
+                if (template_class_depth (current_class_type) == 0)
+                  {
+                   decl = check_explicit_specialization
+                           (declarator, decl,
+                            template_count, 2 * (funcdef_flag != 0) + 4);
+                   if (decl == error_mark_node)
+                     return error_mark_node;
+                  }
+              
+                t = do_friend (ctype, declarator, decl,
+                              last_function_parms, attrlist, flags, quals,
+                              funcdef_flag);
+              }
+            if (t && funcdef_flag)
+              return t;
+           return void_type_node;
          }
 
        /* Structure field.  It may not be a function, except for C++ */
index 3d4ab4400f671d6dd909156ecb15ff47d32d94fe..f13614b750a8c39977c3eaedfcae6eb7acd7bdd0 100644 (file)
@@ -2548,11 +2548,13 @@ component_decl_list:
                { 
                  finish_member_declaration ($1);
                  current_aggr = NULL_TREE;
+                 reset_type_access_control ();
                }
        | component_decl_list component_decl
                { 
                  finish_member_declaration ($2);
                  current_aggr = NULL_TREE;
+                 reset_type_access_control ();
                }
        ;
 
index 6e037f4d727b96500ba1644553866059d4a132e8..c99a0db4e7064d61340f27021cb544dd1c0d463c 100644 (file)
@@ -1593,13 +1593,41 @@ decl_type_access_control (decl)
      added to type_lookups after typed_declspecs saved the copy that
      ended up in current_type_lookups.  */
   type_lookups = current_type_lookups;
+  
+  current_type_lookups = NULL_TREE;
 }
 
+/* Record the lookups, if we're doing deferred access control.  */
+
 void
 save_type_access_control (lookups)
      tree lookups;
 {
-  current_type_lookups = lookups;
+  if (type_lookups != error_mark_node)
+    {
+      my_friendly_assert (!current_type_lookups, 20010301);
+      current_type_lookups = lookups;
+    }
+  else
+    my_friendly_assert (!lookups || lookups == error_mark_node, 20010301);
+}
+
+/* Set things up so that the next deferred access control will succeed.
+   This is needed for friend declarations see grokdeclarator for details.  */
+
+void
+skip_type_access_control ()
+{
+  type_lookups = NULL_TREE;
+}
+
+/* Reset the deferred access control.  */
+
+void
+reset_type_access_control ()
+{
+  type_lookups = NULL_TREE;
+  current_type_lookups = NULL_TREE;
 }
 
 /* Begin a function definition declared with DECL_SPECS and
@@ -1732,6 +1760,10 @@ tree
 begin_class_definition (t)
      tree t;
 {
+  /* Check the bases are accessible. */
+  decl_type_access_control (TYPE_NAME (t));
+  reset_type_access_control ();
+  
   if (processing_template_parmlist)
     {
       cp_error ("definition of `%#T' inside template parameter list", t);
@@ -1953,6 +1985,8 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
     check_for_missing_semicolon (t); 
   if (pop_scope_p)
     pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
+  if (current_function_decl)
+    type_lookups = error_mark_node;
   if (current_scope () == current_function_decl)
     do_pending_defargs ();
 
index d8d9633990e7f09f475b21c69d83114d012309dd..86736d39462533247f1fcde163494a4d280242d3 100644 (file)
@@ -1,3 +1,9 @@
+2001-03-26  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/friend12.C: New test.
+       * g++.old-deja/g++.other/friend9.C: Expect no errors.
+       * g++.old-deja/g++.robertl/eb56.C: Make typedef public.
+
 2001-03-25  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * gcc.c-torture/execute/20010325-1.c: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.other/friend12.C b/gcc/testsuite/g++.old-deja/g++.other/friend12.C
new file mode 100644 (file)
index 0000000..df767b3
--- /dev/null
@@ -0,0 +1,71 @@
+// Build don't link:
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 1 Mar 2001 <nathan@codesourcery.com>
+
+// DR 209. friend access is not checked.
+
+class Z;
+class A
+{
+  class Inner {}; // ERROR - private
+  Inner f (Inner);
+  public:
+  A ();
+  friend class Z;
+};
+
+class B
+{
+  A::Inner j ();    // ERROR - private
+  A::Inner k ();    // ERROR - private
+  friend A::Inner A::f (Inner);
+  int t;
+  friend class A::Inner;
+};
+
+A::Inner l ();    // ERROR - private
+A::Inner m ();    // ERROR - private
+A::Inner a,       // ERROR - private
+         b;       // ERROR - private
+A::Inner a1;      // ERROR - private
+int b2;
+
+A::Inner A::f (Inner)
+{
+  B b;
+  b.t = 1;
+  return A::Inner ();
+}
+
+void Foo ()
+{
+  A::Inner i;  // ERROR - private
+  class Local
+  {
+    friend A::Inner A::f (Inner);
+    A::Inner k; // ERROR - private
+  };
+  class Local1 : A::Inner
+  { // ERROR - private
+    
+  };
+  A::Inner k;  // ERROR - private
+}
+
+class X : A::Inner
+{  // ERROR - private
+  class I : A::Inner
+  {  // ERROR - private
+    
+  };
+};
+
+class Z : A::Inner
+{  // ERROR - private
+  class I : A::Inner
+  { // ok, the base A::Inner is in the scope of Z which is a friend of A
+    
+  };
+};
+int b4;
index 442d9899e3a7d0d7de58636389a527b72ca80d2a..e51b0274c6654dd33c61ba7e8417d1c7da16675a 100644 (file)
@@ -5,14 +5,16 @@
 
 // Bug 853: We reported the wrong line no for a friend access violation
 
+// Since DR 209, friend declaration access is not checked.
+
 class F
 {
-  class Internal;   // ERROR - is private
+  class Internal;
 };
 
 class C
 {
-  friend class F::Internal; // ERROR - in this context
+  friend class F::Internal;
   public:
   typedef enum { A, B } e;
 
index 2d497f8b4e366ba36a98f1934ae324c45b141b9f..2249a40b24ccf218c8df529875ff3b2a93b5973e 100644 (file)
@@ -2,6 +2,7 @@
 // Build don't link:
 
 class foo {
+  public:
         typedef int sometype;
 };