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]
Other format: [Raw text]

[C++ PATCH] Fix PR3765 (problem modifying access via using declaration)


This patch fixes an access checking problem in 'accessible_p'.
A derived class may have more restricted access than base class
due to in-class using declaration or access declaration.  For
example, the base class may have public access while the derived
class modifies the access to private.

However, we are performing depth-first-search with 'dfs_accessible_p'.
And it terminates searching when we have access.  So for the above
example, it finds the public base class before looking at its
derived class.  This patch adjusts the check so that base class
access is obtained from 'access_in_type' while only friend access
is dealt with by 'dfs_accessible_p'.  The patch also fixes numerous
typos in the comment in relevant codes.

Tested on i686-pc-linux-gnu.  OK for trunk?

--Kriang


2003-06-16  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/3765
	* friend.c (add_friend): Check access for member functions
	and templates.

2003-06-16  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	PR c++/3765
	* g++.dg/parse/access4.C: New test.



diff -cprN gcc-main-save/gcc/cp/search.c gcc-main-new/gcc/cp/search.c
*** gcc-main-save/gcc/cp/search.c	Sun Jun 15 20:39:45 2003
--- gcc-main-new/gcc/cp/search.c	Sun Jun 15 21:13:29 2003
*************** dfs_access_in_type (tree binfo, void *da
*** 635,641 ****
  
    if (context_for_name_lookup (decl) == type)
      {
!       /* If we have desceneded to the scope of DECL, just note the
  	 appropriate access.  */
        if (TREE_PRIVATE (decl))
  	access = ak_private;
--- 635,641 ----
  
    if (context_for_name_lookup (decl) == type)
      {
!       /* If we have descended to the scope of DECL, just note the
  	 appropriate access.  */
        if (TREE_PRIVATE (decl))
  	access = ak_private;
*************** access_in_type (tree type, tree decl)
*** 749,755 ****
    return BINFO_ACCESS (binfo);
  }
  
! /* Called from dfs_accessible_p via dfs_walk.  */
  
  static tree
  dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
--- 749,755 ----
    return BINFO_ACCESS (binfo);
  }
  
! /* Called from accessible_p via dfs_walk.  */
  
  static tree
  dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
*************** dfs_accessible_queue_p (tree derived, in
*** 768,787 ****
    return binfo;
  }
  
! /* Called from dfs_accessible_p via dfs_walk.  */
  
  static tree
! dfs_accessible_p (tree binfo, void *data)
  {
-   int protected_ok = data != 0;
    access_kind access;
  
    BINFO_MARKED (binfo) = 1;
    access = BINFO_ACCESS (binfo);
!   if (access == ak_public || (access == ak_protected && protected_ok))
!     return binfo;
!   else if (access != ak_none
! 	   && is_friend (BINFO_TYPE (binfo), current_scope ()))
      return binfo;
  
    return NULL_TREE;
--- 768,784 ----
    return binfo;
  }
  
! /* Called from accessible_p via dfs_walk.  */
  
  static tree
! dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
  {
    access_kind access;
  
    BINFO_MARKED (binfo) = 1;
    access = BINFO_ACCESS (binfo);
!   if (access != ak_none
!       && is_friend (BINFO_TYPE (binfo), current_scope ()))
      return binfo;
  
    return NULL_TREE;
*************** accessible_p (tree type, tree decl)
*** 908,913 ****
--- 905,911 ----
  {
    tree binfo;
    tree t;
+   access_kind access;
  
    /* Nonzero if it's OK to access DECL if it has protected
       accessibility in TYPE.  */
*************** accessible_p (tree type, tree decl)
*** 961,978 ****
  
    /* Compute the accessibility of DECL in the class hierarchy
       dominated by type.  */
!   access_in_type (type, decl);
!   /* Walk the hierarchy again, looking for a base class that allows
!      access.  */
!   t = dfs_walk (binfo, dfs_accessible_p, 
! 		dfs_accessible_queue_p,
! 		protected_ok ? &protected_ok : 0);
!   /* Clear any mark bits.  Note that we have to walk the whole tree
!      here, since we have aborted the previous walk from some point
!      deep in the tree.  */
!   dfs_walk (binfo, dfs_unmark, 0,  0);
  
!   return t != NULL_TREE;
  }
  
  struct lookup_field_info {
--- 959,980 ----
  
    /* Compute the accessibility of DECL in the class hierarchy
       dominated by type.  */
!   access = access_in_type (type, decl);
!   if (access == ak_public
!       || (access == ak_protected && protected_ok))
!     return 1;
!   else
!     {
!       /* Walk the hierarchy again, looking for a base class that allows
! 	 access.  */
!       t = dfs_walk (binfo, dfs_accessible_p, dfs_accessible_queue_p, 0);
!       /* Clear any mark bits.  Note that we have to walk the whole tree
! 	 here, since we have aborted the previous walk from some point
! 	 deep in the tree.  */
!       dfs_walk (binfo, dfs_unmark, 0,  0);
  
!       return t != NULL_TREE;
!     }
  }
  
  struct lookup_field_info {
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/access4.C gcc-main-new/gcc/testsuite/g++.dg/parse/access4.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/access4.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/parse/access4.C	Sun Jun 15 19:45:03 2003
***************
*** 0 ****
--- 1,24 ----
+ // { dg-do compile }
+ 
+ // Origin: David Baron <dbaron@fas.harvard.edu>
+ 
+ // PR c++/3765: Changing access from public to private by member
+ // using declaration.
+ 
+ class A
+ {
+   public:
+     int foo() { return 1; }	// { dg-error "inaccessible" }
+ };
+ 
+ class B : public A
+ {
+   private:
+     using A::foo;
+ };
+ 
+ int main()
+ {
+   B b;
+   return b.foo();		// { dg-error "this context" }
+ }


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