This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Remove scope_chain->check_access, fix PR9252 (a regression)
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 15 Apr 2003 17:58:43 +0700 (ICT)
- Subject: [C++ PATCH] Remove scope_chain->check_access, fix PR9252 (a regression)
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This is a continuation of my earlier patch (unreviewed)
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg00444.html
that unifies access checking disabling and deferring mechanisms
to use the same functions. This patch completes the work
by removing the `scope_chain->check_access' field, and
using `perform_or_defer_access_check' throughout the frontend.
PR c++/9252 is fixed as a by-product of not calling the function
`enforce_access' directly.
Bootstrapped and tested on i686-pc-linux-gnu with no regressions.
OK to commit this together with the earlier patch mentioned above
to the main trunk?
--Kriang
2003-04-15 Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot 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-04-15 Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
PR c++/9252
* g++.dg/parse/access8.C: New test.
* g++.dg/parse/access9.C: New test.
diff -cprN gcc-main-save/gcc/cp/call.c gcc-main-new/gcc/cp/call.c
*** gcc-main-save/gcc/cp/call.c Sun Mar 30 00:55:57 2003
--- gcc-main-new/gcc/cp/call.c Mon Apr 14 19:15:37 2003
*************** build_op_delete_call (enum tree_code cod
*** 4033,4039 ****
/* If the FN is a member function, make sure that it is
accessible. */
if (DECL_CLASS_SCOPE_P (fn))
! enforce_access (type, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
--- 4033,4039 ----
/* If the FN is a member function, make sure that it is
accessible. */
if (DECL_CLASS_SCOPE_P (fn))
! perform_or_defer_access_check (type, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
*************** build_over_call (struct z_candidate *can
*** 4484,4490 ****
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
! enforce_access (cand->access_path, fn);
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
--- 4484,4490 ----
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (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 -cprN gcc-main-save/gcc/cp/class.c gcc-main-new/gcc/cp/class.c
*** gcc-main-save/gcc/cp/class.c Sun Apr 6 20:30:41 2003
--- gcc-main-new/gcc/cp/class.c Mon Apr 14 19:15:37 2003
*************** alter_access (tree t, tree fdecl, tree a
*** 1086,1092 ****
}
else
{
! enforce_access (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
--- 1086,1092 ----
}
else
{
! perform_or_defer_access_check (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
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 Mon Apr 14 17:23:01 2003
--- gcc-main-new/gcc/cp/cp-tree.h Tue Apr 15 15:41:53 2003
*************** struct saved_scope GTY(())
*** 726,732 ****
int x_processing_specialization;
bool x_processing_explicit_instantiation;
int need_pop_function_context;
- int check_access;
struct stmt_tree_s x_stmt_tree;
--- 726,731 ----
*************** typedef enum tsubst_flags_t {
*** 3033,3042 ****
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
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. */
--- 3032,3039 ----
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
instantiate_type use) */
} tsubst_flags_t;
/* The kind of checking we can do looking in a class hierarchy. */
diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c Sun Apr 6 20:30:41 2003
--- gcc-main-new/gcc/cp/decl.c Mon Apr 14 19:15:37 2003
*************** maybe_push_to_top_level (int pseudo)
*** 2243,2249 ****
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;
--- 2243,2248 ----
*************** make_typename_type (tree context, tree n
*** 5478,5489 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, tmpl);
! else
! enforce_access (context, tmpl);
! }
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
--- 5477,5483 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, tmpl);
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
*************** make_typename_type (tree context, tree n
*** 5513,5524 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, t);
! else
! enforce_access (context, t);
! }
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
--- 5507,5513 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, t);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
*************** make_unbound_class_template (tree contex
*** 5575,5586 ****
}
if (complain & tf_error)
! {
! if (complain & tf_parsing)
! perform_or_defer_access_check (context, tmpl);
! else
! enforce_access (context, tmpl);
! }
return tmpl;
}
--- 5564,5570 ----
}
if (complain & tf_error)
! perform_or_defer_access_check (context, tmpl);
return tmpl;
}
*************** register_dtor_fn (tree decl)
*** 8428,8434 ****
tree compound_stmt;
tree args;
tree fcall;
- int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
--- 8412,8417 ----
*************** register_dtor_fn (tree decl)
*** 8445,8454 ****
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;
fcall = build_cleanup (decl);
! scope_chain->check_access = flag_access_control = saved_flag_access_control;
/* Create the body of the anonymous function. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
--- 8428,8437 ----
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. */
!
! push_deferring_access_checks (dk_no_check);
fcall = build_cleanup (decl);
! pop_deferring_access_checks ();
/* Create the body of the anonymous function. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
diff -cprN gcc-main-save/gcc/cp/init.c gcc-main-new/gcc/cp/init.c
*** gcc-main-save/gcc/cp/init.c Tue Mar 18 22:45:20 2003
--- gcc-main-new/gcc/cp/init.c Mon Apr 14 19:15:37 2003
*************** build_offset_ref (type, name)
*** 1662,1669 ****
t = OVL_CURRENT (t);
/* unique functions are handled easily. */
! if (!enforce_access (basebinfo, t))
! return error_mark_node;
mark_used (t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
--- 1662,1668 ----
t = OVL_CURRENT (t);
/* unique functions are handled easily. */
! perform_or_defer_access_check (basebinfo, t);
mark_used (t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
diff -cprN gcc-main-save/gcc/cp/lex.c gcc-main-new/gcc/cp/lex.c
*** gcc-main-save/gcc/cp/lex.c Sun Mar 9 21:21:31 2003
--- gcc-main-new/gcc/cp/lex.c Mon Apr 14 19:15:37 2003
*************** do_identifier (token, args)
*** 790,796 ****
{
/* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id)
! enforce_access (CP_DECL_CONTEXT(id), id);
if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
--- 790,796 ----
{
/* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == 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 -cprN gcc-main-save/gcc/cp/method.c gcc-main-new/gcc/cp/method.c
*** gcc-main-save/gcc/cp/method.c Sun Apr 6 20:30:41 2003
--- gcc-main-new/gcc/cp/method.c Mon Apr 14 19:15:37 2003
*************** hack_identifier (tree value, tree name)
*** 179,185 ****
{
tree path;
path = currently_open_derived_class (DECL_CONTEXT (value));
! enforce_access (path, value);
}
}
else if (TREE_CODE (value) == TREE_LIST
--- 179,185 ----
{
tree path;
path = currently_open_derived_class (DECL_CONTEXT (value));
! perform_or_defer_access_check (path, value);
}
}
else if (TREE_CODE (value) == TREE_LIST
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 449,455 ****
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 `...'",
--- 449,454 ----
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 472,479 ****
/* 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;
t = a;
if (this_adjusting)
--- 471,477 ----
/* We don't bother with a body block for thunks. */
/* There's no need to check accessibility inside the thunk body. */
! push_deferring_access_checks (dk_no_check);
t = a;
if (this_adjusting)
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 503,509 ****
DECL_IGNORED_P (thunk_fndecl) = 1;
/* Re-enable access control. */
! scope_chain->check_access = saved_check_access;
expand_body (finish_function (0));
}
--- 501,507 ----
DECL_IGNORED_P (thunk_fndecl) = 1;
/* Re-enable access control. */
! pop_deferring_access_checks ();
expand_body (finish_function (0));
}
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c Mon Apr 14 17:23:01 2003
--- gcc-main-new/gcc/cp/parser.c Mon Apr 14 21:20:49 2003
*************** cp_parser_template_argument (cp_parser*
*** 8245,8251 ****
if (template_p)
argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
TREE_OPERAND (argument, 1),
! tf_error | tf_parsing);
else if (TREE_CODE (argument) != TEMPLATE_DECL)
cp_parser_error (parser, "expected template-name");
}
--- 8245,8251 ----
if (template_p)
argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
TREE_OPERAND (argument, 1),
! tf_error);
else if (TREE_CODE (argument) != TEMPLATE_DECL)
cp_parser_error (parser, "expected template-name");
}
*************** cp_parser_explicit_instantiation (cp_par
*** 8302,8308 ****
begin_explicit_instantiation ();
/* [temp.explicit] says that we are supposed to ignore access
control while processing explicit instantiation directives. */
! scope_chain->check_access = 0;
/* Parse a decl-specifier-seq. */
decl_specifiers
= cp_parser_decl_specifier_seq (parser,
--- 8302,8308 ----
begin_explicit_instantiation ();
/* [temp.explicit] says that we are supposed to ignore access
control while processing explicit instantiation directives. */
! push_deferring_access_checks (dk_no_check);
/* Parse a decl-specifier-seq. */
decl_specifiers
= cp_parser_decl_specifier_seq (parser,
*************** cp_parser_explicit_instantiation (cp_par
*** 8337,8343 ****
/* 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);
}
--- 8337,8343 ----
/* We're done with the instantiation. */
end_explicit_instantiation ();
/* Turn access control back on. */
! pop_deferring_access_checks ();
cp_parser_consume_semicolon_at_end_of_statement (parser);
}
*************** cp_parser_class_name (cp_parser *parser,
*** 11391,11398 ****
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));
else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl)))
--- 11391,11397 ----
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));
else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl)))
*************** cp_parser_class_specifier (cp_parser* pa
*** 11451,11456 ****
--- 11450,11456 ----
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)
*************** cp_parser_constructor_declarator_p (cp_p
*** 13647,13654 ****
/* 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);
--- 13647,13652 ----
*************** cp_parser_constructor_declarator_p (cp_p
*** 13690,13697 ****
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
--- 13688,13693 ----
*************** yyparse (void)
*** 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;
--- 14661,14668 ----
bool error_occurred;
the_parser = cp_parser_new ();
! 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 -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Sun Mar 30 00:55:57 2003
--- gcc-main-new/gcc/cp/pt.c Mon Apr 14 19:16:32 2003
*************** instantiate_class_template (type)
*** 5252,5257 ****
--- 5252,5261 ----
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 (false);
+
maybe_push_to_top_level (uses_template_parms (type));
if (t)
*************** instantiate_class_template (type)
*** 5562,5567 ****
--- 5566,5572 ----
popclass ();
pop_from_top_level ();
+ pop_deferring_access_checks ();
pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type))
diff -cprN gcc-main-save/gcc/cp/search.c gcc-main-new/gcc/cp/search.c
*** gcc-main-save/gcc/cp/search.c Wed Apr 2 21:02:45 2003
--- gcc-main-new/gcc/cp/search.c Mon Apr 14 19:15:37 2003
*************** accessible_p (tree type, tree decl)
*** 910,919 ****
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)))
--- 910,915 ----
*************** lookup_member (tree xbasetype, tree name
*** 1290,1298 ****
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 (errstr && protect)
{
--- 1286,1293 ----
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))
! perform_or_defer_access_check (xbasetype, rval);
if (errstr && protect)
{
diff -cprN gcc-main-save/gcc/cp/semantics.c gcc-main-new/gcc/cp/semantics.c
*** gcc-main-save/gcc/cp/semantics.c Mon Apr 14 17:23:01 2003
--- gcc-main-new/gcc/cp/semantics.c Mon Apr 14 20:38:46 2003
*************** void push_deferring_access_checks (defer
*** 141,146 ****
--- 141,152 ----
{
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)
{
*************** void perform_or_defer_access_check (tree
*** 266,271 ****
--- 272,278 ----
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. */
*************** finish_non_static_data_member (tree decl
*** 1276,1282 ****
access_type = DECL_CONTEXT (access_type);
}
! enforce_access (access_type, decl);
/* If the data member was named `C::M', convert `*this' to `C'
first. */
--- 1283,1289 ----
access_type = DECL_CONTEXT (access_type);
}
! perform_or_defer_access_check (access_type, decl);
/* If the data member was named `C::M', convert `*this' to `C'
first. */
*************** simplify_aggr_init_exprs_r (tp, walk_sub
*** 2299,2310 ****
/* 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;
call_expr = build_aggr_init (slot, call_expr,
DIRECT_BIND | LOOKUP_ONLYCONVERTING);
! flag_access_control = old_ac;
}
/* We want to use the value of the initialized location as the
--- 2306,2315 ----
/* 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. */
! push_deferring_access_checks (dk_no_check);
call_expr = build_aggr_init (slot, call_expr,
DIRECT_BIND | LOOKUP_ONLYCONVERTING);
! pop_deferring_access_checks ();
}
/* We want to use the value of the initialized location as the
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/access8.C gcc-main-new/gcc/testsuite/g++.dg/template/access8.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/access8.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/access8.C Mon Apr 14 21:39:36 2003
***************
*** 0 ****
--- 1,16 ----
+ // Copyright (C) 2003 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot 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 -cprN gcc-main-save/gcc/testsuite/g++.dg/template/access9.C gcc-main-new/gcc/testsuite/g++.dg/template/access9.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/access9.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/access9.C Mon Apr 14 21:39:36 2003
***************
*** 0 ****
--- 1,19 ----
+ // Copyright (C) 2003 Free Software Foundation
+ // Contributed by Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot 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);