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.
/* 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);
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);
}
else
{
- enforce_access (t, fdecl);
+ perform_or_defer_access_check (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
int x_processing_specialization;
bool x_processing_explicit_instantiation;
int need_pop_function_context;
- int check_access;
struct stmt_tree_s x_stmt_tree;
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. */
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;
}
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),
}
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);
}
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;
}
tree compound_stmt;
tree args;
tree fcall;
- int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
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);
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;
{
/* 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);
}
{
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
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 `...'",
/* 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)
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));
}
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");
}
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,
/* 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);
}
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)))
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)
/* 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);
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
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;
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)
popclass ();
pop_from_top_level ();
+ pop_deferring_access_checks ();
pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type))
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)))
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)
{
{
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)
{
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. */
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. */
/* 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
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.
--- /dev/null
+// 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);
--- /dev/null
+// 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);