[C++ PATCH]: Fix 2137

Nathan Sidwell nathan@codesourcery.com
Mon Mar 26 00:41:00 GMT 2001


Hi,
I've installed this patch to the mainline which fixes bug 2137.
We were neglecting to check the access for a friend function declaration
with the result that we'd have accesses to check lying about til some
later time. However, the proposed resolution of DR209
http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#209
is that the friend class/function does not need to be accessible at the
friend declaration. So this patch removes such access checks.


built & tested on i686-pc-linux-gnu, approved by Mark.

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-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-26  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;
  };
  


More information about the Gcc-patches mailing list