This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH for access declarations
- To: Jason Merrill <jason at cygnus dot com>
- Subject: PATCH for access declarations
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Sat, 13 Jun 1998 23:16:37 -0700
- Cc: egcs-patches at cygnus dot com
- Reply-to: mark at markmitchell dot com
Here's a patch that makes us complain about illegal access (using)
declarations in classes. Jason, OK?
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-06-13 Mark Mitchell <mark@markmitchell.com>
* class.c (alter_access): Accept a BINFO explaining how to get
from the entity whose accessed is being altered to the type doing
the altering.
(handle_using_decl): New function containing code split out from ...
(finish_struct_1): Here.
Index: testsuite/g++.old-deja/g++.other/using1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.other/using1.C,v
retrieving revision 1.1
diff -c -p -r1.1 using1.C
*** using1.C 1998/03/25 16:14:49 1.1
--- using1.C 1998/06/14 06:09:36
*************** class D2;
*** 2,8 ****
class B {
private:
! int a;
protected:
int b;
--- 2,8 ----
class B {
private:
! int a; // ERROR - B::a is private
protected:
int b;
*************** class D : public B {
*** 13,19 ****
public:
using B::a;
using B::b;
! };
class D2 : public B {
public:
--- 13,19 ----
public:
using B::a;
using B::b;
! }; // ERROR - within this context
class D2 : public B {
public:
Index: cp/class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.60
diff -c -p -r1.60 class.c
*** class.c 1998/06/12 09:46:57 1.60
--- class.c 1998/06/14 06:07:30
*************** static void add_virtual_function PROTO((
*** 107,113 ****
static tree delete_duplicate_fields_1 PROTO((tree, tree));
static void delete_duplicate_fields PROTO((tree));
static void finish_struct_bits PROTO((tree, int));
! static int alter_access PROTO((tree, tree, tree));
static int overrides PROTO((tree, tree));
static int strictly_overrides PROTO((tree, tree));
static void merge_overrides PROTO((tree, tree, int, tree));
--- 107,114 ----
static tree delete_duplicate_fields_1 PROTO((tree, tree));
static void delete_duplicate_fields PROTO((tree));
static void finish_struct_bits PROTO((tree, int));
! static int alter_access PROTO((tree, tree, tree, tree));
! static void handle_using_decl PROTO((tree, tree, tree, tree));
static int overrides PROTO((tree, tree));
static int strictly_overrides PROTO((tree, tree));
static void merge_overrides PROTO((tree, tree, int, tree));
*************** delete_duplicate_fields (fields)
*** 1277,1288 ****
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
}
! /* Change the access of FDECL to ACCESS in T.
! Return 1 if change was legit, otherwise return 0. */
static int
! alter_access (t, fdecl, access)
tree t;
tree fdecl;
tree access;
{
--- 1278,1291 ----
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
}
! /* Change the access of FDECL to ACCESS in T. The access to FDECL is
! along the path given by BINFO. Return 1 if change was legit,
! otherwise return 0. */
static int
! alter_access (t, binfo, fdecl, access)
tree t;
+ tree binfo;
tree fdecl;
tree access;
{
*************** alter_access (t, fdecl, access)
*** 1306,1312 ****
}
else
{
! enforce_access (TYPE_BINFO (t), fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
--- 1309,1315 ----
}
else
{
! enforce_access (binfo, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
*************** alter_access (t, fdecl, access)
*** 1314,1319 ****
--- 1317,1410 ----
return 0;
}
+ /* Process the USING_DECL, which is a member of T. The METHOD_VEC, if
+ non-NULL, is the methods of T. The FIELDS are the fields of T.
+ Returns 1 if the USING_DECL was valid, 0 otherwise. */
+
+ void
+ handle_using_decl (using_decl, t, method_vec, fields)
+ tree using_decl;
+ tree t;
+ tree method_vec;
+ tree fields;
+ {
+ tree ctype = DECL_INITIAL (using_decl);
+ tree name = DECL_NAME (using_decl);
+ tree access
+ = TREE_PRIVATE (using_decl) ? access_private_node
+ : TREE_PROTECTED (using_decl) ? access_protected_node
+ : access_public_node;
+ tree fdecl, binfo;
+ tree flist = NULL_TREE;
+ tree tmp;
+ int i;
+ int n_methods;
+
+ binfo = binfo_or_else (ctype, t);
+ if (! binfo)
+ return;
+
+ if (name == constructor_name (ctype)
+ || name == constructor_name_full (ctype))
+ cp_error_at ("using-declaration for constructor", using_decl);
+
+ fdecl = lookup_member (binfo, name, 0, 0);
+
+ if (!fdecl)
+ {
+ cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype);
+ return;
+ }
+
+ /* Functions are represented as TREE_LIST, with the purpose
+ being the type and the value the functions. Other members
+ come as themselves. */
+ if (TREE_CODE (fdecl) == TREE_LIST)
+ /* Ignore base type this came from. */
+ fdecl = TREE_VALUE (fdecl);
+
+ if (TREE_CODE (fdecl) == OVERLOAD)
+ {
+ /* We later iterate over all functions. */
+ flist = fdecl;
+ fdecl = OVL_FUNCTION (flist);
+ }
+
+ name = DECL_NAME (fdecl);
+ n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
+ for (i = 2; i < n_methods; i++)
+ if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
+ == name)
+ {
+ cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
+ cp_error_at (" because of local method `%#D' with same name",
+ OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+ return;
+ }
+
+ for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
+ if (DECL_NAME (tmp) == name)
+ {
+ cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
+ cp_error_at (" because of local field `%#D' with same name", tmp);
+ return;
+ }
+
+ /* Make type T see field decl FDECL with access ACCESS.*/
+ if (flist)
+ {
+ while (flist)
+ {
+ if (alter_access (t, binfo, OVL_FUNCTION (flist),
+ access) == 0)
+ return;
+ flist = OVL_CHAIN (flist);
+ }
+ }
+ else
+ alter_access (t, binfo, fdecl, access);
+ }
+
/* If FOR_TYPE needs to reinitialize virtual function table pointers
for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
Returns BASE_INIT_LIST appropriately modified. */
*************** finish_struct_1 (t, warn_anon)
*** 3186,3221 ****
empty = 0;
}
- /* Handle access declarations. */
if (TREE_CODE (x) == USING_DECL)
{
! tree ctype = DECL_INITIAL (x);
! tree sname = DECL_NAME (x);
! tree access
! = TREE_PRIVATE (x) ? access_private_node
! : TREE_PROTECTED (x) ? access_protected_node
! : access_public_node;
! tree fdecl, binfo;
!
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
!
! binfo = binfo_or_else (ctype, t);
! if (! binfo)
! continue;
!
! if (sname == constructor_name (ctype)
! || sname == constructor_name_full (ctype))
! cp_error_at ("using-declaration for constructor", x);
!
! fdecl = lookup_member (binfo, sname, 0, 0);
!
! if (fdecl)
! access_decls = scratch_tree_cons (access, fdecl, access_decls);
! else
! cp_error_at ("no members matching `%D' in `%#T'", x, ctype);
continue;
}
--- 3277,3291 ----
empty = 0;
}
if (TREE_CODE (x) == USING_DECL)
{
! /* Save access declarations for later. */
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
!
! access_decls = scratch_tree_cons (NULL_TREE, x, access_decls);
continue;
}
*************** finish_struct_1 (t, warn_anon)
*** 3657,3734 ****
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
}
-
- {
- int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
-
- for (access_decls = nreverse (access_decls); access_decls;
- access_decls = TREE_CHAIN (access_decls))
- {
- tree fdecl = TREE_VALUE (access_decls);
- tree flist = NULL_TREE;
- tree name;
- tree access = TREE_PURPOSE (access_decls);
- int i = 2;
- tree tmp;
-
- /* Functions are represented as TREE_LIST, with the purpose
- being the type and the value the functions. Other members
- come as themselves. */
- if (TREE_CODE (fdecl) == TREE_LIST)
- {
- /* Ignore base type this came from. */
- fdecl = TREE_VALUE (fdecl);
- }
- if (TREE_CODE (fdecl) == OVERLOAD)
- {
- /* We later iterate over all functions. */
- flist = fdecl;
- fdecl = OVL_FUNCTION (flist);
- }
-
- name = DECL_NAME (fdecl);
-
- for (; i < n_methods; i++)
- if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
- == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local method `%#D' with same name",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- fdecl = NULL_TREE;
- break;
- }
! if (! fdecl)
! continue;
!
! for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
! if (DECL_NAME (tmp) == name)
! {
! cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
! cp_error_at (" because of local field `%#D' with same name", tmp);
! fdecl = NULL_TREE;
! break;
! }
!
! if (!fdecl)
! continue;
!
! /* Make type T see field decl FDECL with access ACCESS.*/
! if (flist)
! {
! while (flist)
! {
! if (alter_access (t, OVL_FUNCTION (flist), access) == 0)
! break;
! flist = OVL_CHAIN (flist);
! }
! }
! else
! alter_access (t, fdecl, access);
! }
!
! }
if (vfield == NULL_TREE && has_virtual)
{
--- 3727,3736 ----
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
}
! for (access_decls = nreverse (access_decls); access_decls;
! access_decls = TREE_CHAIN (access_decls))
! handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
if (vfield == NULL_TREE && has_virtual)
{