diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2003-05-10 11:29:53 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2003-05-10 11:29:53 +0000 |
commit | 78757caa17dac295834129518cffc87f778cf66f (patch) | |
tree | c56f80b0b8d2950e80b44d92a5f02235bdc24b54 | |
parent | 8d241e0b5734bb89d46fc9b6884f78ad70ff453c (diff) | |
download | gcc-78757caa17dac295834129518cffc87f778cf66f.zip gcc-78757caa17dac295834129518cffc87f778cf66f.tar.gz gcc-78757caa17dac295834129518cffc87f778cf66f.tar.bz2 |
re PR c++/9252 ([New parser] Errors due to legally used "typename")
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
-rw-r--r-- | gcc/cp/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/cp/call.c | 4 | ||||
-rw-r--r-- | gcc/cp/class.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 29 | ||||
-rw-r--r-- | gcc/cp/init.c | 3 | ||||
-rw-r--r-- | gcc/cp/lex.c | 2 | ||||
-rw-r--r-- | gcc/cp/method.c | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 17 | ||||
-rw-r--r-- | gcc/cp/pt.c | 5 | ||||
-rw-r--r-- | gcc/cp/search.c | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/access8.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/access9.C | 19 |
15 files changed, 115 insertions, 60 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2087066..81645ce 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5d7e3df..84bdcd6 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 196815a..c693fdf 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 89d068a..3398398 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6df2a0b..4bec8a6 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index f26fde4..4b6fdc8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 5ecb03e..816f9e3 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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); } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 841c291..12fa923 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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)); } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 607749b..1d0ab40 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0354826..972bdab 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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)) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index fa27435..f9fa166 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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) { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index dfe40ee..62a900a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e30b580..b86bff6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..4bdadae --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access8.C @@ -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 index 0000000..b24c93f --- /dev/null +++ b/gcc/testsuite/g++.dg/template/access9.C @@ -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); |