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] Stage 2: Implement access check for template instantiation (3/n)


Hi

In this part 3 patch, duplicate access violation diagnostics
are suppressed.  Such uplicate error is a problem not only in
template but ordinary code.  One example is PR 21312 (which is
fixed by this patch).  Access may be checked during qualified
name lookup and later again while building expression nodes.

Trying to check every use of perform_or_defer_access_check to
figure out whether it is required in a particular situation is
fragile to future changes.  So the approach used is adding
some extra logic to enforce_access.  It remember previously
issued access error and suppress duplicate ones.  Only
invalid access is recorded there so this has negligible effect
on valid codes.

There is a new function added: set_access_errors.  The idea
behind it can be seen in pt.c changes (although it will be
better utilized in a later patch).  When instantiating different
instantiations of the same template, such as A<int> and then
A<char>, the template pattern code has the same source position.
Calling set_access_errors to clear access_errors to NULL
ensures that diagnostics are correctly produced in every
instantiation if necessary.  Note that it also works when
an instantiation, say class B<5>, triggers further instantiation
such as B<4>.

Tested on i686-pc-linux-gnu. OK for the mainline?

--Kriang

2005-05-14  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	Defer access check until template instantiation 3/n
	PR c++/21312
	* call.c (access_errors): New static variable.
	(set_access_errors): New functions.
	(enforce_access): Don't issue duplicate access error diagnostic.
	* cp-tree.h (set_access_errors): Add declaration.
	* parser.c (c_parse_file): Use set_access_errors.
	* pt.c (instantiate_class_template, instantiate_decl): Likewise.



diff -cprN gcc-main-save/gcc/cp/call.c gcc-main-new/gcc/cp/call.c
*** gcc-main-save/gcc/cp/call.c	2005-05-08 16:24:11.000000000 +0700
--- gcc-main-new/gcc/cp/call.c	2005-05-14 00:31:44.108235288 +0700
*************** struct conversion {
*** 121,126 ****
--- 121,128 ----
  static struct obstack conversion_obstack;
  static bool conversion_obstack_initialized;
  
+ static GTY(()) tree access_errors;
+ 
  static struct z_candidate * tourney (struct z_candidate *);
  static int equal_functions (tree, tree);
  static int joust (struct z_candidate *, struct z_candidate *, bool);
*************** build_op_delete_call (enum tree_code cod
*** 4040,4045 ****
--- 4042,4057 ----
    return error_mark_node;
  }
  
+ /* Set ACCESS_ERROR so that subsequent failed access checking
+    recorded in T are not diagnosed.  */
+ 
+ tree set_access_errors (tree t)
+ {
+   tree r = access_errors;
+   access_errors = t;
+   return r;
+ }
+ 
  /* If the current scope isn't allowed to access DECL along
     BASETYPE_PATH, give an error.  The most derived class in
     BASETYPE_PATH is the one used to qualify DECL.  */
*************** enforce_access (tree basetype_path, tree
*** 4051,4056 ****
--- 4063,4078 ----
    
    if (!accessible_p (basetype_path, decl, true))
      {
+       tree *t = find_access_checks_append_location (&access_errors,
+ 						    basetype_path,
+ 						    decl,
+ 						    input_location);
+       if (t == NULL)
+ 	/* Diagnostic is already issued.  */
+ 	return false;
+       access_errors = build_access (basetype_path, decl, access_errors,
+ 				    input_location);
+ 
        if (TREE_PRIVATE (decl))
  	cp_error_at ("%q+#D is private", decl);
        else if (TREE_PROTECTED (decl))
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	2005-05-14 00:26:47.000000000 +0700
--- gcc-main-new/gcc/cp/cp-tree.h	2005-05-14 00:41:43.814066144 +0700
*************** extern tree build_op_delete_call (enum t
*** 3628,3633 ****
--- 3628,3634 ----
  extern bool can_convert (tree, tree);
  extern bool can_convert_arg (tree, tree, tree);
  extern bool can_convert_arg_bad (tree, tree, tree);
+ extern tree set_access_errors (tree);
  extern bool enforce_access (tree, tree);
  extern tree convert_default_arg (tree, tree, tree, int);
  extern tree convert_arg_to_ellipsis (tree);
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c	2005-05-14 00:26:47.000000000 +0700
--- gcc-main-new/gcc/cp/parser.c	2005-05-14 00:36:31.465550336 +0700
*************** c_parse_file (void)
*** 16077,16084 ****
--- 16077,16087 ----
    already_called = true;
  
    the_parser = cp_parser_new ();
+ 
    push_deferring_access_checks (flag_access_control
  				? dk_no_deferred : dk_no_check);
+   set_access_errors (NULL_TREE);
+ 
    error_occurred = cp_parser_translation_unit (the_parser);
    the_parser = NULL;
  }
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c	2005-05-08 22:28:47.000000000 +0700
--- gcc-main-new/gcc/cp/pt.c	2005-05-14 00:40:40.967620256 +0700
*************** instantiate_class_template (tree type)
*** 5416,5421 ****
--- 5416,5422 ----
    tree typedecl;
    tree pbinfo;
    tree base_list;
+   tree save_access_errors;
    
    if (type == error_mark_node)
      return error_mark_node;
*************** instantiate_class_template (tree type)
*** 5471,5476 ****
--- 5472,5479 ----
       the process of being defined.  */
    TYPE_BEING_DEFINED (type) = 1;
  
+   /* Prevent duplicate access check error message.  */
+   save_access_errors = set_access_errors (NULL_TREE);
    /* We may be in the middle of deferred access check.  Disable
       it now.  */
    push_deferring_access_checks (dk_no_deferred);
*************** instantiate_class_template (tree type)
*** 5882,5887 ****
--- 5885,5891 ----
    popclass ();
    pop_from_top_level ();
    pop_deferring_access_checks ();
+   set_access_errors (save_access_errors);
    pop_tinst_level ();
  
    /* The vtable for a template class can be emitted in any translation
*************** instantiate_decl (tree d, int defer_ok, 
*** 11325,11330 ****
--- 11329,11335 ----
    tree code_pattern;
    tree spec;
    tree gen_tmpl;
+   tree save_access_errors;
    int pattern_defined;
    int need_push;
    location_t saved_loc = input_location;
*************** instantiate_decl (tree d, int defer_ok, 
*** 11373,11378 ****
--- 11378,11385 ----
  
    timevar_push (TV_PARSE);
  
+   /* Prevent duplicate access check error message.  */
+   save_access_errors = set_access_errors (NULL_TREE);
    /* We may be in the middle of deferred access check.  Disable it now.  */
    push_deferring_access_checks (dk_no_deferred);
  
*************** instantiate_decl (tree d, int defer_ok, 
*** 11589,11594 ****
--- 11596,11602 ----
  out:
    input_location = saved_loc;
    pop_deferring_access_checks ();
+   set_access_errors (save_access_errors);
    pop_tinst_level ();
  
    timevar_pop (TV_PARSE);

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