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
This commit is contained in:
parent
8d241e0b57
commit
78757caa17
|
@ -1,3 +1,38 @@
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
Loading…
Reference in New Issue