Commit 78757caa by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

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
parent 8d241e0b
2003-05-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 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 PR c++/9554
* parser.c (cp_parser_class_name): Remove check_access parameter. * parser.c (cp_parser_class_name): Remove check_access parameter.
All caller adjusted. Update declaration. All caller adjusted. Update declaration.
......
...@@ -4062,7 +4062,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, ...@@ -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 /* If the FN is a member function, make sure that it is
accessible. */ accessible. */
if (DECL_CLASS_SCOPE_P (fn)) if (DECL_CLASS_SCOPE_P (fn))
enforce_access (type, fn); perform_or_defer_access_check (type, fn);
if (pass == 0) if (pass == 0)
args = tree_cons (NULL_TREE, addr, args); args = tree_cons (NULL_TREE, addr, args);
...@@ -4513,7 +4513,7 @@ build_over_call (struct z_candidate *cand, int flags) ...@@ -4513,7 +4513,7 @@ build_over_call (struct z_candidate *cand, int flags)
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1); joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn)) 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) if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args); args = build_tree_list (NULL_TREE, args);
......
...@@ -1086,7 +1086,7 @@ alter_access (tree t, tree fdecl, tree access) ...@@ -1086,7 +1086,7 @@ alter_access (tree t, tree fdecl, tree access)
} }
else else
{ {
enforce_access (t, fdecl); perform_or_defer_access_check (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl)); DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1; return 1;
} }
......
...@@ -696,7 +696,6 @@ struct saved_scope GTY(()) ...@@ -696,7 +696,6 @@ struct saved_scope GTY(())
int x_processing_specialization; int x_processing_specialization;
bool x_processing_explicit_instantiation; bool x_processing_explicit_instantiation;
int need_pop_function_context; int need_pop_function_context;
int check_access;
struct stmt_tree_s x_stmt_tree; struct stmt_tree_s x_stmt_tree;
...@@ -3013,10 +3012,8 @@ typedef enum tsubst_flags_t { ...@@ -3013,10 +3012,8 @@ typedef enum tsubst_flags_t {
tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */ tf_ignore_bad_quals = 1 << 3, /* ignore bad cvr qualifiers */
tf_keep_type_decl = 1 << 4, /* retain typedef type decls tf_keep_type_decl = 1 << 4, /* retain typedef type decls
(make_typename_type use) */ (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) */ instantiate_type use) */
tf_parsing = 1 << 6 /* called from parser
(make_typename_type use) */
} tsubst_flags_t; } tsubst_flags_t;
/* The kind of checking we can do looking in a class hierarchy. */ /* The kind of checking we can do looking in a class hierarchy. */
......
...@@ -2242,7 +2242,6 @@ maybe_push_to_top_level (int pseudo) ...@@ -2242,7 +2242,6 @@ maybe_push_to_top_level (int pseudo)
s->need_pop_function_context = need_pop; s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl; s->function_decl = current_function_decl;
s->last_parms = last_function_parms; s->last_parms = last_function_parms;
s->check_access = flag_access_control;
scope_chain = s; scope_chain = s;
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
...@@ -5481,12 +5480,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain) ...@@ -5481,12 +5480,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
} }
if (complain & tf_error) if (complain & tf_error)
{ perform_or_defer_access_check (context, tmpl);
if (complain & tf_parsing)
perform_or_defer_access_check (context, tmpl);
else
enforce_access (context, tmpl);
}
return lookup_template_class (tmpl, return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1), TREE_OPERAND (fullname, 1),
...@@ -5516,12 +5510,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain) ...@@ -5516,12 +5510,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
} }
if (complain & tf_error) if (complain & tf_error)
{ perform_or_defer_access_check (context, t);
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)) if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t); t = TREE_TYPE (t);
...@@ -5578,12 +5567,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain) ...@@ -5578,12 +5567,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
} }
if (complain & tf_error) if (complain & tf_error)
{ perform_or_defer_access_check (context, tmpl);
if (complain & tf_parsing)
perform_or_defer_access_check (context, tmpl);
else
enforce_access (context, tmpl);
}
return tmpl; return tmpl;
} }
...@@ -8447,7 +8431,6 @@ register_dtor_fn (tree decl) ...@@ -8447,7 +8431,6 @@ register_dtor_fn (tree decl)
tree compound_stmt; tree compound_stmt;
tree args; tree args;
tree fcall; tree fcall;
int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return; return;
...@@ -8464,10 +8447,10 @@ register_dtor_fn (tree decl) ...@@ -8464,10 +8447,10 @@ register_dtor_fn (tree decl)
to the original function, rather than the anonymous one. That to the original function, rather than the anonymous one. That
will make the back-end think that nested functions are in use, will make the back-end think that nested functions are in use,
which causes confusion. */ 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); 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. */ /* Create the body of the anonymous function. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
......
...@@ -1662,8 +1662,7 @@ build_offset_ref (type, name) ...@@ -1662,8 +1662,7 @@ build_offset_ref (type, name)
t = OVL_CURRENT (t); t = OVL_CURRENT (t);
/* unique functions are handled easily. */ /* unique functions are handled easily. */
if (!enforce_access (basebinfo, t)) perform_or_defer_access_check (basebinfo, t);
return error_mark_node;
mark_used (t); mark_used (t);
if (DECL_STATIC_FUNCTION_P (t)) if (DECL_STATIC_FUNCTION_P (t))
return t; return t;
......
...@@ -792,7 +792,7 @@ do_identifier (token, args) ...@@ -792,7 +792,7 @@ do_identifier (token, args)
{ {
/* Check access. */ /* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id) 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)) if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id); id = DECL_INITIAL (id);
} }
......
...@@ -179,7 +179,7 @@ hack_identifier (tree value, tree name) ...@@ -179,7 +179,7 @@ hack_identifier (tree value, tree name)
{ {
tree path; tree path;
path = currently_open_derived_class (DECL_CONTEXT (value)); 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 else if (TREE_CODE (value) == TREE_LIST
...@@ -452,7 +452,6 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -452,7 +452,6 @@ use_thunk (tree thunk_fndecl, bool emit_p)
doesn't work for varargs. */ doesn't work for varargs. */
tree a, t; tree a, t;
int saved_check_access;
if (varargs_function_p (function)) if (varargs_function_p (function))
error ("generic thunk code fails for method `%#D' which uses `...'", error ("generic thunk code fails for method `%#D' which uses `...'",
...@@ -475,8 +474,7 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -475,8 +474,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
/* We don't bother with a body block for thunks. */ /* We don't bother with a body block for thunks. */
/* There's no need to check accessibility inside the thunk body. */ /* There's no need to check accessibility inside the thunk body. */
saved_check_access = scope_chain->check_access; push_deferring_access_checks (dk_no_check);
scope_chain->check_access = 0;
t = a; t = a;
if (this_adjusting) if (this_adjusting)
...@@ -506,7 +504,7 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -506,7 +504,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
DECL_IGNORED_P (thunk_fndecl) = 1; DECL_IGNORED_P (thunk_fndecl) = 1;
/* Re-enable access control. */ /* Re-enable access control. */
scope_chain->check_access = saved_check_access; pop_deferring_access_checks ();
expand_body (finish_function (0)); expand_body (finish_function (0));
} }
......
...@@ -8244,7 +8244,7 @@ cp_parser_template_argument (cp_parser* parser) ...@@ -8244,7 +8244,7 @@ cp_parser_template_argument (cp_parser* parser)
if (template_p) if (template_p)
argument = make_unbound_class_template (TREE_OPERAND (argument, 0), argument = make_unbound_class_template (TREE_OPERAND (argument, 0),
TREE_OPERAND (argument, 1), TREE_OPERAND (argument, 1),
tf_error | tf_parsing); tf_error);
else if (TREE_CODE (argument) != TEMPLATE_DECL) else if (TREE_CODE (argument) != TEMPLATE_DECL)
cp_parser_error (parser, "expected template-name"); cp_parser_error (parser, "expected template-name");
} }
...@@ -8301,7 +8301,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) ...@@ -8301,7 +8301,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
begin_explicit_instantiation (); begin_explicit_instantiation ();
/* [temp.explicit] says that we are supposed to ignore access /* [temp.explicit] says that we are supposed to ignore access
control while processing explicit instantiation directives. */ control while processing explicit instantiation directives. */
scope_chain->check_access = 0; push_deferring_access_checks (dk_no_check);
/* Parse a decl-specifier-seq. */ /* Parse a decl-specifier-seq. */
decl_specifiers decl_specifiers
= cp_parser_decl_specifier_seq (parser, = cp_parser_decl_specifier_seq (parser,
...@@ -8336,7 +8336,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) ...@@ -8336,7 +8336,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
/* We're done with the instantiation. */ /* We're done with the instantiation. */
end_explicit_instantiation (); end_explicit_instantiation ();
/* Turn access control back on. */ /* 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); cp_parser_consume_semicolon_at_end_of_statement (parser);
} }
...@@ -11390,8 +11390,7 @@ cp_parser_class_name (cp_parser *parser, ...@@ -11390,8 +11390,7 @@ cp_parser_class_name (cp_parser *parser,
standard does not seem to be definitive, but there is no other standard does not seem to be definitive, but there is no other
valid interpretation of the following `::'. Therefore, those valid interpretation of the following `::'. Therefore, those
names are considered class-names. */ names are considered class-names. */
decl = TYPE_NAME (make_typename_type (scope, decl, decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
tf_error | tf_parsing));
else if (decl == error_mark_node else if (decl == error_mark_node
|| TREE_CODE (decl) != TYPE_DECL || TREE_CODE (decl) != TYPE_DECL
|| !IS_AGGR_TYPE (TREE_TYPE (decl))) || !IS_AGGR_TYPE (TREE_TYPE (decl)))
...@@ -11450,6 +11449,7 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -11450,6 +11449,7 @@ cp_parser_class_specifier (cp_parser* parser)
saved_num_template_parameter_lists saved_num_template_parameter_lists
= parser->num_template_parameter_lists; = parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0; parser->num_template_parameter_lists = 0;
/* Start the class. */ /* Start the class. */
type = begin_class_definition (type); type = begin_class_definition (type);
if (type == error_mark_node) if (type == error_mark_node)
...@@ -13646,8 +13646,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) ...@@ -13646,8 +13646,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
/* Assume that we are looking at a constructor declarator. */ /* Assume that we are looking at a constructor declarator. */
constructor_p = true; constructor_p = true;
push_deferring_access_checks (dk_no_check);
/* Look for the optional `::' operator. */ /* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false); /*current_scope_valid_p=*/false);
...@@ -13689,8 +13687,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) ...@@ -13689,8 +13687,6 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
constructor_p = !cp_parser_error_occurred (parser); constructor_p = !cp_parser_error_occurred (parser);
} }
pop_deferring_access_checks ();
/* If we're still considering a constructor, we have to see a `(', /* If we're still considering a constructor, we have to see a `(',
to begin the parameter-declaration-clause, followed by either a to begin the parameter-declaration-clause, followed by either a
`)', an `...', or a decl-specifier. We need to check for a `)', an `...', or a decl-specifier. We need to check for a
...@@ -14664,7 +14660,8 @@ yyparse (void) ...@@ -14664,7 +14660,8 @@ yyparse (void)
bool error_occurred; bool error_occurred;
the_parser = cp_parser_new (); 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); error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL; the_parser = NULL;
......
...@@ -5259,6 +5259,10 @@ instantiate_class_template (type) ...@@ -5259,6 +5259,10 @@ instantiate_class_template (type)
the process of being defined. */ the process of being defined. */
TYPE_BEING_DEFINED (type) = 1; 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)); maybe_push_to_top_level (uses_template_parms (type));
if (t) if (t)
...@@ -5568,6 +5572,7 @@ instantiate_class_template (type) ...@@ -5568,6 +5572,7 @@ instantiate_class_template (type)
popclass (); popclass ();
pop_from_top_level (); pop_from_top_level ();
pop_deferring_access_checks ();
pop_tinst_level (); pop_tinst_level ();
if (TYPE_CONTAINS_VPTR_P (type)) if (TYPE_CONTAINS_VPTR_P (type))
......
...@@ -913,10 +913,6 @@ accessible_p (tree type, tree decl) ...@@ -913,10 +913,6 @@ accessible_p (tree type, tree decl)
accessibility in TYPE. */ accessibility in TYPE. */
int protected_ok = 0; 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 /* If this declaration is in a block or namespace scope, there's no
access control. */ access control. */
if (!TYPE_P (context_for_name_lookup (decl))) if (!TYPE_P (context_for_name_lookup (decl)))
...@@ -1293,9 +1289,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) ...@@ -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 In the case of overloaded function names, access control is
applied to the function selected by overloaded resolution. */ applied to the function selected by overloaded resolution. */
if (rval && protect && !is_overloaded_fn (rval) if (rval && protect && !is_overloaded_fn (rval))
&& !enforce_access (xbasetype, rval)) perform_or_defer_access_check (xbasetype, rval);
return error_mark_node;
if (errstr && protect) if (errstr && protect)
{ {
......
...@@ -141,6 +141,12 @@ void push_deferring_access_checks (deferring_kind deferring) ...@@ -141,6 +141,12 @@ void push_deferring_access_checks (deferring_kind deferring)
{ {
deferred_access *d; 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. */ /* Recycle previously used free store if available. */
if (deferred_access_free_list) if (deferred_access_free_list)
{ {
...@@ -266,6 +272,7 @@ void perform_or_defer_access_check (tree class_type, tree decl) ...@@ -266,6 +272,7 @@ void perform_or_defer_access_check (tree class_type, tree decl)
check; check;
check = TREE_CHAIN (check)) check = TREE_CHAIN (check))
if (TREE_VALUE (check) == decl if (TREE_VALUE (check) == decl
&& TYPE_P (TREE_PURPOSE (check))
&& same_type_p (TREE_PURPOSE (check), class_type)) && same_type_p (TREE_PURPOSE (check), class_type))
return; return;
/* If not, record the check. */ /* If not, record the check. */
...@@ -1276,7 +1283,7 @@ finish_non_static_data_member (tree decl, tree qualifying_scope) ...@@ -1276,7 +1283,7 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
access_type = DECL_CONTEXT (access_type); 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' /* If the data member was named `C::M', convert `*this' to `C'
first. */ first. */
...@@ -2301,12 +2308,10 @@ simplify_aggr_init_exprs_r (tp, walk_subtrees, data) ...@@ -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 /* 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 need to copy the returned value out of the static buffer into the
SLOT. */ SLOT. */
int old_ac = flag_access_control; push_deferring_access_checks (dk_no_check);
flag_access_control = 0;
call_expr = build_aggr_init (slot, call_expr, call_expr = build_aggr_init (slot, call_expr,
DIRECT_BIND | LOOKUP_ONLYCONVERTING); 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 /* We want to use the value of the initialized location as the
......
2003-05-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 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 PR c++/9554
* g++.dg/parse/access1.C: New test. * g++.dg/parse/access1.C: New test.
......
// 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);
// 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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment