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] Remove check_access_p in parser, fix PR9554 (a regression)


Hi

The new parser currently passes an `check_access_p' flag as an argument
to various functions during parsing.  Failure to do so in certain
places will result in compiler bug like the one reported in PR9554.
This bug is due to access_check omission in the parameter of
cp_parser_template_id.

Rather than having to pass the flag around in the parser, one approach
would be using the `scope_chain->access_check' mechanism.  However,
this can be merged with the deferred access checking functions because
there are actually 3 different working checking modes we have to deal 
with: immediate check, deferred check, and no check.  So I propose
to extend the deferred access checking mechanism to work in all 3 modes.
With the patch, we simply call
	push_deferring_access_checks (dk_no_check);
to turn off checking in the parser, and call
	pop_deferring_access_checks ();
after finishing parsing the declaration.

Merging the `scope_chain->access_check' used elsewhere in the frontend 
into deferred checking functions will be addressed in a future patch.  
The `scope_chain' structure just doesn't look like the right place to 
control access checking.

Bootstrapped and tested on i686-pc-linux-gnu.  OK to commit to
the main trunk?

--Kriang


2003-04-07  Kriang Lerdsuwanakij  <lerdsuwa at users dot sourceforge dot net>

	PR c++/9554
	* parser.c (cp_parser_class_name): Remove check_access parameter.
	All caller adjusted.  Update declaration.
	(cp_parser_lookup_name): Likewise.
	* semantics.c (push_deferring_access_checks): Change parameter type
	to enum deferring_kind.  All caller adjusted.
	(resume_deferring_access_checks): Adjust to use new enum.
	(stop_deferring_access_checks): Likewise.
	(perform_or_defer_access_check): Likewise.
	* cp-tree.h (deferring_kind): New enum.
	(deferred_access): Adjust field type.
	(push_deferring_access_checks): Update declaration.

2003-04-07  Kriang Lerdsuwanakij  <lerdsuwa at users dot sourceforge dot net>

	PR c++/9554
	* g++.dg/parse/access1.C: New test.


diff -cprN gcc-main-save/gcc/cp/cp-tree.h gcc-main-new/gcc/cp/cp-tree.h
*** gcc-main-save/gcc/cp/cp-tree.h	Sun Apr  6 20:30:41 2003
--- gcc-main-new/gcc/cp/cp-tree.h	Mon Apr  7 17:09:28 2003
*************** typedef enum base_access {
*** 3050,3055 ****
--- 3050,3062 ----
    ba_quiet = 4     /* Do not issue error messages (bit mask).  */
  } base_access;
  
+ /* The various kinds of access check during parsing.  */
+ typedef enum deferring_kind {
+   dk_no_deferred = 0, /* Check access immediately */
+   dk_deferred = 1,    /* Deferred check */
+   dk_no_check = 2     /* No access check */
+ } deferring_kind;
+ 
  /* The kind of base we can find, looking in a class hierarchy.
     Values <0 indicate we failed.  */
  typedef enum base_kind {
*************** typedef struct deferred_access GTY(())
*** 3108,3115 ****
       name being looked up; the TREE_VALUE is the DECL to which the
       name was resolved.  */
    tree deferred_access_checks;
!   /* TRUE iff we are deferring access checks.  */
!   bool deferring_access_checks_p;
    /* The next deferred access data in stack or linked-list.  */
    struct deferred_access *next;
  } deferred_access;
--- 3115,3122 ----
       name being looked up; the TREE_VALUE is the DECL to which the
       name was resolved.  */
    tree deferred_access_checks;
!   /* The current mode of access checks.  */
!   enum deferring_kind deferring_access_checks_kind;
    /* The next deferred access data in stack or linked-list.  */
    struct deferred_access *next;
  } deferred_access;
*************** extern tree copied_binfo			(tree, tree);
*** 4063,4069 ****
  extern tree original_binfo			(tree, tree);
  
  /* in semantics.c */
! extern void push_deferring_access_checks	(bool defer_p);
  extern void resume_deferring_access_checks	(void);
  extern void stop_deferring_access_checks	(void);
  extern void pop_deferring_access_checks		(void);
--- 4070,4076 ----
  extern tree original_binfo			(tree, tree);
  
  /* in semantics.c */
! extern void push_deferring_access_checks	(deferring_kind);
  extern void resume_deferring_access_checks	(void);
  extern void stop_deferring_access_checks	(void);
  extern void pop_deferring_access_checks		(void);
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c	Sun Mar 30 00:55:57 2003
--- gcc-main-new/gcc/cp/parser.c	Mon Apr  7 17:09:28 2003
*************** static bool cp_parser_ctor_initializer_o
*** 1555,1561 ****
  /* Classes [gram.class] */
  
  static tree cp_parser_class_name
!   (cp_parser *, bool, bool, bool, bool, bool, bool);
  static tree cp_parser_class_specifier
    (cp_parser *);
  static tree cp_parser_class_head
--- 1555,1561 ----
  /* Classes [gram.class] */
  
  static tree cp_parser_class_name
!   (cp_parser *, bool, bool, bool, bool, bool);
  static tree cp_parser_class_specifier
    (cp_parser *);
  static tree cp_parser_class_head
*************** static void cp_parser_label_declaration
*** 1664,1670 ****
  /* Utility Routines */
  
  static tree cp_parser_lookup_name
!   (cp_parser *, tree, bool, bool, bool, bool);
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
--- 1664,1670 ----
  /* Utility Routines */
  
  static tree cp_parser_lookup_name
!   (cp_parser *, tree, bool, bool, bool);
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
*************** cp_parser_diagnose_invalid_type_name (cp
*** 1924,1930 ****
      {
        tree name;
  
!       /* If parsing tenatively, we should commit; we really are
  	 looking at a declaration.  */
        /* Consume the first identifier.  */
        name = cp_lexer_consume_token (parser->lexer)->value;
--- 1924,1930 ----
      {
        tree name;
  
!       /* If parsing tentatively, we should commit; we really are
  	 looking at a declaration.  */
        /* Consume the first identifier.  */
        name = cp_lexer_consume_token (parser->lexer)->value;
*************** cp_parser_unqualified_id (cp_parser* par
*** 3082,3088 ****
  					      /*typename_keyword_p=*/false,
  					      /*template_keyword_p=*/false,
  					      /*type_p=*/false,
- 					      /*check_access_p=*/true,
  					      /*check_dependency=*/false,
  					      /*class_head_p=*/false);
  	    if (cp_parser_parse_definitely (parser))
--- 3082,3087 ----
*************** cp_parser_unqualified_id (cp_parser* par
*** 3100,3106 ****
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
  				      /*type_p=*/false,
- 				      /*check_access_p=*/true,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false);
  	    if (cp_parser_parse_definitely (parser))
--- 3099,3104 ----
*************** cp_parser_unqualified_id (cp_parser* par
*** 3118,3124 ****
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
  				      /*type_p=*/false,
- 				      /*check_access_p=*/true,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false);
  	    if (cp_parser_parse_definitely (parser))
--- 3116,3121 ----
*************** cp_parser_unqualified_id (cp_parser* par
*** 3133,3139 ****
  				  /*typename_keyword_p=*/false,
  				  /*template_keyword_p=*/false,
  				  /*type_p=*/false,
- 				  /*check_access_p=*/true,
  				  /*check_dependency=*/false,
  				  /*class_head_p=*/false);
  	/* If an error occurred, assume that the name of the
--- 3130,3135 ----
*************** cp_parser_nested_name_specifier_opt (cp_
*** 3233,3239 ****
    else
      start = -1;
  
!   push_deferring_access_checks (true);
  
    while (true)
      {
--- 3229,3235 ----
    else
      start = -1;
  
!   push_deferring_access_checks (dk_deferred);
  
    while (true)
      {
*************** cp_parser_class_or_namespace_name (cp_pa
*** 3486,3492 ****
  				typename_keyword_p,
  				template_keyword_p,
  				type_p,
- 				/*check_access_p=*/true,
  				check_dependency_p,
  				/*class_head_p=*/false);
    /* If that didn't work, try for a namespace-name.  */
--- 3482,3487 ----
*************** cp_parser_simple_declaration (cp_parser*
*** 6536,6542 ****
    /* Defer access checks until we know what is being declared; the
       checks for names appearing in the decl-specifier-seq should be
       done as if we were in the scope of the thing being declared.  */
!   push_deferring_access_checks (true);
  
    /* Parse the decl-specifier-seq.  We have to keep track of whether
       or not the decl-specifier-seq declares a named class or
--- 6531,6537 ----
    /* Defer access checks until we know what is being declared; the
       checks for names appearing in the decl-specifier-seq should be
       done as if we were in the scope of the thing being declared.  */
!   push_deferring_access_checks (dk_deferred);
  
    /* Parse the decl-specifier-seq.  We have to keep track of whether
       or not the decl-specifier-seq declares a named class or
*************** cp_parser_simple_declaration (cp_parser*
*** 6565,6571 ****
       where "T" should name a type -- but does not.  */
    if (cp_parser_diagnose_invalid_type_name (parser))
      {
!       /* If parsing tenatively, we should commit; we really are
  	 looking at a declaration.  */
        cp_parser_commit_to_tentative_parse (parser);
        /* Give up.  */
--- 6560,6566 ----
       where "T" should name a type -- but does not.  */
    if (cp_parser_diagnose_invalid_type_name (parser))
      {
!       /* If parsing tentatively, we should commit; we really are
  	 looking at a declaration.  */
        cp_parser_commit_to_tentative_parse (parser);
        /* Give up.  */
*************** cp_parser_mem_initializer_id (cp_parser*
*** 7313,7319 ****
  				 /*typename_keyword_p=*/true,
  				 /*template_keyword_p=*/false,
  				 /*type_p=*/false,
- 				 /*check_access_p=*/true,
  				 /*check_dependency_p=*/true,
  				 /*class_head_p=*/false);
    /* Otherwise, we could also be looking for an ordinary identifier.  */
--- 7308,7313 ----
*************** cp_parser_mem_initializer_id (cp_parser*
*** 7323,7329 ****
  			     /*typename_keyword_p=*/true,
  			     /*template_keyword_p=*/false,
  			     /*type_p=*/false,
- 			     /*check_access_p=*/true,
  			     /*check_dependency_p=*/true,
  			     /*class_head_p=*/false);
    /* If we found one, we're done.  */
--- 7317,7322 ----
*************** cp_parser_template_id (cp_parser *parser
*** 7943,7949 ****
    else
      start_of_id = -1;
  
!   push_deferring_access_checks (true);
  
    /* Parse the template-name.  */
    template = cp_parser_template_name (parser, template_keyword_p,
--- 7936,7942 ----
    else
      start_of_id = -1;
  
!   push_deferring_access_checks (dk_deferred);
  
    /* Parse the template-name.  */
    template = cp_parser_template_name (parser, template_keyword_p,
*************** cp_parser_template_name (cp_parser* pars
*** 8117,8123 ****
  
    /* Look up the name.  */
    decl = cp_parser_lookup_name (parser, identifier,
- 				/*check_access=*/true,
  				/*is_type=*/false,
  				/*is_namespace=*/false,
  				check_dependency_p);
--- 8110,8115 ----
*************** cp_parser_explicit_instantiation (cp_par
*** 8344,8350 ****
      }
    /* We're done with the instantiation.  */
    end_explicit_instantiation ();
!   /* Trun access control back on.  */
    scope_chain->check_access = flag_access_control;
  
    cp_parser_consume_semicolon_at_end_of_statement (parser);
--- 8336,8342 ----
      }
    /* We're done with the instantiation.  */
    end_explicit_instantiation ();
!   /* Turn access control back on.  */
    scope_chain->check_access = flag_access_control;
  
    cp_parser_consume_semicolon_at_end_of_statement (parser);
*************** cp_parser_type_name (cp_parser* parser)
*** 8688,8694 ****
  				    /*typename_keyword_p=*/false,
  				    /*template_keyword_p=*/false,
  				    /*type_p=*/false,
- 				    /*check_access_p=*/true,
  				    /*check_dependency_p=*/true,
  				    /*class_head_p=*/false);
    /* If it's not a class-name, keep looking.  */
--- 8680,8685 ----
*************** cp_parser_elaborated_type_specifier (cp_
*** 8847,8853 ****
  	     types, so we set IS_TYPE to TRUE when calling
  	     cp_parser_lookup_name.  */
  	  decl = cp_parser_lookup_name (parser, identifier, 
- 					/*check_access=*/true,
  					/*is_type=*/true,
  					/*is_namespace=*/false,
  					/*check_dependency=*/true);
--- 8838,8843 ----
*************** cp_parser_namespace_name (cp_parser* par
*** 9115,9121 ****
       function if the token after the name is the scope resolution
       operator.)  */
    namespace_decl = cp_parser_lookup_name (parser, identifier,
- 					  /*check_access=*/true,
  					  /*is_type=*/false,
  					  /*is_namespace=*/true,
  					  /*check_dependency=*/true);
--- 9105,9110 ----
*************** cp_parser_function_definition (cp_parser
*** 10958,10964 ****
       function is being defined.  There is no need to do this for the
       definition of member functions; we cannot be defining a member
       from another class.  */
!   push_deferring_access_checks (!member_p);
  
    /* Parse the decl-specifier-seq.  */
    decl_specifiers 
--- 10947,10953 ----
       function is being defined.  There is no need to do this for the
       definition of member functions; we cannot be defining a member
       from another class.  */
!   push_deferring_access_checks (member_p ? dk_no_check: dk_deferred);
  
    /* Parse the decl-specifier-seq.  */
    decl_specifiers 
*************** cp_parser_initializer_list (cp_parser* p
*** 11302,11311 ****
     keyword has been used to indicate that the name that appears next
     is a template.  TYPE_P is true iff the next name should be treated
     as class-name, even if it is declared to be some other kind of name
!    as well.  The accessibility of the class-name is checked iff
!    CHECK_ACCESS_P is true.  If CHECK_DEPENDENCY_P is FALSE, names are
!    looked up in dependent scopes.  If CLASS_HEAD_P is TRUE, this class
!    is the class being defined in a class-head.
  
     Returns the TYPE_DECL representing the class.  */
  
--- 11291,11299 ----
     keyword has been used to indicate that the name that appears next
     is a template.  TYPE_P is true iff the next name should be treated
     as class-name, even if it is declared to be some other kind of name
!    as well.  If CHECK_DEPENDENCY_P is FALSE, names are looked up in
!    dependent scopes.  If CLASS_HEAD_P is TRUE, this class is the class
!    being defined in a class-head.
  
     Returns the TYPE_DECL representing the class.  */
  
*************** cp_parser_class_name (cp_parser *parser,
*** 11314,11320 ****
  		      bool typename_keyword_p, 
  		      bool template_keyword_p, 
  		      bool type_p,
- 		      bool check_access_p,
  		      bool check_dependency_p,
  		      bool class_head_p)
  {
--- 11302,11307 ----
*************** cp_parser_class_name (cp_parser *parser,
*** 11369,11375 ****
  	    type_p = true;
  	  /* Look up the name.  */
  	  decl = cp_parser_lookup_name (parser, identifier, 
- 					check_access_p,
  					type_p,
  					/*is_namespace=*/false,
  					check_dependency_p);
--- 11356,11361 ----
*************** cp_parser_class_specifier (cp_parser* pa
*** 11435,11441 ****
    bool nested_name_specifier_p;
    unsigned saved_num_template_parameter_lists;
  
!   push_deferring_access_checks (false);  
  
    /* Parse the class-head.  */
    type = cp_parser_class_head (parser,
--- 11421,11427 ----
    bool nested_name_specifier_p;
    unsigned saved_num_template_parameter_lists;
  
!   push_deferring_access_checks (dk_no_deferred);
  
    /* Parse the class-head.  */
    type = cp_parser_class_head (parser,
*************** cp_parser_class_head (cp_parser* parser,
*** 11636,11641 ****
--- 11622,11629 ----
    if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
      qualified_p = true;
  
+   push_deferring_access_checks (dk_no_check);
+ 
    /* Determine the name of the class.  Begin by looking for an
       optional nested-name-specifier.  */
    nested_name_specifier 
*************** cp_parser_class_head (cp_parser* parser,
*** 11660,11667 ****
             class A { class B; };
             class A::B {};
  	 
- 	 So, we ask cp_parser_class_name not to check accessibility.  
- 
           We do not know if we will see a class-name, or a
  	 template-name.  We look for a class-name first, in case the
  	 class-name is a template-id; if we looked for the
--- 11648,11653 ----
*************** cp_parser_class_head (cp_parser* parser,
*** 11671,11677 ****
  				   /*typename_keyword_p=*/false,
  				   /*template_keyword_p=*/false,
  				   /*type_p=*/true,
- 				   /*check_access_p=*/false,
  				   /*check_dependency_p=*/false,
  				   /*class_head_p=*/true);
        /* If that didn't work, ignore the nested-name-specifier.  */
--- 11657,11662 ----
*************** cp_parser_class_head (cp_parser* parser,
*** 11730,11735 ****
--- 11715,11722 ----
  	}
      }
  
+   pop_deferring_access_checks ();
+ 
    /* If it's not a `:' or a `{' then we can't really be looking at a
       class-head, since a class-head only appears as part of a
       class-specifier.  We have to detect this situation before calling
*************** cp_parser_base_specifier (cp_parser* par
*** 12529,12535 ****
  			       class_scope_p,
  			       template_p,
  			       /*type_p=*/true,
- 			       /*check_access=*/true,
  			       /*check_dependency_p=*/true,
  			       /*class_head_p=*/false);
  
--- 12516,12521 ----
*************** cp_parser_label_declaration (cp_parser* 
*** 13173,13182 ****
     If there was no entity with the indicated NAME, the ERROR_MARK_NODE
     is returned.
  
-    If CHECK_ACCESS is TRUE, then access control is performed on the
-    declaration to which the name resolves, and an error message is
-    issued if the declaration is inaccessible.
- 
     If IS_TYPE is TRUE, bindings that do not refer to types are
     ignored.
  
--- 13159,13164 ----
*************** cp_parser_label_declaration (cp_parser* 
*** 13187,13193 ****
     types.  */
  
  static tree
! cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access, 
  		       bool is_type, bool is_namespace, bool check_dependency)
  {
    tree decl;
--- 13169,13175 ----
     types.  */
  
  static tree
! cp_parser_lookup_name (cp_parser *parser, tree name, 
  		       bool is_type, bool is_namespace, bool check_dependency)
  {
    tree decl;
*************** cp_parser_lookup_name (cp_parser *parser
*** 13355,13361 ****
  
       During an explicit instantiation, access is not checked at all,
       as per [temp.explicit].  */
!   if (check_access && scope_chain->check_access && DECL_P (decl))
      {
        tree qualifying_type;
        
--- 13337,13343 ----
  
       During an explicit instantiation, access is not checked at all,
       as per [temp.explicit].  */
!   if (DECL_P (decl))
      {
        tree qualifying_type;
        
*************** static tree
*** 13380,13386 ****
  cp_parser_lookup_name_simple (cp_parser* parser, tree name)
  {
    return cp_parser_lookup_name (parser, name, 
- 				/*check_access=*/true,
  				/*is_type=*/false,
  				/*is_namespace=*/false,
  				/*check_dependency=*/true);
--- 13362,13367 ----
*************** cp_parser_constructor_declarator_p (cp_p
*** 13665,13670 ****
--- 13646,13654 ----
    cp_parser_parse_tentatively (parser);
    /* Assume that we are looking at a constructor declarator.  */
    constructor_p = true;
+ 
+   push_deferring_access_checks (dk_no_check);
+ 
    /* Look for the optional `::' operator.  */
    cp_parser_global_scope_opt (parser,
  			      /*current_scope_valid_p=*/false);
*************** cp_parser_constructor_declarator_p (cp_p
*** 13700,13711 ****
  					/*typename_keyword_p=*/false,
  					/*template_keyword_p=*/false,
  					/*type_p=*/false,
- 					/*check_access_p=*/false,
  					/*check_dependency_p=*/false,
  					/*class_head_p=*/false);
        /* If there was no class-name, then this is not a constructor.  */
        constructor_p = !cp_parser_error_occurred (parser);
      }
    /* If we're still considering a constructor, we have to see a `(',
       to begin the parameter-declaration-clause, followed by either a
       `)', an `...', or a decl-specifier.  We need to check for a
--- 13684,13697 ----
  					/*typename_keyword_p=*/false,
  					/*template_keyword_p=*/false,
  					/*type_p=*/false,
  					/*check_dependency_p=*/false,
  					/*class_head_p=*/false);
        /* If there was no class-name, then this is not a constructor.  */
        constructor_p = !cp_parser_error_occurred (parser);
      }
+ 
+   pop_deferring_access_checks ();
+ 
    /* If we're still considering a constructor, we have to see a `(',
       to begin the parameter-declaration-clause, followed by either a
       `)', an `...', or a decl-specifier.  We need to check for a
*************** cp_parser_single_declaration (cp_parser*
*** 13969,13975 ****
       whether it will be a function-definition.  */
    cp_parser_parse_tentatively (parser);
    /* Defer access checks until we know what is being declared.  */
!   push_deferring_access_checks (true);
  
    /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
       alternative.  */
--- 13955,13961 ----
       whether it will be a function-definition.  */
    cp_parser_parse_tentatively (parser);
    /* Defer access checks until we know what is being declared.  */
!   push_deferring_access_checks (dk_deferred);
  
    /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
       alternative.  */
*************** cp_parser_parse_tentatively (cp_parser* 
*** 14559,14565 ****
    /* In order to avoid repetitive access control error messages,
       access checks are queued up until we are no longer parsing
       tentatively.  */
!   push_deferring_access_checks (true);
  }
  
  /* Commit to the currently active tentative parse.  */
--- 14545,14551 ----
    /* In order to avoid repetitive access control error messages,
       access checks are queued up until we are no longer parsing
       tentatively.  */
!   push_deferring_access_checks (dk_deferred);
  }
  
  /* Commit to the currently active tentative parse.  */
*************** yyparse (void)
*** 14679,14685 ****
    bool error_occurred;
  
    the_parser = cp_parser_new ();
!   push_deferring_access_checks (false);
    error_occurred = cp_parser_translation_unit (the_parser);
    the_parser = NULL;
    
--- 14665,14671 ----
    bool error_occurred;
  
    the_parser = cp_parser_new ();
!   push_deferring_access_checks (dk_no_deferred);
    error_occurred = cp_parser_translation_unit (the_parser);
    the_parser = NULL;
    
diff -cprN gcc-main-save/gcc/cp/semantics.c gcc-main-new/gcc/cp/semantics.c
*** gcc-main-save/gcc/cp/semantics.c	Sun Mar  9 21:21:31 2003
--- gcc-main-new/gcc/cp/semantics.c	Mon Apr  7 17:09:28 2003
*************** static tree clear_decl_rtl PARAMS ((tree
*** 79,84 ****
--- 79,135 ----
        (SUBSTMT) = (COND);				\
    } while (0)
  
+ /* Deferred Access Checking Overview
+    ---------------------------------
+ 
+    Most C++ expressions and declarations require access checking
+    to be performed during parsing.  However, in several cases,
+    this has to be treated differently.
+ 
+    For member declarations, access checking has to be deferred
+    until more information about the declaration is known.  For
+    example:
+ 
+      class A {
+          typedef int X;
+        public:
+          X f();
+      };
+ 
+      A::X A::f();
+      A::X g();
+ 
+    When we are parsing the function return type `A::X', we don't
+    really know if this is allowed until we parse the function name.
+ 
+    Furthermore, some contexts require that access checking is
+    never performed at all.  These include class heads, and template
+    instantiations.
+ 
+    Typical use of access checking functions is described here:
+    
+    1. When we enter a context that requires certain access checking
+       mode, the function `push_deferring_access_checks' is called with
+       DEFERRING argument specifying the desired mode.  Access checking
+       may be performed immediately (dk_no_deferred), deferred
+       (dk_deferred), or not performed (dk_no_check).
+ 
+    2. When a declaration such as a type, or a variable, is encountered,
+       the function `perform_or_defer_access_check' is called.  It
+       maintains a TREE_LIST of all deferred checks.
+ 
+    3. The global `current_class_type' or `current_function_decl' is then
+       setup by the parser.  `enforce_access' relies on these information
+       to check access.
+ 
+    4. Upon exiting the context mentioned in step 1,
+       `perform_deferred_access_checks' is called to check all declaration
+       stored in the TREE_LIST.   `pop_deferring_access_checks' is then
+       called to restore the previous access checking mode.
+ 
+       In case of parsing error, we simply call `pop_deferring_access_checks'
+       without `perform_deferred_access_checks'.  */
+ 
  /* Data for deferred access checking.  */
  static GTY(()) deferred_access *deferred_access_stack;
  static GTY(()) deferred_access *deferred_access_free_list;
*************** static GTY(()) deferred_access *deferred
*** 86,92 ****
  /* Save the current deferred access states and start deferred
     access checking iff DEFER_P is true.  */
  
! void push_deferring_access_checks (bool deferring_p)
  {
    deferred_access *d;
  
--- 137,143 ----
  /* Save the current deferred access states and start deferred
     access checking iff DEFER_P is true.  */
  
! void push_deferring_access_checks (deferring_kind deferring)
  {
    deferred_access *d;
  
*************** void push_deferring_access_checks (bool 
*** 101,107 ****
  
    d->next = deferred_access_stack;
    d->deferred_access_checks = NULL_TREE;
!   d->deferring_access_checks_p = deferring_p;
    deferred_access_stack = d;
  }
  
--- 152,158 ----
  
    d->next = deferred_access_stack;
    d->deferred_access_checks = NULL_TREE;
!   d->deferring_access_checks_kind = deferring;
    deferred_access_stack = d;
  }
  
*************** void push_deferring_access_checks (bool 
*** 110,123 ****
  
  void resume_deferring_access_checks (void)
  {
!   deferred_access_stack->deferring_access_checks_p = true;
  }
  
  /* Stop deferring access checks.  */
  
  void stop_deferring_access_checks (void)
  {
!   deferred_access_stack->deferring_access_checks_p = false;
  }
  
  /* Discard the current deferred access checks and restore the
--- 161,176 ----
  
  void resume_deferring_access_checks (void)
  {
!   if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
!     deferred_access_stack->deferring_access_checks_kind = dk_deferred;
  }
  
  /* Stop deferring access checks.  */
  
  void stop_deferring_access_checks (void)
  {
!   if (deferred_access_stack->deferring_access_checks_kind == dk_deferred)
!     deferred_access_stack->deferring_access_checks_kind = dk_no_deferred;
  }
  
  /* Discard the current deferred access checks and restore the
*************** void perform_or_defer_access_check (tree
*** 199,209 ****
    tree check;
  
    /* If we are not supposed to defer access checks, just check now.  */
!   if (!deferred_access_stack->deferring_access_checks_p)
      {
        enforce_access (class_type, decl);
        return;
      }
  
    /* See if we are already going to perform this check.  */
    for (check = deferred_access_stack->deferred_access_checks;
--- 252,265 ----
    tree check;
  
    /* If we are not supposed to defer access checks, just check now.  */
!   if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
      {
        enforce_access (class_type, decl);
        return;
      }
+   /* Exit if we are in a context that no access checking is performed.  */
+   else if (deferred_access_stack->deferring_access_checks_kind == dk_no_check)
+     return;
  
    /* See if we are already going to perform this check.  */
    for (check = deferred_access_stack->deferred_access_checks;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/parse/access1.C gcc-main-new/gcc/testsuite/g++.dg/parse/access1.C
*** gcc-main-save/gcc/testsuite/g++.dg/parse/access1.C	Thu Jan  1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/parse/access1.C	Mon Apr  7 17:24:32 2003
***************
*** 0 ****
--- 1,13 ----
+ // { dg-do compile }
+ 
+ // Origin: Volker Lukas <vlukas at gmx dot de>
+ 
+ // PR c++/9554: Access checking for template ID as class head.
+ 
+ class enclose
+ {
+   template<typename T> struct enclosed;
+ };
+ 
+ template <>
+ struct enclose::enclosed<int>;


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