This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[C++ PATCH] Fix bug 2137/DR 209


Hi,
this patch fixes bug 2137 by implementing dr 209
http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#209

because we now check type access, this is a regression from 2.95.
The deferred type access stuff would sometimes leave state lying around,
leading to duplicate diagnostics. Also base class access wasn't being
checked, nor were local classes dealt with correctly (we have to
revert to deferred checking).

built & tested on i686-pc-linux-gnu, ok for mainline and branch?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-03-01  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-01  Nathan Sidwell  <nathan@codesourcery.com>

	* g++.old-deja/g++.other/friend9.C: Expect no errors.
	* g++.old-deja/g++.robertl/eb56.C: Make typedef public.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.582
diff -c -3 -p -r1.582 cp-tree.h
*** cp-tree.h	2001/02/27 13:12:16	1.582
--- cp-tree.h	2001/03/01 16:38:20
*************** extern tree get_binfo				PARAMS ((tree, 
*** 4184,4189 ****
--- 4184,4191 ----
  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: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.755
diff -c -3 -p -r1.755 decl.c
*** decl.c	2001/02/26 11:01:44	1.755
--- decl.c	2001/03/01 16:38:25
*************** friend declaration requires class-key, i
*** 11104,11110 ****
  	  /* 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));
  
  	      /* A friendly class?  */
  	      if (current_class_type)
--- 11104,11112 ----
  	  /* Only try to do this stuff if we didn't already give up.  */
  	  if (type != integer_type_node)
  	    {
! 	      /* 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)
*************** friend declaration requires class-key, i
*** 11366,11397 ****
  	if (friendp)
  	  {
  	    /* Friends are treated specially.  */
  	    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;
! 	      }
  	  }
  
  	/* Structure field.  It may not be a function, except for C++ */
--- 11368,11400 ----
  	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");
  
!             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: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.214
diff -c -3 -p -r1.214 parse.y
*** parse.y	2001/02/14 13:58:49	1.214
--- parse.y	2001/03/01 16:38:27
*************** component_decl_list:
*** 2547,2557 ****
--- 2547,2559 ----
  		{ 
  		  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: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.191
diff -c -3 -p -r1.191 semantics.c
*** semantics.c	2001/02/18 05:59:45	1.191
--- semantics.c	2001/03/01 16:38:27
*************** decl_type_access_control (decl)
*** 1596,1608 ****
       added to type_lookups after typed_declspecs saved the copy that
       ended up in current_type_lookups.  */
    type_lookups = current_type_lookups;
  }
  
  void
  save_type_access_control (lookups)
       tree lookups;
  {
!   current_type_lookups = lookups;
  }
  
  /* Begin a function definition declared with DECL_SPECS and
--- 1596,1636 ----
       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;
+ {
+   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
*************** tree
*** 1735,1740 ****
--- 1763,1772 ----
  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);
*************** finish_class_definition (t, attributes, 
*** 1962,1967 ****
--- 1994,2001 ----
      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: testsuite/g++.old-deja/g++.other/friend9.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.other/friend9.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 friend9.C
*** friend9.C	2000/11/28 10:06:16	1.1
--- friend9.C	2001/03/01 16:38:18
***************
*** 5,18 ****
  
  // Bug 853: We reported the wrong line no for a friend access violation
  
  class F
  {
!   class Internal;   // ERROR - is private
  };
  
  class C
  {
!   friend class F::Internal; // ERROR - in this context
    public:
    typedef enum { A, B } e;
  
--- 5,20 ----
  
  // 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;
  };
  
  class C
  {
!   friend class F::Internal;
    public:
    typedef enum { A, B } e;
  
Index: testsuite/g++.old-deja/g++.robertl/eb56.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.robertl/eb56.C,v
retrieving revision 1.3
diff -c -3 -p -r1.3 eb56.C
*** eb56.C	1998/12/16 22:04:13	1.3
--- eb56.C	2001/03/01 16:38:18
***************
*** 2,7 ****
--- 2,8 ----
  // Build don't link:
  
  class foo {
+   public:
          typedef int sometype;
  };
  
// 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]