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 for protected member access checks



This patch fixes a long-standing bug in g++ whereby we would sometimes
incorrectly forbid access to a protected member.  Recent corrections
to our access-control code made this flaw more obvious.

-- 
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-03-24  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (lang_type): Remove has_assignment and
	has_real_assignment.  Add befriending_classes.
	(TYPE_HAS_ASSIGNMENT): Remove.
	(TYPE_HAS_REAL_ASSIGNMENT): Likewise.
	(CLASSTYPE_BEFRIENDING_CLASSES): New macro.
	(lang_decl): Document.
	(DECL_BEFRIENDING_CLASSES): New macro.
	(FRIEND_NAME): Move declaration to more obvious location.
	(FRIEND_DECLS): Likewise.
	* class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT.
	* decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES.
	(fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT.
	(grok_op_properties): Likewise.
	* friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS.
	(add_friend): Likewise.  Don't do weird things with assignment
	operators.  Update DECL_BEFRIENDING_CLASSES.
	(add_friends): Don't do weird things with assignment operators.
	(make_friend_class): Likewise.  Update
	CLASSTYPE_BEFRIENDING_CLASSES.
	* pt.c (instantiate_class_template): Don't set
	TYPE_HAS_ASSIGNMENT. 
	(tsubst_copy): Substitute the TREE_TYPE for more unary
	expressions.
	* ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT.
	* search.c (protected_accessible_p): New function.
	(friend_accessible_p): Likewise.
	(accessible_p): Use them.
	
Index: testsuite/g++.old-deja/g++.other/friend1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.other/friend1.C,v
retrieving revision 1.4
diff -c -p -r1.4 friend1.C
*** friend1.C	1999/03/09 23:02:05	1.4
--- friend1.C	1999/03/24 08:57:35
***************
*** 9,29 ****
  // From: Alexandre Oliva <oliva@dcc.unicamp.br>
  // Date: 06 Mar 1998 01:43:18 -0300
  
  
  class B {
  protected:
    int i; // ERROR - in this context
!   static int j; // gets bogus error - XFAIL *-*-*
  };
  
  class D : public B {
!     friend void f();
  };
  
  void f()
  {
      ((B*)0)->i = 3; // ERROR - protected
      ((D*)0)->i = 4;
!     B::j = 5;			// gets bogus error - XFAIL *-*-*
      D::j = 6;
  }
--- 9,85 ----
  // From: Alexandre Oliva <oliva@dcc.unicamp.br>
  // Date: 06 Mar 1998 01:43:18 -0300
  
+ template <int*>
+ class X {};
  
+ template <typename T>
+ void g();
+ 
+ struct S;
+ 
+ template <typename T>
+ struct R;
+ 
  class B {
  protected:
    int i; // ERROR - in this context
!   static int j;
  };
  
  class D : public B {
!   friend void f();
!   template <typename T>
!   friend void g();
!   friend struct S;
!   template <typename T>
!   friend struct R;
  };
  
+ struct S {
+   void h();
+   X<&B::j> x;
+ };
+ 
+ template <typename T>
+ struct R {
+   void h();
+   X<&B::j> x;
+ };
+ 
  void f()
  {
      ((B*)0)->i = 3; // ERROR - protected
      ((D*)0)->i = 4;
!     B::j = 5;
      D::j = 6;
  }
+ 
+ template <typename T>
+ void g()
+ {
+     ((B*)0)->i = 3; // ERROR - protected
+     ((D*)0)->i = 4;
+     B::j = 5;
+     D::j = 6;
+ }
+ 
+ template void g<int>();
+ 
+ void S::h()
+ {
+   ((B*)0)->i = 3; // ERROR - protected
+   ((D*)0)->i = 4;
+   B::j = 5;
+   D::j = 6;
+ }
+ 
+ template <typename T>
+ void R<T>::h() 
+ {
+   ((B*)0)->i = 3; // ERROR - protected
+   ((D*)0)->i = 4;
+   B::j = 5;
+   D::j = 6;
+ }
+ 
+ template struct R<double>;
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.135
diff -c -p -r1.135 class.c
*** class.c	1999/03/09 23:02:30	1.135
--- class.c	1999/03/24 08:57:39
*************** finish_struct_1 (t, warn_anon)
*** 3808,3814 ****
    if (! IS_SIGNATURE (t))
      CLASSTYPE_NON_AGGREGATE (t)
        = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
-   TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t);
    TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
    TYPE_HAS_COMPLEX_ASSIGN_REF (t)
      |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
--- 3808,3813 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.207
diff -c -p -r1.207 cp-tree.h
*** cp-tree.h	1999/03/23 00:01:39	1.207
--- cp-tree.h	1999/03/24 08:57:41
*************** struct lang_type
*** 683,694 ****
      {
        unsigned has_type_conversion : 1;
        unsigned has_init_ref : 1;
-       unsigned has_assignment : 1;
        unsigned has_default_ctor : 1;
        unsigned uses_multiple_inheritance : 1;
        unsigned const_needs_init : 1;
        unsigned ref_needs_init : 1;
        unsigned has_const_assign_ref : 1;
  
        unsigned has_nonpublic_ctor : 2;
        unsigned has_nonpublic_assign_ref : 2;
--- 683,694 ----
      {
        unsigned has_type_conversion : 1;
        unsigned has_init_ref : 1;
        unsigned has_default_ctor : 1;
        unsigned uses_multiple_inheritance : 1;
        unsigned const_needs_init : 1;
        unsigned ref_needs_init : 1;
        unsigned has_const_assign_ref : 1;
+       unsigned anon_union : 1;
  
        unsigned has_nonpublic_ctor : 2;
        unsigned has_nonpublic_assign_ref : 2;
*************** struct lang_type
*** 721,742 ****
        unsigned has_opaque_typedecls : 1;
        unsigned sigtable_has_been_generated : 1;
        unsigned was_anonymous : 1;
-       unsigned has_real_assignment : 1;
        unsigned has_real_assign_ref : 1;
        unsigned has_const_init_ref : 1;
- 
        unsigned has_complex_init_ref : 1;
        unsigned has_complex_assign_ref : 1;
        unsigned has_abstract_assign_ref : 1;
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
        unsigned has_mutable : 1;
-       unsigned anon_union : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 9;
      } type_flags;
  
    int n_ancestors;
--- 721,740 ----
        unsigned has_opaque_typedecls : 1;
        unsigned sigtable_has_been_generated : 1;
        unsigned was_anonymous : 1;
        unsigned has_real_assign_ref : 1;
        unsigned has_const_init_ref : 1;
        unsigned has_complex_init_ref : 1;
+ 
        unsigned has_complex_assign_ref : 1;
        unsigned has_abstract_assign_ref : 1;
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
        unsigned has_mutable : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 11;
      } type_flags;
  
    int n_ancestors;
*************** struct lang_type
*** 772,779 ****
    union tree_node *signature;
    union tree_node *signature_pointe
r_to;
    union tree_node *signature_reference_to;
- 
    union tree_node *template_info;
  };
  
  /* Indicates whether or not (and how) a template was expanded for this class.
--- 770,777 ----
    union tree_node *signature;
    union tree_node *signature_pointer_to;
    union tree_node *signature_reference_to;
    union tree_node *template_info;
+   tree befriending_classes;
  };
  
  /* Indicates whether or not (and how) a template was expanded for this class.
*************** struct lang_type
*** 789,801 ****
  /* List of friends which were defined inline in this class definition.  */
  #define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE))
  
- /* Nonzero for _CLASSTYPE means that the _CLASSTYPE either has
-    a special meaning for the assignment operator ("operator="),
-    or one of its fields (or base members) has a special meaning
-    defined.  */
- #define TYPE_HAS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assignment)
- #define TYPE_HAS_REAL_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assignment)
- 
  /* Nonzero for _CLASSTYPE means that operator new and delete are defined,
     respectively.  */
  #define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
--- 787,792 ----
*************** struct lang_type
*** 1057,1067 ****
  /* Same, but cache a list whose value is the binfo of this type.  */
  #define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list)
  
! /* A list of class types with which this type is a friend.  The
     TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
     case of a template friend.  */
  #define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
  
  /* Say whether this node was declared as a "class" or a "struct".  */
  #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
  
--- 1048,1062 ----
  /* Same, but cache a list whose value is the binfo of this type.  */
  #define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list)
  
! /* A list of class types of which this type is a friend.  The
     TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
     case of a template friend.  */
  #define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
  
+ /* A list of the classes which grant friendship to this class.  */
+ #define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \
+   (TYPE_LANG_SPECIFIC (NODE)->befriending_classes)
+ 
  /* Say whether this node was declared as a "class" or a "struct".  */
  #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
  
*************** struct lang_type
*** 1169,1174 ****
--- 1164,1178 ----
  /* The binding level associated with the namespace.  */
  #define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level)
  
+ 
+ /* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or
+    a lang_decl (which has lang_decl_flags as its initial prefix).  A
+    FUNCTION_DECL, NAMESPACE_DECL, TYPE_DECL, or USING_DECL may have a
+    full lang_decl.  A FIELD_DECL, or a static data member VAR_DECL,
+    will have only lang_decl_flags.  Thus, one should only access the
+    members of lang_decl that are not in lang_decl_flags for DECLs that
+    are not FIELD_DECLs or VAR_DECLs.  */
+ 
  struct lang_decl_flags
  {
  #ifdef ONLY_INT_FIELDS
*************** struct lang_decl
*** 1215,1220 ****
--- 1219,1225 ----
    struct lang_decl_flags decl_flags;
  
    tree main_decl_variant;
+   tree befriending_classes;
    struct pending_inline *pending_inline_info;
  };
  
*************** struct lang_decl
*** 1281,1286 ****
--- 1286,1295 ----
     member functions for this class.  */
  #define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr)
  
+ /* A TREE_LIST of the types which have befriended this FUNCTION_DECL.  */
+ #define DECL_BEFRIENDING_CLASSES(NODE) \
+   (DECL_LANG_SPECIFIC(NODE)->befriending_classes)
+ 
  /* Nonzero for FUNCTION_DECL means that this decl is a static
     member function.  */
  #define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function)
*************** extern int flag_new_for_scope;
*** 1822,1827 ****
--- 1831,1838 ----
     the TREE_PUROSE will be the class type, and the TREE_VALUE will be
     NULL_TREE.  */
  #define DECL_FRIENDLIST(NODE)		(DECL_INITIAL (NODE))
+ #define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
+ #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
  
  /* The DECL_ACCESS, if non-NULL, is a TREE_LIST.  The TREE_PURPOSE of
     each node is a type; the TREE_VALUE is the access granted for this
*************** extern tree current_class_name;	/* IDENT
*** 2676,2684 ****
     class derived from the type pointed to (referred to) by TYPE1.  */
  #define same_or_base_type_p(type1, type2) \
    comptypes ((type1), (type2), COMPARE_BASE)
- 
- #define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
- #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
  
  /* These macros are used to access a TEMPLATE_PARM_INDEX.  */
  #define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
--- 2687,2692 ----
Index: cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.325
diff -c -p -r1.325 decl.c
*** decl.c	1999/03/17 00:28:27	1.325
--- decl.c	1999/03/24 08:57:50
*************** duplicate_decls (newdecl, olddecl)
*** 3326,3331 ****
--- 3326,3338 ----
        DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
        DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
        olddecl_friend = DECL_FRIEND_P (olddecl);
+ 
+       /* Only functions have DECL_BEFRIENDING_CLASSES.  */
+       if (TREE_CODE (newdecl) == FUNCTION_DECL
+ 	  || DECL_FUNCTION_TEMPLATE_P (newdecl))
+ 	DECL_BEFRIENDING_CLASSES (newdecl)
+ 	  = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+ 		     DECL_BEFRIENDING_CLASSES (olddecl));
      }
  
    if (TREE_CODE (newdecl) == FUNCTION_DECL)
*************** fixup_anonymous_union (t)
*** 6668,6674 ****
    TYPE_HAS_INIT_REF (t) = 0;
    TYPE_HAS_CONST_INIT_REF (t) = 0;
    TYPE_HAS_ASSIGN_REF (t) = 0;
-   TYPE_HAS_ASSIGNMENT (t) = 0;
    TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
  
    /* Splice the implicitly generated functions out of the TYPE_METHODS
--- 6675,6680 ----
*************** grok_op_properties (decl, virtualp, frie
*** 11823,11829 ****
        if (name == ansi_opname[(int) MODIFY_EXPR]
  	  && !(DECL_TEMPLATE_INSTANTIATION (decl)
  	       && is_member_template (DECL_TI_TEMPLATE (decl))))
! 	TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
        else if (name == ansi_opname[(int) CALL_EXPR])
  	TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
        else if (name == ansi_opname[(int) ARRAY_REF])
--- 11829,11835 ----
        if (name == ansi_opname[(int) MODIFY_EXPR]
  	  && !(DECL_TEMPLATE_INSTANTIATION (decl)
  	       && is_member_template (DECL_TI_TEMPLATE (decl))))
! 	;
        else if (name == ansi_opname[(int) CALL_EXPR])
  	TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
        else if (name == ansi_opname[(int) ARRAY_REF])
Index: cp/friend.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/friend.c,v
retrieving revision 1.40
diff -c -p -r1.40 friend.c
*** friend.c	1999/03/05 16:38:53	1.40
--- friend.c	1999/03/24 08:57:51
*************** is_friend (type, supplicant)
*** 61,69 ****
  
        for (; list ; list = TREE_CHAIN (list))
  	{
! 	  if (name == TREE_PURPOSE (list))
  	    {
! 	      tree friends = TREE_VALUE (list);
  	      for (; friends ; friends = TREE_CHAIN (friends))
  		{
  		  if (same_type_p (ctype, TREE_PURPOSE (friends)))
--- 61,69 ----
  
        for (; list ; list = TREE_CHAIN (list))
  	{
! 	  if (name == FRIEND_NAME (list))
  	    {
! 	      tree friends = FRIEND_DECLS (list);
  	      for (; friends ; friends = TREE_CHAIN (friends))
  		{
  		  if (same_type_p (ctype, TREE_PURPOSE (friends)))
*************** add_friend (type, decl)
*** 148,158 ****
    tree list = DECL_FRIENDLIST (typedecl);
    tree name = DECL_NAME (decl);
  
    while (list)
      {
!       if (name == TREE_PURPOSE (list))
  	{
! 	  tree friends = TREE_VALUE (list);
  	  for (; friends ; friends = TREE_CHAIN (friends))
  	    {
  	      if (decl == TREE_VALUE (friends))
--- 148,160 ----
    tree list = DECL_FRIENDLIST (typedecl);
    tree name = DECL_NAME (decl);
  
+   type = TREE_TYPE (typedecl);
+ 
    while (list)
      {
!       if (name == FRIEND_NAME (list))
  	{
! 	  tree friends = FRIEND_DECLS (list);
  	  for (; friends ; friends = TREE_CHAIN (friends))
  	    {
  	      if (decl == TREE_VALUE (friends))
*************** add_friend (type, decl)
*** 170,190 ****
  	}
        list = TREE_CHAIN (list);
      }
    DECL_FRIENDLIST (typedecl)
      = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
  		 DECL_FRIENDLIST (typedecl));
!   if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR])
!     {
!       tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
!       TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
!       if (parmtypes && TREE_CHAIN (parmtypes))
! 	{
! 	  tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes));
! 	  if (TREE_CODE (parmtype) == REFERENCE_TYPE
! 	      && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl))
! 	    TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1;
! 	}
!     }
  }
  
  /* Declare that every member function NAME in FRIEND_TYPE
--- 172,184 ----
  	}
        list = TREE_CHAIN (list);
      }
+ 
    DECL_FRIENDLIST (typedecl)
      = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
  		 DECL_FRIENDLIST (typedecl));
!   DECL_BEFRIENDING_CLASSES (decl) 
!     = tree_cons (NULL_TREE, type,
! 		 DECL_BEFRIENDING_CLASSES (decl));
  }
  
  /* Declare that every member function NAME in FRIEND_TYPE
*************** add_friends (type, name, friend_type)
*** 199,207 ****
  
    while (list)
      {
!       if (name == TREE_PURPOSE (list))
  	{
! 	  tree friends = TREE_VALUE (list);
  	  while (friends && TREE_PURPOSE (friends) != friend_type)
  	    friends = TREE_CHAIN (friends);
  	  if (friends)
--- 193,201 ----
  
    while (list)
      {
!       if (name == FRIEND_NAME (list))
  	{
! 	  tree friends = FRIEND_DECLS (list);
  	  while (friends && TREE_PURPOSE (friends) != friend_type)
  	    friends = TREE_CHAIN (friends);
  	  if (friends)
*************** add_friends (type, name, friend_type)
*** 226,238 ****
      = tree_cons (name,
  		 build_tree_list (friend_type, NULL_TREE),
  		 DECL_FRIENDLIST (typedecl));
-   if (! strncmp (IDENTIFIER_POINTER (name),
- 		 IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]),
- 		 strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]))))
-     {
-       TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1;
-       sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists");
-     }
  }
  
  /* Make FRIEND_TYPE a friend class to TYPE.  If FRIEND_TYPE has already
--- 220,225 ----
*************** make_friend_class (type, friend_type)
*** 308,313 ****
--- 295,305 ----
      {
        CLASSTYPE_FRIEND_CLASSES (type)
  	= tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type));
+       if (is_template_friend)
+ 	friend_type = TREE_TYPE (friend_type);
+       CLASSTYPE_BEFRIENDING_CLASSES (friend_type)
+ 	= tree_cons (NULL_TREE, type, 
+ 		     CLASSTYPE_BEFRIENDING_CLASSES (friend_type)); 
      }
  }
  
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.272
diff -c -p -r1.272 pt.c
*** pt.c	1999/03/23 16:13:42	1.272
--- pt.c	1999/03/24 08:58:01
*************** instantiate_class_template (type)
*** 4783,4789 ****
  
    TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
    TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
-   TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern);
    TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
    TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
    TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
--- 4783,4788 ----
*************** tsubst_copy (t, args, complain, in_decl)
*** 6682,6688 ****
      case THROW_EXPR:
      case TYPEID_EXPR:
        return build1
! 	(code, NULL_TREE,
  	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
  
      case PLUS_EXPR:
--- 6681,6687 ----
      case THROW_EXPR:
      case TYPEID_EXPR:
        return build1
! 	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
  	 tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
  
      case PLUS_EXPR:
Index: cp/ptree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/ptree.c,v
retrieving revision 1.14
diff -c -p -r1.14 ptree.c
*** ptree.c	1998/12/16 21:16:04	1.14
--- ptree.c	1999/03/24 08:58:01
*************** print_lang_type (file, node, indent)
*** 113,120 ****
      fputs (" delete", file);
    if (TYPE_GETS_DELETE (node) & 2)
      fputs (" delete[]", file);
-   if (TYPE_HAS_ASSIGNMENT (node))
-     fputs (" has=", file);
    if (TYPE_HAS_ASSIGN_REF (node))
      fputs (" this=(X&)", file);
    if (TYPE_OVERLOADS_CALL_EXPR (node))
--- 113,118 ----
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.87
diff -c -p -r1.87 search.c
*** search.c	1999/03/15 13:42:56	1.87
--- search.c	1999/03/24 08:58:03
*************** static tree access_in_type PROTO ((tree,
*** 147,152 ****
--- 147,154 ----
  static tree dfs_canonical_queue PROTO ((tree, void *));
  static tree dfs_assert_unmarked_p PROTO ((tree, void *));
  static void assert_canonical_unmarked PROTO ((tree));
+ static int protected_accessible_p PROTO ((tree, tree, tree, tree));
+ static int friend_accessible_p PROTO ((tree, tree, tree, tree));
  
  /* Allocate a level of searching.  */
  
*************** dfs_accessible_p (binfo, data)
*** 846,851 ****
--- 848,963 ----
    return NULL_TREE;
  }
  
+ /* Returns non-zero if it is OK to access DECL when named in TYPE
+    through an object indiated by BINFO in the context of DERIVED.  */
+ 
+ static int
+ protected_accessible_p (type, decl, derived, binfo)
+      tree type;
+      tree decl;
+      tree derived;
+      tree binfo;
+ {
+   tree access;
+ 
+   /* We're checking this clause from [class.access.base]
+ 
+        m as a member of N is protected, and the reference occurs in a
+        member or friend of class N, or in a member or friend of a
+        class P derived from N, where m as a member of P is private or
+        protected.  
+ 
+     If DERIVED isn't derived from TYPE, then it certainly does not
+     apply.  */
+   if (!DERIVED_FROM_P (type, derived))
+     return 0;
+ 
+   access = access_in_type (derived, decl);
+   if (same_type_p (derived, type))
+     {
+       if (access != access_private_node)
+ 	return 0;
+     }
+   else if (access != access_private_node
+ 	   && access != access_protected_node)
+     return 0;
+   
+   /* [class.protected]
+ 
+      When a friend or a member function of a derived class references
+      a protected nonstatic member of a base class, an access check
+      applies in addition to those described earlier in clause
+      _class.access_.4) Except when forming a pointer to member
+      (_expr.unary.op_), the access must be through a pointer to,
+      reference to, or object of the derived class itself (or any class
+      derived from that class) (_expr.ref_).  If the access is to form
+      a pointer to member, the nested-name-specifier shall name the
+      derived class (or any class derived from that class).  */
+   if (DECL_NONSTATIC_MEMBER_P (decl))
+     {
+       /* We can tell through what the reference is occurring by
+ 	 chasing BINFO up to the root.  */
+       tree t = binfo;
+       while (BINFO_INHERITANCE_CHAIN (t))
+ 	t = BINFO_INHERITANCE_CHAIN (t);
+       
+       if (!DERIVED_FROM_P (derived, BINFO_TYPE (t)))
+ 	return 0;
+     }
+ 
+   return 1;
+ }
+ 
+ /* Returns non-zero if SCOPE is a friend of a type which would be able
+    to acces DECL, named in TYPE, through the object indicated by
+    BINFO.  */
+ 
+ static int
+ friend_accessible_p (scope, type, decl, binfo)
+      tree scope;
+      tree type;
+      tree decl;
+      tree binfo;
+ {
+   tree befriending_classes;
+   tree t;
+ 
+   if (!scope)
+     return 0;
+ 
+   if (TREE_CODE (scope) == FUNCTION_DECL
+       || DECL_FUNCTION_TEMPLATE_P (scope))
+     befriending_classes = DECL_BEFRIENDING_CLASSES (scope);
+   else if (TYPE_P (scope))
+     befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope);
+   else
+     return 0;
+ 
+   for (t = befriending_classes; t; t = TREE_CHAIN (t))
+     if (protected_accessible_p (type, decl, TREE_VALUE (t), binfo))
+       return 1;
+ 
+   if (TREE_CODE (scope) == FUNCTION_DECL
+       || DECL_FUNCTION_TEMPLATE_P (scope))
+     {
+       /* Perhaps this SCOPE is a member of a class which is a 
+ 	 friend.  */ 
+       if (friend_accessible_p (DECL_CLASS_CONTEXT (scope), type,
+ 			       decl, binfo))
+ 	return 1;
+ 
+       /* Or an instantiation of something which is a friend.  */
+       if (DECL_TEMPLATE_INFO (scope))
+ 	return friend_accessible_p (DECL_TI_TEMPLATE (scope),
+ 				    type, decl, binfo);
+     }
+   else if (CLASSTYPE_TEMPLATE_INFO (scope))
+     return friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope),
+ 				type, decl, binfo);
+ 
+   return 0;
+ }
+    
  /* DECL is a declaration from a base class of TYPE, which was the
     classs used to name DECL.  Return non-zero if, in the current
     context, DECL is accessible.  If TYPE is actually a BINFO node,
*************** accessible_p (type, decl)
*** 858,864 ****
       tree decl;
       
  {
-   tree scope;
    tree binfo;
    tree t;
  
--- 970,975 ----
*************** accessible_p (type, decl)
*** 909,956 ****
    /* Figure out where the reference is occurring.  Check to see if
       DECL is private or protected in this scope, since that will
       determine whether protected access in TYPE allowed.  */
!   if (current_class_type
!       && DERIVED_FROM_P (type, current_class_type))
!     {
!       tree access = access_in_type (current_class_type, decl);
!       if (same_type_p (current_class_type, type)
! 	  && access == access_private_node)
! 	protected_ok = 1;
!       else if (access && (access == access_private_node
! 			  || access == access_protected_node))
! 	protected_ok = 1;
!     }
  
-   /* Now, loop through the classes of which SCOPE is a friend.  */
-   if (!protected_ok && scope)
-     {
-       /* FIXME: Implement this.  Right now, we have no way of knowing
- 	        which classes befriend a particular function or class.  */
-     }
- 
-   /* [class.protected]
- 
-      When a friend or a member function of a derived class references
-      a protected nonstatic member of a base class, an access check
-      applies in addition to those described earlier in clause
-      _class.access_.4) Except when forming a pointer to member
-      (_expr.unary.op_), the access must be through a pointer to,
-      reference to, or object of the derived class itself (or any class
-      derived from that class) (_expr.ref_).  If the access is to form
-      a pointer to member, the nested-name-specifier shall name the
-      derived class (or any class derived from that class).  */
-   if (protected_ok && DECL_NONSTATIC_MEMBER_P (decl))
-     {
-       /* We can tell through what the reference is occurring by
- 	 chasing BINFO up to the root.  */
-       t = binfo;
-       while (BINFO_INHERITANCE_CHAIN (t))
- 	t = BINFO_INHERITANCE_CHAIN (t);
-       
-       if (!DERIVED_FROM_P (current_class_type, BINFO_TYPE (t)))
- 	protected_ok = 0;
-     }
-   
    /* Standardize on the same that will access_in_type will use.  We
       don't need to know what path was chosen from this point onwards.  */ 
    binfo = TYPE_BINFO (type);
--- 1020,1035 ----
    /* Figure out where the reference is occurring.  Check to see if
       DECL is private or protected in this scope, since that will
       determine whether protected access in TYPE allowed.  */
!   if (current_class_type)
!     protected_ok 
!       = protected_accessible_p (type, decl, current_class_type,
! 				binfo);
! 
!   /* Now, loop through the classes of which we are a friend.  */
!   if (!protected_ok)
!     protected_ok = friend_accessible_p (current_scope (),
! 					type, decl, binfo);
  
    /* Standardize on the same that will access_in_type will use.  We
       don't need to know what path was chosen from this point onwards.  */ 
    binfo = TYPE_BINFO (type);


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