re PR c++/29475 (incomplete template diagnostics.)

PR c++/29475
	* cp-tree.h (enforce_access, perform_or_defer_access_check): Added an
	extra argument that represents the declaration to use to print
	potential error messages.
	* init.c (build_offset_ref): Adjusted the call to
	perform_or_defer_access_check.
	* class.c (alter_access, resolve_address_of_overloaded_function):
	Likewise.
	* decl.c (make_typename_type, make_unbound_class_template): Likewise. 
	* search.c (lookup_member): Likewise.
	* friend.c (add_friend): Likewise.
	* parser.c (cp_parser_template_id,
	cp_parser_pre_parsed_nested_name_specifier): Likewise.
	* semantics.c (finish_non_static_data_member,
	check_accessibility_of_qualified_id, finish_id_expression): Likewise.
	(pop_to_parent_deferring_access_checks, perform_access_checks,
	perform_or_defer_access_check): Adjusted the call to enforce_access.
	* call.c (enforce_access): Use the new extra argument to build the
	error message.
	(build_op_delete_call): Adjusted the call to
	perform_or_defer_access_check.
	(build_over_call): Likewise.

	PR c++/29475
	* g++.dg/template/access19.C: New test.
	* g++.old-deja/g++.other/access11.C: Adjusted the line where the
	error is reported.

From-SVN: r119027
This commit is contained in:
Simon Martin 2006-11-20 21:15:44 +00:00 committed by Mark Mitchell
parent 903ff2758b
commit 02022f3a70
13 changed files with 92 additions and 30 deletions

View file

@ -1,3 +1,28 @@
2006-11-20 Simon Martin <simartin@users.sourceforge.net>
PR c++/29475
* cp-tree.h (enforce_access, perform_or_defer_access_check): Added an
extra argument that represents the declaration to use to print
potential error messages.
* init.c (build_offset_ref): Adjusted the call to
perform_or_defer_access_check.
* class.c (alter_access, resolve_address_of_overloaded_function):
Likewise.
* decl.c (make_typename_type, make_unbound_class_template): Likewise.
* search.c (lookup_member): Likewise.
* friend.c (add_friend): Likewise.
* parser.c (cp_parser_template_id,
cp_parser_pre_parsed_nested_name_specifier): Likewise.
* semantics.c (finish_non_static_data_member,
check_accessibility_of_qualified_id, finish_id_expression): Likewise.
(pop_to_parent_deferring_access_checks, perform_access_checks,
perform_or_defer_access_check): Adjusted the call to enforce_access.
* call.c (enforce_access): Use the new extra argument to build the
error message.
(build_op_delete_call): Adjusted the call to
perform_or_defer_access_check.
(build_over_call): Likewise.
2006-11-16 Dirk Mueller <dmueller@suse.de>
* name-lookup.c (begin_scope): Use GGC_CNEW instead of

View file

@ -4097,7 +4097,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))
perform_or_defer_access_check (TYPE_BINFO (type), fn);
perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
@ -4128,21 +4128,22 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
/* If the current scope isn't allowed to access DECL along
BASETYPE_PATH, give an error. The most derived class in
BASETYPE_PATH is the one used to qualify DECL. */
BASETYPE_PATH is the one used to qualify DECL. DIAG_DECL is
the declaration to use in the error diagnostic. */
bool
enforce_access (tree basetype_path, tree decl)
enforce_access (tree basetype_path, tree decl, tree diag_decl)
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
if (!accessible_p (basetype_path, decl, true))
{
if (TREE_PRIVATE (decl))
error ("%q+#D is private", decl);
error ("%q+#D is private", diag_decl);
else if (TREE_PROTECTED (decl))
error ("%q+#D is protected", decl);
error ("%q+#D is protected", diag_decl);
else
error ("%q+#D is inaccessible", decl);
error ("%q+#D is inaccessible", diag_decl);
error ("within this context");
return false;
}
@ -4771,9 +4772,9 @@ build_over_call (struct z_candidate *cand, int flags)
if (DECL_TEMPLATE_INFO (fn)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
perform_or_defer_access_check (cand->access_path,
DECL_TI_TEMPLATE (fn));
DECL_TI_TEMPLATE (fn), fn);
else
perform_or_defer_access_check (cand->access_path, fn);
perform_or_defer_access_check (cand->access_path, fn, fn);
}
if (args && TREE_CODE (args) != TREE_LIST)

View file

@ -1129,7 +1129,7 @@ alter_access (tree t, tree fdecl, tree access)
}
else
{
perform_or_defer_access_check (TYPE_BINFO (t), fdecl);
perform_or_defer_access_check (TYPE_BINFO (t), fdecl, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
@ -5958,7 +5958,7 @@ resolve_address_of_overloaded_function (tree target_type,
if (DECL_FUNCTION_MEMBER_P (fn))
{
gcc_assert (access_path);
perform_or_defer_access_check (access_path, fn);
perform_or_defer_access_check (access_path, fn, fn);
}
}

View file

@ -3772,7 +3772,7 @@ extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree)
extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree, int);
extern bool can_convert_arg_bad (tree, tree, tree);
extern bool enforce_access (tree, tree);
extern bool enforce_access (tree, tree, tree);
extern tree convert_default_arg (tree, tree, tree, int);
extern tree convert_arg_to_ellipsis (tree);
extern tree build_x_va_arg (tree, tree);
@ -4209,7 +4209,7 @@ extern tree get_deferred_access_checks (void);
extern void pop_to_parent_deferring_access_checks (void);
extern void perform_access_checks (tree);
extern void perform_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree);
extern void perform_or_defer_access_check (tree, tree, tree);
extern int stmts_are_full_exprs_p (void);
extern void init_cp_semantics (void);
extern tree do_poplevel (tree);

View file

@ -2858,7 +2858,7 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), t);
perform_or_defer_access_check (TYPE_BINFO (context), t, t);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
@ -2921,7 +2921,7 @@ make_unbound_class_template (tree context, tree name, tree parm_list,
}
if (complain & tf_error)
perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
perform_or_defer_access_check (TYPE_BINFO (context), tmpl, tmpl);
return tmpl;
}

View file

@ -171,7 +171,7 @@ add_friend (tree type, tree decl, bool complain)
ctx = DECL_CONTEXT (decl);
if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
perform_or_defer_access_check (TYPE_BINFO (ctx), decl);
perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl);
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);

View file

@ -1383,9 +1383,9 @@ build_offset_ref (tree type, tree member, bool address_p)
(or any class derived from that class). */
if (address_p && DECL_P (t)
&& DECL_NONSTATIC_MEMBER_P (t))
perform_or_defer_access_check (TYPE_BINFO (type), t);
perform_or_defer_access_check (TYPE_BINFO (type), t, t);
else
perform_or_defer_access_check (basebinfo, t);
perform_or_defer_access_check (basebinfo, t, t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
@ -1398,7 +1398,7 @@ build_offset_ref (tree type, tree member, bool address_p)
/* We need additional test besides the one in
check_accessibility_of_qualified_id in case it is
a pointer to non-static member. */
perform_or_defer_access_check (TYPE_BINFO (type), member);
perform_or_defer_access_check (TYPE_BINFO (type), member, member);
if (!address_p)
{

View file

@ -8759,6 +8759,7 @@ cp_parser_template_id (cp_parser *parser,
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
perform_or_defer_access_check (TREE_PURPOSE (check),
TREE_VALUE (check),
TREE_VALUE (check));
/* Return the stored value. */
return TREE_VALUE (value);
@ -16643,7 +16644,9 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
value = cp_lexer_consume_token (parser->lexer)->value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
perform_or_defer_access_check (TREE_PURPOSE (check), TREE_VALUE (check));
perform_or_defer_access_check (TREE_PURPOSE (check),
TREE_VALUE (check),
TREE_VALUE (check));
/* Set the scope from the stored value. */
parser->scope = TREE_VALUE (value);
parser->qualifying_scope = TREE_TYPE (value);

View file

@ -1273,7 +1273,7 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
&& !really_overloaded_fn (rval)
&& !(TREE_CODE (rval) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (rval)))
perform_or_defer_access_check (basetype_path, rval);
perform_or_defer_access_check (basetype_path, rval, rval);
if (errstr && protect)
{

View file

@ -234,7 +234,7 @@ pop_to_parent_deferring_access_checks (void)
/* Check access. */
for (; checks; checks = TREE_CHAIN (checks))
enforce_access (TREE_PURPOSE (checks),
TREE_VALUE (checks));
TREE_VALUE (checks), TREE_VALUE (checks));
}
else
{
@ -271,7 +271,7 @@ perform_access_checks (tree checks)
while (checks)
{
enforce_access (TREE_PURPOSE (checks),
TREE_VALUE (checks));
TREE_VALUE (checks), TREE_VALUE (checks));
checks = TREE_CHAIN (checks);
}
}
@ -299,10 +299,10 @@ perform_deferred_access_checks (void)
}
/* Defer checking the accessibility of DECL, when looked up in
BINFO. */
BINFO. DIAG_DECL is the declaration to use to print diagnostics. */
void
perform_or_defer_access_check (tree binfo, tree decl)
perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl)
{
tree check;
deferred_access *ptr;
@ -319,7 +319,7 @@ perform_or_defer_access_check (tree binfo, tree decl)
/* If we are not supposed to defer access checks, just check now. */
if (ptr->deferring_access_checks_kind == dk_no_deferred)
{
enforce_access (binfo, decl);
enforce_access (binfo, decl, diag_decl);
return;
}
@ -1432,7 +1432,8 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
DECL_NAME (decl),
/*template_p=*/false);
perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
decl);
/* If the data member was named `C::M', convert `*this' to `C'
first. */
@ -1511,7 +1512,8 @@ check_accessibility_of_qualified_id (tree decl,
or similar in a default argument value. */
&& CLASS_TYPE_P (qualifying_type)
&& !dependent_type_p (qualifying_type))
perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
decl);
}
/* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the
@ -2839,7 +2841,7 @@ finish_id_expression (tree id_expression,
tree path;
path = currently_open_derived_class (DECL_CONTEXT (decl));
perform_or_defer_access_check (TYPE_BINFO (path), decl);
perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
}
decl = convert_from_reference (decl);

View file

@ -1,3 +1,10 @@
2006-11-20 Simon Martin <simartin@users.sourceforge.net>
PR c++/29475
* g++.dg/template/access19.C: New test.
* g++.old-deja/g++.other/access11.C: Adjusted the line where the
error is reported.
2006-11-20 Andrew Pinski <andrew_pinski@playstation.sony.com>
PR tree-opt/25500

View file

@ -0,0 +1,24 @@
/* PR c++/29475 The error diagnostic contained "U = U" instead of "U = char" */
/* { dg-do "compile" } */
template< class T >
class explicit_t
{
public:
explicit_t( const T& c ): value( c ) { }
operator T&() { return value; }
private:
template< class U >
explicit_t( U t ); /* { dg-error "with U = char, T = int|is private" } */
T value;
};
int foo( int x, explicit_t< int > y )
{
return x + y;
}
int main()
{
return foo( 5, 'c' ); /* { dg-error "this context" } */
}

View file

@ -5,12 +5,12 @@
class A
{
private:
template <class T> void g(T t) {} // { dg-error "" } private
template <class T> void g(T t) {}
int i;
};
template <>
void A::g<int>(int t) { i = 1; }
void A::g<int>(int t) { i = 1; } // { dg-error "" } private
int main()
{