re PR c++/9252 ([New parser] Errors due to legally used "typename")
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Sat, 10 May 2003 11:29:53 +0000 (11:29 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Sat, 10 May 2003 11:29:53 +0000 (11:29 +0000)
PR c++/9252
* cp-tree.h (saved_scope): Remove check_access field.
(tsubst_flags_t): Remove tf_parsing.
* decl.c (maybe_push_to_top_level): Don't initialize
scope_chain->check_access.
(make_typename_type, make_unbound_class_template): Don't use
tf_parsing.
(register_dtor_fn): Use push/pop_deferring_access_checks
instead of scope_chain->check_access.
* method.c (use_thunk): Likewise.
* parser.c (cp_parser_explicit_instantiation
(cp_parser_constructor_declarator_p): Don't call
push/pop_deferring_access_checks here.
(cp_parser_template_argument, cp_parser_class_name): Don't use
tf_parsing.
(yyparse): Check flag_access_control.
* pt.c (instantiate_class_template): Call
push/pop_deferring_access_checks.
* semantics.c (push_deferring_access_checks): Propagate
dk_no_check.
(perform_or_defer_access_check): Make sure basetype_path is
a type before comparison.
* call.c (build_op_delete_call, build_over_call): Use
perform_or_defer_access_check.
* class.c (alter_access): Likewise.
* init.c (build_offset_ref): Likewise.
* lex.c (do_identifier): Likewise.
* method.c (hack_identifier): Likewise.
* search.c (lookup_member): Likewise.
* semantics.c (finish_non_static_data_member): Likewise.
(simplify_aggr_init_exprs_r): Use push/pop_deferring_access_checks
instead of flag_access_control.

* g++.dg/parse/access8.C: New test.
* g++.dg/parse/access9.C: New test.

From-SVN: r66660

15 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/access8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/access9.C [new file with mode: 0644]

index 2087066..81645ce 100644 (file)
@@ -1,5 +1,40 @@
 2003-05-10  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
+       PR c++/9252
+       * cp-tree.h (saved_scope): Remove check_access field.
+       (tsubst_flags_t): Remove tf_parsing.
+       * decl.c (maybe_push_to_top_level): Don't initialize
+       scope_chain->check_access.
+       (make_typename_type, make_unbound_class_template): Don't use
+       tf_parsing.
+       (register_dtor_fn): Use push/pop_deferring_access_checks
+       instead of scope_chain->check_access.
+       * method.c (use_thunk): Likewise.
+       * parser.c (cp_parser_explicit_instantiation
+       (cp_parser_constructor_declarator_p): Don't call
+       push/pop_deferring_access_checks here.
+       (cp_parser_template_argument, cp_parser_class_name): Don't use
+       tf_parsing.
+       (yyparse): Check flag_access_control.
+       * pt.c (instantiate_class_template): Call
+       push/pop_deferring_access_checks.
+       * semantics.c (push_deferring_access_checks): Propagate
+       dk_no_check.
+       (perform_or_defer_access_check): Make sure basetype_path is
+       a type before comparison.
+       * call.c (build_op_delete_call, build_over_call): Use
+       perform_or_defer_access_check.
+       * class.c (alter_access): Likewise.
+       * init.c (build_offset_ref): Likewise.
+       * lex.c (do_identifier): Likewise.
+       * method.c (hack_identifier): Likewise.
+       * search.c (lookup_member): Likewise.
+       * semantics.c (finish_non_static_data_member): Likewise.
+       (simplify_aggr_init_exprs_r): Use push/pop_deferring_access_checks
+       instead of flag_access_control.
+
+2003-05-10  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
        PR c++/9554
        * parser.c (cp_parser_class_name): Remove check_access parameter.
        All caller adjusted.  Update declaration.
index 5d7e3df..84bdcd6 100644 (file)
@@ -4062,7 +4062,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
       /* If the FN is a member function, make sure that it is
         accessible.  */
       if (DECL_CLASS_SCOPE_P (fn))
-       enforce_access (type, fn);
+       perform_or_defer_access_check (type, fn);
 
       if (pass == 0)
        args = tree_cons (NULL_TREE, addr, args);
@@ -4513,7 +4513,7 @@ build_over_call (struct z_candidate *cand, int flags)
       joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
 
   if (DECL_FUNCTION_MEMBER_P (fn))
-    enforce_access (cand->access_path, fn);
+    perform_or_defer_access_check (cand->access_path, fn);
 
   if (args && TREE_CODE (args) != TREE_LIST)
     args = build_tree_list (NULL_TREE, args);
index 196815a..c693fdf 100644 (file)
@@ -1086,7 +1086,7 @@ alter_access (tree t, tree fdecl, tree access)
     }
   else
     {
-      enforce_access (t, fdecl);
+      perform_or_defer_access_check (t, fdecl);
       DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
       return 1;
     }
index 89d068a..3398398 100644 (file)
@@ -696,7 +696,6 @@ struct saved_scope GTY(())
   int x_processing_specialization;
   bool x_processing_explicit_instantiation;
   int need_pop_function_context;
-  int check_access;
 
   struct stmt_tree_s x_stmt_tree;
 
@@ -3013,10 +3012,8 @@ typedef enum tsubst_flags_t {
   tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
   tf_keep_type_decl = 1 << 4,  /* retain typedef type decls
                                   (make_typename_type use) */
-  tf_ptrmem_ok = 1 << 5,     /* pointers to member ok (internal
+  tf_ptrmem_ok = 1 << 5      /* pointers to member ok (internal
                                instantiate_type use) */
-  tf_parsing = 1 << 6       /* called from parser
-                               (make_typename_type use) */
 } tsubst_flags_t;
 
 /* The kind of checking we can do looking in a class hierarchy.  */
index 6df2a0b..4bec8a6 100644 (file)
@@ -2242,7 +2242,6 @@ maybe_push_to_top_level (int pseudo)
   s->need_pop_function_context = need_pop;
   s->function_decl = current_function_decl;
   s->last_parms = last_function_parms;
-  s->check_access = flag_access_control;
 
   scope_chain = s;
   current_function_decl = NULL_TREE;
@@ -5481,12 +5480,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
            }
 
          if (complain & tf_error)
-           {
-             if (complain & tf_parsing)
-               perform_or_defer_access_check (context, tmpl);
-             else
-               enforce_access (context, tmpl);
-           }
+           perform_or_defer_access_check (context, tmpl);
 
          return lookup_template_class (tmpl,
                                        TREE_OPERAND (fullname, 1),
@@ -5516,12 +5510,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
                }
 
              if (complain & tf_error)
-               {
-                 if (complain & tf_parsing)
-                   perform_or_defer_access_check (context, t);
-                 else
-                   enforce_access (context, t);
-               }
+               perform_or_defer_access_check (context, t);
 
              if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
                t = TREE_TYPE (t);
@@ -5578,12 +5567,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
        }
       
       if (complain & tf_error)
-       {
-         if (complain & tf_parsing)
-           perform_or_defer_access_check (context, tmpl);
-         else
-           enforce_access (context, tmpl);
-       }
+       perform_or_defer_access_check (context, tmpl);
 
       return tmpl;
     }
@@ -8447,7 +8431,6 @@ register_dtor_fn (tree decl)
   tree compound_stmt;
   tree args;
   tree fcall;
-  int saved_flag_access_control;
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
@@ -8464,10 +8447,10 @@ register_dtor_fn (tree decl)
      to the original function, rather than the anonymous one.  That
      will make the back-end think that nested functions are in use,
      which causes confusion.  */
-  saved_flag_access_control = flag_access_control;
-  scope_chain->check_access = flag_access_control = 0;
+  
+  push_deferring_access_checks (dk_no_check);
   fcall = build_cleanup (decl);
-  scope_chain->check_access = flag_access_control = saved_flag_access_control;
+  pop_deferring_access_checks ();
 
   /* Create the body of the anonymous function.  */
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
index f26fde4..4b6fdc8 100644 (file)
@@ -1662,8 +1662,7 @@ build_offset_ref (type, name)
          t = OVL_CURRENT (t);
 
          /* unique functions are handled easily.  */
-         if (!enforce_access (basebinfo, t))
-           return error_mark_node;
+         perform_or_defer_access_check (basebinfo, t);
          mark_used (t);
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
index 5ecb03e..816f9e3 100644 (file)
@@ -792,7 +792,7 @@ do_identifier (token, args)
     {
       /* Check access.  */
       if (IDENTIFIER_CLASS_VALUE (token) == id)
-       enforce_access (CP_DECL_CONTEXT(id), id);
+       perform_or_defer_access_check (CP_DECL_CONTEXT(id), id);
       if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
        id = DECL_INITIAL (id);
     }
index 841c291..12fa923 100644 (file)
@@ -179,7 +179,7 @@ hack_identifier (tree value, tree name)
        {
          tree path;
          path = currently_open_derived_class (DECL_CONTEXT (value));
-         enforce_access (path, value);
+         perform_or_defer_access_check (path, value);
        }
     }
   else if (TREE_CODE (value) == TREE_LIST 
@@ -452,7 +452,6 @@ use_thunk (tree thunk_fndecl, bool emit_p)
         doesn't work for varargs.  */
 
       tree a, t;
-      int saved_check_access;
 
       if (varargs_function_p (function))
        error ("generic thunk code fails for method `%#D' which uses `...'",
@@ -475,8 +474,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       /* We don't bother with a body block for thunks.  */
 
       /* There's no need to check accessibility inside the thunk body.  */
-      saved_check_access = scope_chain->check_access;
-      scope_chain->check_access = 0;
+      push_deferring_access_checks (dk_no_check);
 
       t = a;
       if (this_adjusting)
@@ -506,7 +504,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       DECL_IGNORED_P (thunk_fndecl) = 1;
 
       /* Re-enable access control.  */
-      scope_chain->check_access = saved_check_access;
+      pop_deferring_access_checks ();
 
       expand_body (finish_function (0));
     }
index 607749b..1d0ab40 100644 (file)
@@ -8244,7 +8244,7 @@ cp_parser_template_argument (cp_parser* parser)
       if (template_p)
        argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
                                                TREE_OPERAND (argument, 1),
-                                               tf_error | tf_parsing);
+                                               tf_error);
       else if (TREE_CODE (argument) != TEMPLATE_DECL)
        cp_parser_error (parser, "expected template-name");
     }
@@ -8301,7 +8301,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   begin_explicit_instantiation ();
   /* [temp.explicit] says that we are supposed to ignore access
      control while processing explicit instantiation directives.  */
-  scope_chain->check_access = 0;
+  push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
   decl_specifiers 
     = cp_parser_decl_specifier_seq (parser,
@@ -8336,7 +8336,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   /* We're done with the instantiation.  */
   end_explicit_instantiation ();
   /* Turn access control back on.  */
-  scope_chain->check_access = flag_access_control;
+  pop_deferring_access_checks ();
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 }
@@ -11390,8 +11390,7 @@ cp_parser_class_name (cp_parser *parser,
        standard does not seem to be definitive, but there is no other
        valid interpretation of the following `::'.  Therefore, those
        names are considered class-names.  */
-    decl = TYPE_NAME (make_typename_type (scope, decl, 
-                                         tf_error | tf_parsing));
+    decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
   else if (decl == error_mark_node
           || TREE_CODE (decl) != TYPE_DECL
           || !IS_AGGR_TYPE (TREE_TYPE (decl)))
@@ -11450,6 +11449,7 @@ cp_parser_class_specifier (cp_parser* parser)
   saved_num_template_parameter_lists 
     = parser->num_template_parameter_lists; 
   parser->num_template_parameter_lists = 0;
+
   /* Start the class.  */
   type = begin_class_definition (type);
   if (type == error_mark_node)
@@ -13646,8 +13646,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   /* 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);
@@ -13689,8 +13687,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
       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
@@ -14664,7 +14660,8 @@ yyparse (void)
   bool error_occurred;
 
   the_parser = cp_parser_new ();
-  push_deferring_access_checks (dk_no_deferred);
+  push_deferring_access_checks (flag_access_control
+                               ? dk_no_deferred : dk_no_check);
   error_occurred = cp_parser_translation_unit (the_parser);
   the_parser = NULL;
   
index 0354826..972bdab 100644 (file)
@@ -5259,6 +5259,10 @@ instantiate_class_template (type)
      the process of being defined.  */
   TYPE_BEING_DEFINED (type) = 1;
 
+  /* We may be in the middle of deferred access check.  Disable
+     it now.  */
+  push_deferring_access_checks (dk_no_deferred);
+
   maybe_push_to_top_level (uses_template_parms (type));
 
   if (t)
@@ -5568,6 +5572,7 @@ instantiate_class_template (type)
 
   popclass ();
   pop_from_top_level ();
+  pop_deferring_access_checks ();
   pop_tinst_level ();
 
   if (TYPE_CONTAINS_VPTR_P (type))
index fa27435..f9fa166 100644 (file)
@@ -913,10 +913,6 @@ accessible_p (tree type, tree decl)
      accessibility in TYPE.  */
   int protected_ok = 0;
 
-  /* If we're not checking access, everything is accessible.  */
-  if (!scope_chain->check_access)
-    return 1;
-
   /* If this declaration is in a block or namespace scope, there's no
      access control.  */
   if (!TYPE_P (context_for_name_lookup (decl)))
@@ -1293,9 +1289,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 
      In the case of overloaded function names, access control is
      applied to the function selected by overloaded resolution.  */
-  if (rval && protect && !is_overloaded_fn (rval)
-      && !enforce_access (xbasetype, rval))
-    return error_mark_node;
+  if (rval && protect && !is_overloaded_fn (rval))
+    perform_or_defer_access_check (xbasetype, rval);
 
   if (errstr && protect)
     {
index dfe40ee..62a900a 100644 (file)
@@ -141,6 +141,12 @@ void push_deferring_access_checks (deferring_kind deferring)
 {
   deferred_access *d;
 
+  /* For context like template instantiation, access checking
+     disabling applies to all nested context.  */
+  if (deferred_access_stack
+      && deferred_access_stack->deferring_access_checks_kind == dk_no_check)
+    deferring = dk_no_check;
+
   /* Recycle previously used free store if available.  */
   if (deferred_access_free_list)
     {
@@ -266,6 +272,7 @@ void perform_or_defer_access_check (tree class_type, tree decl)
        check;
        check = TREE_CHAIN (check))
     if (TREE_VALUE (check) == decl
+       && TYPE_P (TREE_PURPOSE (check))
        && same_type_p (TREE_PURPOSE (check), class_type))
       return;
   /* If not, record the check.  */
@@ -1276,7 +1283,7 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
            access_type = DECL_CONTEXT (access_type);
        }
 
-      enforce_access (access_type, decl);
+      perform_or_defer_access_check (access_type, decl);
 
       /* If the data member was named `C::M', convert `*this' to `C'
         first.  */
@@ -2301,12 +2308,10 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data)
       /* If we're using the non-reentrant PCC calling convention, then we
         need to copy the returned value out of the static buffer into the
         SLOT.  */
-      int old_ac = flag_access_control;
-
-      flag_access_control = 0;
+      push_deferring_access_checks (dk_no_check);
       call_expr = build_aggr_init (slot, call_expr,
                                   DIRECT_BIND | LOOKUP_ONLYCONVERTING);
-      flag_access_control = old_ac;
+      pop_deferring_access_checks ();
     }
 
   /* We want to use the value of the initialized location as the
index e30b580..b86bff6 100644 (file)
@@ -1,5 +1,11 @@
 2003-05-10  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
+       PR c++/9252
+       * g++.dg/template/access8.C: New test.
+       * g++.dg/template/access9.C: New test.
+
+2003-05-10  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
+
        PR c++/9554
        * g++.dg/parse/access1.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/template/access8.C b/gcc/testsuite/g++.dg/template/access8.C
new file mode 100644 (file)
index 0000000..4bdadae
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright (C) 2003 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+// Template instantiate during deferred access check
+
+template <class T> struct C {
+  typedef typename T::X Y;
+};
+
+class A {
+  typedef int X;
+  template <class T> friend struct C;
+};
+
+C<A>::Y f(int);
diff --git a/gcc/testsuite/g++.dg/template/access9.C b/gcc/testsuite/g++.dg/template/access9.C
new file mode 100644 (file)
index 0000000..b24c93f
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright (C) 2003 Free Software Foundation
+// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+// { dg-do compile }
+
+// Template instantiate during deferred access check
+
+template <void (*)(int)> struct C {
+  typedef int Y;
+};
+
+template <class T> void f(typename T::X) {
+}
+
+class A {
+  typedef int X;
+  template <class T> friend void f(typename T::X);
+};
+
+C<&f<A> >::Y g(int);