(C++) patch to implement access control for types

Jason Merrill jason@cygnus.com
Mon Feb 7 12:33:00 GMT 2000


I finally got tired of the periodic reports that this doesn't work and
decided to make it work.  See the comment before type_access_control
for a description of the design; it's a bit cheesy, but it works.  I
also fixed access control for static data members of enclosing classes
while I was at it.

2000-02-07  Jason Merrill  <jason@casey.cygnus.com>

	Implement access control for nested types.
	* search.c (type_access_control): New fn.
	(accessible_p): Now we do perform access control for types.
	* semantics.c (deferred_type_access_control): New fn.
	(initial_deferred_type_access_control): New fn.
	(begin_function_definition): Call it.  Add lookups parm.
	* decl.c (struct binding_level): Add this_class field.
	(pushlevel_class): Set it.
	(mark_binding_level): Mark it.
	(lookup_name_real): Use it.  Call type_access_control.
	(mark_saved_scope): Mark lookups field.
	* cp-tree.h (flagged_type_tree): Add lookups field.
	(struct saved_scope): Add lookups field.
	(type_lookups): New macro.
	* parse.y (declmods): Now <ftype>.
	(parse_decl): Add lookups parm.  Call 
	initial_deferred_type_access_control.
	(lang_extdef): Clear type_lookups.
	(typed_declspecs, declmods, typespec): Set lookups field.
	(initdcl): Call deferred_type_access_control.
	(fn.def1, fn.def2, typed_declspecs1, initdcl0_innards, nomods_initdcl0,
	component_decl_1, named_parm): Adjust.
	* friend.c (is_friend): Nested classes are friends of their
	enclosing classes.

	* class.c (currently_open_derived_class): New fn.
	* method.c (hack_identifier): Use it.

	* parse.y (typed_typespecs): Propagate new_type_flag properly.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.253
diff -c -p -r1.253 class.c
*** class.c	2000/02/06 04:27:53	1.253
--- class.c	2000/02/07 20:21:40
*************** popclass ()
*** 5487,5493 ****
      splay_tree_delete (current_class_stack[current_class_depth].names_used);
  }
  
! /* Returns 1 if current_class_type is either T or a nested type of T.  */
  
  int
  currently_open_class (t)
--- 5487,5495 ----
      splay_tree_delete (current_class_stack[current_class_depth].names_used);
  }
  
! /* Returns 1 if current_class_type is either T or a nested type of T.
!    We start looking from 1 because entry 0 is from global scope, and has
!    no type.  */
  
  int
  currently_open_class (t)
*************** currently_open_class (t)
*** 5496,5505 ****
    int i;
    if (t == current_class_type)
      return 1;
!   for (i = 0; i < current_class_depth; ++i)
      if (current_class_stack [i].type == t)
        return 1;
    return 0;
  }
  
  /* When entering a class scope, all enclosing class scopes' names with
--- 5498,5527 ----
    int i;
    if (t == current_class_type)
      return 1;
!   for (i = 1; i < current_class_depth; ++i)
      if (current_class_stack [i].type == t)
        return 1;
    return 0;
+ }
+ 
+ /* If either current_class_type or one of its enclosing classes are derived
+    from T, return the appropriate type.  Used to determine how we found
+    something via unqualified lookup.  */
+ 
+ tree
+ currently_open_derived_class (t)
+      tree t;
+ {
+   int i;
+ 
+   if (DERIVED_FROM_P (t, current_class_type))
+     return current_class_type;
+ 
+   for (i = current_class_depth - 1; i > 0; --i)
+     if (DERIVED_FROM_P (t, current_class_stack[i].type))
+       return current_class_stack[i].type;
+ 
+   return NULL_TREE;
  }
  
  /* When entering a class scope, all enclosing class scopes' names with
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.400
diff -c -p -r1.400 cp-tree.h
*** cp-tree.h	2000/01/31 21:00:01	1.400
--- cp-tree.h	2000/02/07 20:21:43
*************** typedef struct 
*** 276,281 ****
--- 276,282 ----
  {
    tree t;
    int new_type_flag;
+   tree lookups;
  } flagged_type_tree;
  
  typedef struct 
*************** struct saved_scope {
*** 714,719 ****
--- 715,722 ----
    tree x_previous_class_type;
    tree x_previous_class_values;
    tree x_saved_tree;
+   tree lookups;
  
    HOST_WIDE_INT x_processing_template_decl;
    int x_processing_specialization;
*************** struct saved_scope {
*** 774,779 ****
--- 777,790 ----
  
  #define previous_class_values scope_chain->x_previous_class_values
  
+ /* A list of private types mentioned, for deferred access checking.  */
+ 
+ #define type_lookups scope_chain->lookups
+ 
  extern struct saved_scope *scope_chain;
  
  /* Global state pertinent to the current function.  */
*************** extern tree build_vfn_ref			PARAMS ((tre
*** 3550,3555 ****
--- 3561,3567 ----
  extern tree get_vtable_decl                     PARAMS ((tree, int));
  extern void add_method				PARAMS ((tree, tree *, tree));
  extern int currently_open_class			PARAMS ((tree));
+ extern tree currently_open_derived_class	PARAMS ((tree));
  extern tree get_vfield_offset			PARAMS ((tree));
  extern void duplicate_tag_error			PARAMS ((tree));
  extern tree finish_struct			PARAMS ((tree, tree));
*************** extern tree get_vbase				PARAMS ((tree, 
*** 4043,4048 ****
--- 4055,4061 ----
  extern tree get_binfo				PARAMS ((tree, tree, int));
  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 int accessible_p                         PARAMS ((tree, tree));
  extern tree lookup_field			PARAMS ((tree, tree, int, int));
  extern int lookup_fnfields_1                    PARAMS ((tree, tree));
*************** extern tree finish_qualified_call_expr  
*** 4153,4159 ****
  extern tree finish_label_address_expr           PARAMS ((tree));
  extern tree finish_unary_op_expr                PARAMS ((enum tree_code, tree));
  extern tree finish_id_expr                      PARAMS ((tree));
! extern int begin_function_definition            PARAMS ((tree, tree));
  extern tree begin_constructor_declarator        PARAMS ((tree, tree));
  extern tree finish_declarator                   PARAMS ((tree, tree, tree, tree, int));
  extern void finish_translation_unit             PARAMS ((void));
--- 4166,4174 ----
  extern tree finish_label_address_expr           PARAMS ((tree));
  extern tree finish_unary_op_expr                PARAMS ((enum tree_code, tree));
  extern tree finish_id_expr                      PARAMS ((tree));
! extern void deferred_type_access_control	PARAMS ((void));
! extern void initial_deferred_type_access_control PARAMS ((tree));
! extern int begin_function_definition            PARAMS ((tree, tree, tree));
  extern tree begin_constructor_declarator        PARAMS ((tree, tree));
  extern tree finish_declarator                   PARAMS ((tree, tree, tree, tree, int));
  extern void finish_translation_unit             PARAMS ((void));
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.541
diff -c -p -r1.541 decl.c
*** decl.c	2000/01/29 19:10:00	1.541
--- decl.c	2000/02/07 20:21:52
*************** struct binding_level
*** 442,447 ****
--- 442,450 ----
         If 0, the BLOCK is allocated (if needed) when the level is popped.  */
      tree this_block;
  
+     /* The _TYPE node for this level, if parm_flag == 2.  */
+     tree this_class;
+ 
      /* The binding level which this one is contained in (inherits from).  */
      struct binding_level *level_chain;
  
*************** pushlevel_class ()
*** 1524,1529 ****
--- 1527,1533 ----
  
    class_binding_level = current_binding_level;
    class_binding_level->parm_flag = 2;
+   class_binding_level->this_class = current_class_type;
  }
  
  /* ...and a poplevel for class declarations.  */
*************** mark_binding_level (arg)
*** 1837,1842 ****
--- 1841,1847 ----
        ggc_mark_tree (lvl->shadowed_labels);
        ggc_mark_tree (lvl->blocks);
        ggc_mark_tree (lvl->this_block);
+       ggc_mark_tree (lvl->this_class);
        ggc_mark_tree (lvl->incomplete);
        ggc_mark_tree (lvl->dead_vars_from_for);
  
*************** mark_saved_scope (arg)
*** 2278,2283 ****
--- 2283,2290 ----
        ggc_mark_tree (t->x_previous_class_type);
        ggc_mark_tree (t->x_previous_class_values);
        ggc_mark_tree (t->x_saved_tree);
+       ggc_mark_tree (t->lookups);
  
        mark_stmt_tree (&t->x_stmt_tree);
        mark_binding_level (&t->bindings);
*************** lookup_name_real (name, prefer_type, non
*** 5602,5608 ****
  	  else if (type == current_class_type)
  	    val = IDENTIFIER_CLASS_VALUE (name);
  	  else
! 	    val = lookup_member (type, name, 0, prefer_type);
  	}
        else
  	val = NULL_TREE;
--- 5615,5624 ----
  	  else if (type == current_class_type)
  	    val = IDENTIFIER_CLASS_VALUE (name);
  	  else
! 	    {
! 	      val = lookup_member (type, name, 0, prefer_type);
! 	      type_access_control (type, val);
! 	    }
  	}
        else
  	val = NULL_TREE;
*************** lookup_name_real (name, prefer_type, non
*** 5641,5646 ****
--- 5657,5667 ----
        else
  	binding = NULL_TREE;
  
+       /* Handle access control on types from enclosing or base classes.  */
+       if (binding && ! yylex
+ 	  && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
+ 	type_access_control (BINDING_LEVEL (t)->this_class, binding);
+ 
        if (binding
  	  && (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
  	{
Index: friend.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/friend.c,v
retrieving revision 1.50
diff -c -p -r1.50 friend.c
*** friend.c	2000/01/11 08:54:28	1.50
--- friend.c	2000/02/07 20:21:53
*************** is_friend (type, supplicant)
*** 101,108 ****
    else
      /* It's a type.  */
      {
!       if (type == supplicant)
! 	return 1;
        
        list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
        for (; list ; list = TREE_CHAIN (list))
--- 101,113 ----
    else
      /* It's a type.  */
      {
!       /* The type and its nested classes are implicitly friends, as
! 	 per core issue 45 (this is a change from the standard).  */
!       for (context = supplicant;
! 	   context && TYPE_P (context);
! 	   context = TYPE_CONTEXT (context))
! 	if (type == context)
! 	  return 1;
        
        list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
        for (; list ; list = TREE_CHAIN (list))
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.134
diff -c -p -r1.134 method.c
*** method.c	2000/01/29 03:59:09	1.134
--- method.c	2000/02/07 20:21:56
*************** hack_identifier (value, name)
*** 1978,1984 ****
  
    if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
      {
!       if (DECL_LANG_SPECIFIC (value)
  	  && DECL_CLASS_CONTEXT (value) != current_class_type)
  	{
  	  tree path;
--- 1978,1984 ----
  
    if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
      {
!       if (DECL_CLASS_SCOPE_P (value)
  	  && DECL_CLASS_CONTEXT (value) != current_class_type)
  	{
  	  tree path;
*************** hack_identifier (value, name)
*** 1987,1995 ****
  	      ? DECL_CLASS_CONTEXT (value)
  	      : DECL_CONTEXT (value);
  
! 	  get_base_distance (context, current_class_type, 0, &path);
! 	  if (path && !enforce_access (current_class_type, value))
! 	    return error_mark_node;
  	}
      }
    else if (TREE_CODE (value) == TREE_LIST 
--- 1987,1994 ----
  	      ? DECL_CLASS_CONTEXT (value)
  	      : DECL_CONTEXT (value);
  
! 	  path = currently_open_derived_class (context);
! 	  enforce_access (path, value);
  	}
      }
    else if (TREE_CODE (value) == TREE_LIST 
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.161
diff -c -p -r1.161 parse.y
*** parse.y	2000/02/02 06:30:44	1.161
--- parse.y	2000/02/07 20:22:03
*************** extern int end_of_file;
*** 63,69 ****
  static const char *cond_stmt_keyword;
  
  static tree empty_parms PARAMS ((void));
! static void parse_decl PARAMS ((tree, tree, tree, int, tree *));
  
  /* Nonzero if we have an `extern "C"' acting as an extern specifier.  */
  int have_extern_spec;
--- 63,69 ----
  static const char *cond_stmt_keyword;
  
  static tree empty_parms PARAMS ((void));
! static void parse_decl PARAMS ((tree, tree, tree, tree, int, tree *));
  
  /* Nonzero if we have an `extern "C"' acting as an extern specifier.  */
  int have_extern_spec;
*************** empty_parms ()
*** 197,203 ****
  %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
  %type <ttype> reserved_declspecs boolean.literal
  %type <ttype> reserved_typespecquals
- %type <ttype> declmods 
  %type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
  %type <ttype> init initlist maybeasm maybe_init defarg defarg1
  %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
--- 197,202 ----
*************** empty_parms ()
*** 233,238 ****
--- 232,238 ----
  %type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
  %type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
  %type <ftype> structsp typespecqual_reserved parm named_parm full_parm
+ %type <ftype> declmods
  
  %type <itype> extension
  
*************** extern void yyprint			PARAMS ((FILE *, i
*** 315,327 ****
  extern tree combine_strings		PARAMS ((tree));
  
  static void
! parse_decl (declarator, specs_attrs, attributes, initialized, decl)
    tree declarator;
    tree specs_attrs;
    tree attributes;
    int initialized;
    tree* decl;
  {
    split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
    if (current_declspecs
        && TREE_CODE (current_declspecs) != TREE_LIST)
--- 315,330 ----
  extern tree combine_strings		PARAMS ((tree));
  
  static void
! parse_decl (declarator, specs_attrs, lookups, attributes, initialized, decl)
    tree declarator;
    tree specs_attrs;
+   tree lookups;
    tree attributes;
    int initialized;
    tree* decl;
  {
+   initial_deferred_type_access_control (lookups);
+ 
    split_specs_attrs (specs_attrs, &current_declspecs, &prefix_attributes);
    if (current_declspecs
        && TREE_CODE (current_declspecs) != TREE_LIST)
*************** asm_keyword:
*** 391,397 ****
  	;
  
  lang_extdef:
! 		{ if (pending_lang_change) do_pending_lang_change(); }
  	  extdef
  		{ if (! toplevel_bindings_p ())
  		  pop_everything (); }
--- 394,401 ----
  	;
  
  lang_extdef:
! 		{ if (pending_lang_change) do_pending_lang_change();
! 		  type_lookups = NULL_TREE; }
  	  extdef
  		{ if (! toplevel_bindings_p ())
  		  pop_everything (); }
*************** constructor_declarator:
*** 695,713 ****
  
  fn.def1:
  	  typed_declspecs declarator
! 		{ if (!begin_function_definition ($1.t, $2))
  		    YYERROR1; }
  	| declmods notype_declarator
! 		{ if (!begin_function_definition ($1, $2))
  		    YYERROR1; }
  	| notype_declarator
! 		{ if (!begin_function_definition (NULL_TREE, $1))
  		    YYERROR1; }
  	| declmods constructor_declarator
! 		{ if (!begin_function_definition ($1, $2))
  		    YYERROR1; }
  	| constructor_declarator
! 		{ if (!begin_function_definition (NULL_TREE, $1))
  		    YYERROR1; }
  	;
  
--- 699,717 ----
  
  fn.def1:
  	  typed_declspecs declarator
! 		{ if (!begin_function_definition ($1.t, $1.lookups, $2))
  		    YYERROR1; }
  	| declmods notype_declarator
! 		{ if (!begin_function_definition ($1.t, NULL_TREE, $2))
  		    YYERROR1; }
  	| notype_declarator
! 		{ if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
  		    YYERROR1; }
  	| declmods constructor_declarator
! 		{ if (!begin_function_definition ($1.t, NULL_TREE, $2))
  		    YYERROR1; }
  	| constructor_declarator
! 		{ if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
  		    YYERROR1; }
  	;
  
*************** component_constructor_declarator:
*** 727,733 ****
  fn.def2:
  	  declmods component_constructor_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs);
  		 rest_of_mdef:
--- 731,737 ----
  fn.def2:
  	  declmods component_constructor_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1.t, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs);
  		 rest_of_mdef:
*************** fn.def2:
*** 746,752 ****
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| declmods notype_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| notype_declarator
--- 750,756 ----
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| declmods notype_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1.t, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| notype_declarator
*************** fn.def2:
*** 754,760 ****
  		  goto rest_of_mdef; }
  	| declmods constructor_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| constructor_declarator
--- 758,764 ----
  		  goto rest_of_mdef; }
  	| declmods constructor_declarator
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1.t, &specs, &attrs);
  		  attrs = build_tree_list (attrs, NULL_TREE);
  		  $$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
  	| constructor_declarator
*************** type_id:
*** 1667,1678 ****
  
  typed_declspecs:
  	  typed_typespecs  %prec EMPTY
  	| typed_declspecs1
  	;
  
  typed_declspecs1:
  	  declmods typespec
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| typespec reserved_declspecs  %prec HYPERUNARY
  		{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); 
--- 1671,1684 ----
  
  typed_declspecs:
  	  typed_typespecs  %prec EMPTY
+ 		{ $$.lookups = type_lookups; }
  	| typed_declspecs1
+ 		{ $$.lookups = type_lookups; }
  	;
  
  typed_declspecs1:
  	  declmods typespec
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| typespec reserved_declspecs  %prec HYPERUNARY
  		{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2); 
*************** typed_declspecs1:
*** 1681,1694 ****
  		{ $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3)); 
  		  $$.new_type_flag = $1.new_type_flag; }
  	| declmods typespec reserved_declspecs
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| declmods typespec reserved_typespecquals
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1)); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| declmods typespec reserved_typespecquals reserved_declspecs
  		{ $$.t = decl_tree_cons (NULL_TREE, $2.t,
! 					 chainon ($3, chainon ($4, $1))); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	;
  
--- 1687,1700 ----
  		{ $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3)); 
  		  $$.new_type_flag = $1.new_type_flag; }
  	| declmods typespec reserved_declspecs
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| declmods typespec reserved_typespecquals
! 		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	| declmods typespec reserved_typespecquals reserved_declspecs
  		{ $$.t = decl_tree_cons (NULL_TREE, $2.t,
! 					 chainon ($3, chainon ($4, $1.t))); 
  		  $$.new_type_flag = $2.new_type_flag; }
  	;
  
*************** reserved_declspecs:
*** 1727,1748 ****
  
  declmods:
  	  nonempty_cv_qualifiers  %prec EMPTY
! 		{ $$ = $1.t; TREE_STATIC ($$) = 1; }
  	| SCSPEC
! 		{ $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
  	| declmods CV_QUALIFIER
! 		{ $$ = hash_tree_cons (NULL_TREE, $2, $$);
! 		  TREE_STATIC ($$) = 1; }
  	| declmods SCSPEC
! 		{ if (extra_warnings && TREE_STATIC ($$))
  		    warning ("`%s' is not at beginning of declaration",
  			     IDENTIFIER_POINTER ($2));
! 		  $$ = hash_tree_cons (NULL_TREE, $2, $$);
! 		  TREE_STATIC ($$) = TREE_STATIC ($1); }
  	| declmods attributes
! 		{ $$ = hash_tree_cons ($2, NULL_TREE, $1); }
  	| attributes  %prec EMPTY
! 		{ $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
  	;
  
  /* Used instead of declspecs where storage classes are not allowed
--- 1733,1764 ----
  
  declmods:
  	  nonempty_cv_qualifiers  %prec EMPTY
! 		{ $$.lookups = NULL_TREE; TREE_STATIC ($$.t) = 1; }
  	| SCSPEC
! 		{
! 		  $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
! 		  $$.new_type_flag = 0; $$.lookups = NULL_TREE;
! 		}
  	| declmods CV_QUALIFIER
! 		{
! 		  $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
! 		  TREE_STATIC ($$.t) = 1;
! 		}
  	| declmods SCSPEC
! 		{
! 		  if (extra_warnings && TREE_STATIC ($$.t))
  		    warning ("`%s' is not at beginning of declaration",
  			     IDENTIFIER_POINTER ($2));
! 		  $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
! 		  TREE_STATIC ($$.t) = TREE_STATIC ($1.t);
! 		}
  	| declmods attributes
! 		{ $$.t = hash_tree_cons ($2, NULL_TREE, $1.t); }
  	| attributes  %prec EMPTY
! 		{
! 		  $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
! 		  $$.new_type_flag = 0; $$.lookups = NULL_TREE;
! 		}
  	;
  
  /* Used instead of declspecs where storage classes are not allowed
*************** typed_typespecs:
*** 1763,1769 ****
  		  $$.new_type_flag = $1.new_type_flag; }
  	| nonempty_cv_qualifiers typespec reserved_typespecquals
  		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
! 		  $$.new_type_flag = $1.new_type_flag; }
  	;
  
  reserved_typespecquals:
--- 1779,1785 ----
  		  $$.new_type_flag = $1.new_type_flag; }
  	| nonempty_cv_qualifiers typespec reserved_typespecquals
  		{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t)); 
! 		  $$.new_type_flag = $2.new_type_flag; }
  	;
  
  reserved_typespecquals:
*************** reserved_typespecquals:
*** 1779,1798 ****
  
  typespec:
  	  structsp
  	| TYPESPEC  %prec EMPTY
! 		{ $$.t = $1; $$.new_type_flag = 0; }
  	| complete_type_name
! 		{ $$.t = $1; $$.new_type_flag = 0; }
  	| TYPEOF '(' expr ')'
  		{ $$.t = finish_typeof ($3);
! 		  $$.new_type_flag = 0; }
  	| TYPEOF '(' type_id ')'
  		{ $$.t = groktypename ($3.t);
! 		  $$.new_type_flag = 0; }
  	| SIGOF '(' expr ')'
  		{ tree type = TREE_TYPE ($3);
  
!                   $$.new_type_flag = 0;
  		  if (IS_AGGR_TYPE (type))
  		    {
  		      sorry ("sigof type specifier");
--- 1795,1815 ----
  
  typespec:
  	  structsp
+ 	  	{ $$.lookups = NULL_TREE; }
  	| TYPESPEC  %prec EMPTY
! 		{ $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
  	| complete_type_name
! 		{ $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
  	| TYPEOF '(' expr ')'
  		{ $$.t = finish_typeof ($3);
! 		  $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
  	| TYPEOF '(' type_id ')'
  		{ $$.t = groktypename ($3.t);
! 		  $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
  	| SIGOF '(' expr ')'
  		{ tree type = TREE_TYPE ($3);
  
!                   $$.new_type_flag = 0; $$.lookups = NULL_TREE;
  		  if (IS_AGGR_TYPE (type))
  		    {
  		      sorry ("sigof type specifier");
*************** typespec:
*** 1807,1813 ****
  	| SIGOF '(' type_id ')'
  		{ tree type = groktypename ($3.t);
  
!                   $$.new_type_flag = 0;
  		  if (IS_AGGR_TYPE (type))
  		    {
  		      sorry ("sigof type specifier");
--- 1824,1830 ----
  	| SIGOF '(' type_id ')'
  		{ tree type = groktypename ($3.t);
  
!                   $$.new_type_flag = 0; $$.lookups = NULL_TREE;
  		  if (IS_AGGR_TYPE (type))
  		    {
  		      sorry ("sigof type specifier");
*************** maybeasm:
*** 1858,1872 ****
  
  initdcl:
  	  declarator maybeasm maybe_attribute '='
! 		{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
! 					  $3, prefix_attributes); }
  	  init
  /* Note how the declaration of the variable is in effect while its init is parsed! */
  		{ cp_finish_decl ($<ttype>5, $6, $2, LOOKUP_ONLYCONVERTING); }
  	| declarator maybeasm maybe_attribute
! 		{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
  					  $3, prefix_attributes);
! 		  cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0); }
  	;
  
          /* This rule assumes a certain configuration of the parser stack.
--- 1875,1895 ----
  
  initdcl:
  	  declarator maybeasm maybe_attribute '='
! 		{
! 		  deferred_type_access_control ();
! 		  $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
! 					  $3, prefix_attributes);
! 		}
  	  init
  /* Note how the declaration of the variable is in effect while its init is parsed! */
  		{ cp_finish_decl ($<ttype>5, $6, $2, LOOKUP_ONLYCONVERTING); }
  	| declarator maybeasm maybe_attribute
! 		{
! 		  deferred_type_access_control ();
! 		  $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
  					  $3, prefix_attributes);
! 		  cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0);
! 		}
  	;
  
          /* This rule assumes a certain configuration of the parser stack.
*************** initdcl:
*** 1877,1883 ****
  	   we need that reduce so we prefer fn.def1 when appropriate.  */
  initdcl0_innards:
  	  maybe_attribute '='
! 		{ parse_decl ($<ttype>-1, $<ttype>-2, $1, 1, &$<ttype>$); }
            /* Note how the declaration of the variable is in effect
  	     while its init is parsed! */ 
  	  init
--- 1900,1907 ----
  	   we need that reduce so we prefer fn.def1 when appropriate.  */
  initdcl0_innards:
  	  maybe_attribute '='
! 		{ parse_decl ($<ttype>-1, $<ftype>-2.t, $<ftype>-2.lookups,
! 			      $1, 1, &$<ttype>$); }
            /* Note how the declaration of the variable is in effect
  	     while its init is parsed! */ 
  	  init
*************** initdcl0_innards:
*** 1885,1891 ****
  				  LOOKUP_ONLYCONVERTING); }
  	| maybe_attribute
  		{ tree d;
! 		  parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
  		  cp_finish_decl (d, NULL_TREE, $<ttype>0, 0); }
    	;
    
--- 1909,1916 ----
  				  LOOKUP_ONLYCONVERTING); }
  	| maybe_attribute
  		{ tree d;
! 		  parse_decl ($<ttype>-1, $<ftype>-2.t, $<ftype>-2.lookups,
! 			      $1, 0, &d);
  		  cp_finish_decl (d, NULL_TREE, $<ttype>0, 0); }
    	;
    
*************** nomods_initdcl0:
*** 1908,1914 ****
              {}
  	| constructor_declarator maybeasm maybe_attribute
  		{ tree d;
! 		  parse_decl($1, NULL_TREE, $3, 0, &d);
  		  cp_finish_decl (d, NULL_TREE, $2, 0); }
  	;
  
--- 1933,1939 ----
              {}
  	| constructor_declarator maybeasm maybe_attribute
  		{ tree d;
! 		  parse_decl ($1, NULL_TREE, NULL_TREE, $3, 0, &d);
  		  cp_finish_decl (d, NULL_TREE, $2, 0); }
  	;
  
*************** component_decl_1:
*** 2431,2437 ****
  	| declmods notype_components
  		{ 
  		  if (!$2)
! 		    grok_x_components ($1);
  		  $$ = NULL_TREE; 
  		}
  	| notype_declarator maybeasm maybe_attribute maybe_init
--- 2456,2462 ----
  	| declmods notype_components
  		{ 
  		  if (!$2)
! 		    grok_x_components ($1.t);
  		  $$ = NULL_TREE; 
  		}
  	| notype_declarator maybeasm maybe_attribute maybe_init
*************** component_decl_1:
*** 2455,2461 ****
  	   parmlist? */
  	| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1, &specs, &attrs);
  		  $$ = grokfield ($2, specs, $5, $3,
  				  build_tree_list ($4, attrs)); }
  	| component_constructor_declarator maybeasm maybe_attribute maybe_init
--- 2480,2486 ----
  	   parmlist? */
  	| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
  		{ tree specs, attrs;
! 		  split_specs_attrs ($1.t, &specs, &attrs);
  		  $$ = grokfield ($2, specs, $5, $3,
  				  build_tree_list ($4, attrs)); }
  	| component_constructor_declarator maybeasm maybe_attribute maybe_init
*************** functional_cast:
*** 2824,2829 ****
--- 2849,2855 ----
  	| typespec fcast_or_absdcl  %prec EMPTY
  		{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
  	;
+ 
  type_name:
  	  TYPENAME
  	| SELFNAME
*************** named_parm:
*** 3529,3535 ****
  		  $$.t = build_tree_list (specs, NULL_TREE); 
  		  $$.new_type_flag = $1.new_type_flag; }
  	| declmods notype_declarator
! 		{ tree specs = strip_attrs ($1);
  		  $$.t = build_tree_list (specs, $2); 
  		  $$.new_type_flag = 0; }
  	;
--- 3555,3561 ----
  		  $$.t = build_tree_list (specs, NULL_TREE); 
  		  $$.new_type_flag = $1.new_type_flag; }
  	| declmods notype_declarator
! 		{ tree specs = strip_attrs ($1.t);
  		  $$.t = build_tree_list (specs, $2); 
  		  $$.new_type_flag = 0; }
  	;
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.151
diff -c -p -r1.151 search.c
*** search.c	2000/02/06 04:27:53	1.151
--- search.c	2000/02/07 20:22:05
*************** friend_accessible_p (scope, type, decl, 
*** 1072,1080 ****
  
    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,
     then we can tell in what context the access is occurring by looking
     at the most derived class along the path indicated by BINFO.  */
--- 1072,1115 ----
  
    return 0;
  }
! 
! /* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
!    This is fairly complex, so here's the design:
! 
!    The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
!      start to process a top-level declaration.
!    As we process the decl-specifier-seq for the declaration, any types we
!      see that might need access control are passed to type_access_control,
!      which defers checking by adding them to type_lookups.
!    When we are done with the decl-specifier-seq, we record the lookups we've
!      seen in the lookups field of the typed_declspecs nonterminal.
!    When we process the first declarator, either in parse_decl or
!      begin_function_definition, we call initial_deferred_type_access_control,
!      which processes any lookups from within that declarator, stores the
!      lookups from the decl-specifier-seq in current_type_lookups, and sets
!      type_lookups to error_mark_node.
!    Subsequent declarators process current_type_lookups again to make sure
!      that the types are accessible to all of the declarators.  Any lookups
!      within subsequent declarators are processed immediately.
!    Within a function, type_lookups is error_mark_node, so all lookups are
!      processed immediately.  */
! 
! void
! type_access_control (type, val)
!      tree type, val;
! {
!   if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
!       || ! DECL_CLASS_SCOPE_P (val))
!     return;
! 
!   if (type_lookups == error_mark_node)
!     enforce_access (type, val);
!   else if (! accessible_p (type, val))
!     type_lookups = tree_cons (type, val, type_lookups);
! }
! 
  /* DECL is a declaration from a base class of TYPE, which was the
!    class used to name DECL.  Return non-zero if, in the current
     context, DECL is accessible.  If TYPE is actually a BINFO node,
     then we can tell in what context the access is occurring by looking
     at the most derived class along the path indicated by BINFO.  */
*************** accessible_p (type, decl)
*** 1101,1110 ****
    if (!TYPE_P (context_for_name_lookup (decl)))
      return 1;
  
-   /* We don't do access control for types yet.  */
-   if (TREE_CODE (decl) == TYPE_DECL)
-     return 1;
- 
    if (!TYPE_P (type))
      {
        binfo = type;
--- 1136,1141 ----
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.122
diff -c -p -r1.122 semantics.c
*** semantics.c	2000/01/26 20:51:37	1.122
--- semantics.c	2000/02/07 20:22:07
*************** finish_id_expr (expr)
*** 1690,1706 ****
    return expr;
  }
  
! /* Begin a function defniition declared with DECL_SPECS and
     DECLARATOR.  Returns non-zero if the function-declaration is
     legal.  */
  
  int
! begin_function_definition (decl_specs, declarator)
       tree decl_specs;
       tree declarator;
  {
    tree specs;
    tree attrs;
    split_specs_attrs (decl_specs, &specs, &attrs);
    if (!start_function (specs, declarator, attrs, SF_DEFAULT))
      return 0;
--- 1690,1745 ----
    return expr;
  }
  
! static tree current_type_lookups;
! 
! /* Perform deferred access control for types used in the type of a
!    declaration.  */
! 
! void
! deferred_type_access_control ()
! {
!   tree lookup = current_type_lookups;
! 
!   if (lookup == error_mark_node)
!     return;
! 
!   for (; lookup; lookup = TREE_CHAIN (lookup))
!     enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
! }
! 
! /* Perform deferred access control for types used in the type of a
!    declaration.  Called for the first declarator in a declaration.  */
! 
! void
! initial_deferred_type_access_control (lookups)
!      tree lookups;
! {
!   tree lookup = type_lookups;
! 
!   if (lookup != error_mark_node)
!     for (; lookup != lookups; lookup = TREE_CHAIN (lookup))
!       enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
! 
!   current_type_lookups = lookups;
!   type_lookups = error_mark_node;
!   deferred_type_access_control ();
! }    
! 
! /* Begin a function definition declared with DECL_SPECS and
     DECLARATOR.  Returns non-zero if the function-declaration is
     legal.  */
  
  int
! begin_function_definition (decl_specs, lookups, declarator)
       tree decl_specs;
+      tree lookups;
       tree declarator;
  {
    tree specs;
    tree attrs;
+ 
+   initial_deferred_type_access_control (lookups);
+   
    split_specs_attrs (decl_specs, &specs, &attrs);
    if (!start_function (specs, declarator, attrs, SF_DEFAULT))
      return 0;


More information about the Gcc-patches mailing list