PR c++/7347, c++/7348

PR c++/7347, c++/7348
	* cp-tree.h (tsubst_flags_t): Add tf_parsing.
	* decl.c (make_typename_type): Use it.
	(make_unbound_class_template): Likewise.
	(lookup_name_real): Don't call type_access_control if scope is
	template parameter dependent.
	* parse.y (template_arg): Call make_unbound_class_template with
	tf_parsing set.
	(nest_name_specifier): Call make_typename_type with tf_parsing set.
	(typename_sub0): Likewise.
	(typename_sub1): Likewise.
	(instantiate_decl): Push class scope.
	* pt.c (regenerate_decl_from_template): Call pushclass and popclass
	for both static variable and member function template.
	(instantiate_decl) Call pushclass and popclass when tsubst'ing type
	and arguments.
	* search.c (type_access_control): Do type access for TEMPLATE_DECL
	too.

	* g++.dg/template/access4.C: New test.
	* g++.dg/template/access5.C: New test.
	* g++.old-deja/g++.pt/memtemp85.C: Fix access problem.
	* g++.old-deja/g++.pt/memtemp86.C: Likewise.
	* g++.old-deja/g++.pt/ttp58.C: Likewise.
	* g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL.

From-SVN: r55649
This commit is contained in:
Kriang Lerdsuwanakij 2002-07-22 14:23:37 +00:00 committed by Kriang Lerdsuwanakij
parent 0d541696aa
commit 0e902d98ae
13 changed files with 121 additions and 32 deletions

View File

@ -1,3 +1,24 @@
2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/7347, c++/7348
* cp-tree.h (tsubst_flags_t): Add tf_parsing.
* decl.c (make_typename_type): Use it.
(make_unbound_class_template): Likewise.
(lookup_name_real): Don't call type_access_control if scope is
template parameter dependent.
* parse.y (template_arg): Call make_unbound_class_template with
tf_parsing set.
(nest_name_specifier): Call make_typename_type with tf_parsing set.
(typename_sub0): Likewise.
(typename_sub1): Likewise.
(instantiate_decl): Push class scope.
* pt.c (regenerate_decl_from_template): Call pushclass and popclass
for both static variable and member function template.
(instantiate_decl) Call pushclass and popclass when tsubst'ing type
and arguments.
* search.c (type_access_control): Do type access for TEMPLATE_DECL
too.
2002-07-20 Roger Sayle <roger@eyesopen.com> 2002-07-20 Roger Sayle <roger@eyesopen.com>
* decl2.c (cxx_decode_option): Simplify -fhandle-exceptions * decl2.c (cxx_decode_option): Simplify -fhandle-exceptions

View File

@ -3187,8 +3187,10 @@ 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. */

View File

@ -5659,8 +5659,10 @@ make_typename_type (context, name, complain)
return error_mark_node; return error_mark_node;
} }
if (!enforce_access (context, tmpl)) if (complain & tf_parsing)
return error_mark_node; type_access_control (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),
@ -5682,8 +5684,10 @@ make_typename_type (context, name, complain)
t = lookup_field (context, name, 0, 1); t = lookup_field (context, name, 0, 1);
if (t) if (t)
{ {
if (!enforce_access (context, t)) if (complain & tf_parsing)
return error_mark_node; type_access_control (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);
@ -5712,7 +5716,6 @@ make_typename_type (context, name, complain)
return error_mark_node; return error_mark_node;
} }
return build_typename_type (context, name, fullname, NULL_TREE); return build_typename_type (context, name, fullname, NULL_TREE);
} }
@ -5752,8 +5755,10 @@ make_unbound_class_template (context, name, complain)
return error_mark_node; return error_mark_node;
} }
if (!enforce_access (context, tmpl)) if (complain & tf_parsing)
return error_mark_node; type_access_control (context, tmpl);
else
enforce_access (context, tmpl);
return tmpl; return tmpl;
} }
@ -6078,7 +6083,8 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else else
{ {
val = lookup_member (type, name, 0, prefer_type); val = lookup_member (type, name, 0, prefer_type);
type_access_control (type, val); if (!uses_template_parms (type))
type_access_control (type, val);
/* Restore the containing TYPENAME_TYPE if we looked /* Restore the containing TYPENAME_TYPE if we looked
through it before. */ through it before. */

View File

@ -1159,7 +1159,7 @@ template_arg:
$$ = error_mark_node; $$ = error_mark_node;
} }
else else
$$ = make_unbound_class_template ($1, $3, 1); $$ = make_unbound_class_template ($1, $3, tf_error | tf_parsing);
} }
; ;
@ -3071,14 +3071,14 @@ nested_name_specifier:
{ $$ = $2; } { $$ = $2; }
| nested_name_specifier TEMPLATE explicit_template_type SCOPE | nested_name_specifier TEMPLATE explicit_template_type SCOPE
{ got_scope = $$ { got_scope = $$
= make_typename_type ($1, $3, tf_error); } = make_typename_type ($1, $3, tf_error | tf_parsing); }
/* Error handling per Core 125. */ /* Error handling per Core 125. */
| nested_name_specifier IDENTIFIER SCOPE | nested_name_specifier IDENTIFIER SCOPE
{ got_scope = $$ { got_scope = $$
= make_typename_type ($1, $2, tf_error); } = make_typename_type ($1, $2, tf_error | tf_parsing); }
| nested_name_specifier PTYPENAME SCOPE | nested_name_specifier PTYPENAME SCOPE
{ got_scope = $$ { got_scope = $$
= make_typename_type ($1, $2, tf_error); } = make_typename_type ($1, $2, tf_error | tf_parsing); }
; ;
/* Why the @#$%^& do type_name and notype_identifier need to be expanded /* Why the @#$%^& do type_name and notype_identifier need to be expanded
@ -3120,7 +3120,7 @@ typename_sub0:
typename_sub1 identifier %prec EMPTY typename_sub1 identifier %prec EMPTY
{ {
if (TYPE_P ($1)) if (TYPE_P ($1))
$$ = make_typename_type ($1, $2, tf_error); $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE) else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2); error ("`%T' is not a class or namespace", $2);
else else
@ -3133,9 +3133,9 @@ typename_sub0:
| typename_sub1 template_type %prec EMPTY | typename_sub1 template_type %prec EMPTY
{ $$ = TREE_TYPE ($2); } { $$ = TREE_TYPE ($2); }
| typename_sub1 explicit_template_type %prec EMPTY | typename_sub1 explicit_template_type %prec EMPTY
{ $$ = make_typename_type ($1, $2, tf_error); } { $$ = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type %prec EMPTY | typename_sub1 TEMPLATE explicit_template_type %prec EMPTY
{ $$ = make_typename_type ($1, $3, tf_error); } { $$ = make_typename_type ($1, $3, tf_error | tf_parsing); }
; ;
typename_sub1: typename_sub1:
@ -3149,7 +3149,7 @@ typename_sub1:
| typename_sub1 typename_sub2 | typename_sub1 typename_sub2
{ {
if (TYPE_P ($1)) if (TYPE_P ($1))
$$ = make_typename_type ($1, $2, tf_error); $$ = make_typename_type ($1, $2, tf_error | tf_parsing);
else if (TREE_CODE ($2) == IDENTIFIER_NODE) else if (TREE_CODE ($2) == IDENTIFIER_NODE)
error ("`%T' is not a class or namespace", $2); error ("`%T' is not a class or namespace", $2);
else else
@ -3161,10 +3161,10 @@ typename_sub1:
} }
| typename_sub1 explicit_template_type SCOPE | typename_sub1 explicit_template_type SCOPE
{ got_scope = $$ { got_scope = $$
= make_typename_type ($1, $2, tf_error); } = make_typename_type ($1, $2, tf_error | tf_parsing); }
| typename_sub1 TEMPLATE explicit_template_type SCOPE | typename_sub1 TEMPLATE explicit_template_type SCOPE
{ got_scope = $$ { got_scope = $$
= make_typename_type ($1, $3, tf_error); } = make_typename_type ($1, $3, tf_error | tf_parsing); }
; ;
/* This needs to return a TYPE_DECL for simple names so that we don't /* This needs to return a TYPE_DECL for simple names so that we don't

View File

@ -9844,10 +9844,10 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */ register_specialization for it. */
my_friendly_assert (unregistered, 0); my_friendly_assert (unregistered, 0);
if (TREE_CODE (decl) == VAR_DECL) if (DECL_CLASS_SCOPE_P (decl))
/* Make sure that we can see identifiers, and compute access /* Make sure that we can see identifiers, and compute access
correctly, for the class members used in the declaration of correctly, for the class members used in the declaration of
this static variable. */ this static variable or function. */
pushclass (DECL_CONTEXT (decl), 2); pushclass (DECL_CONTEXT (decl), 2);
/* Do the substitution to get the new declaration. */ /* Do the substitution to get the new declaration. */
@ -9859,8 +9859,6 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (new_decl) = DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args, tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl)); tf_error, DECL_TI_TEMPLATE (decl));
/* Pop the class context we pushed above. */
popclass ();
} }
else if (TREE_CODE (decl) == FUNCTION_DECL) else if (TREE_CODE (decl) == FUNCTION_DECL)
{ {
@ -9871,6 +9869,10 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (decl) = NULL_TREE; DECL_INITIAL (decl) = NULL_TREE;
} }
/* Pop the class context we pushed above. */
if (DECL_CLASS_SCOPE_P (decl))
popclass ();
/* The immediate parent of the new template is still whatever it was /* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most before, even though tsubst sets DECL_TI_TEMPLATE up as the most
general template. We also reset the DECL_ASSEMBLER_NAME since general template. We also reset the DECL_ASSEMBLER_NAME since
@ -10052,6 +10054,11 @@ instantiate_decl (d, defer_ok)
tree gen = DECL_TEMPLATE_RESULT (gen_tmpl); tree gen = DECL_TEMPLATE_RESULT (gen_tmpl);
tree type = TREE_TYPE (gen); tree type = TREE_TYPE (gen);
/* Make sure that we can see identifiers, and compute access
correctly. */
if (DECL_CLASS_SCOPE_P (d))
pushclass (DECL_CONTEXT (d), 1);
if (TREE_CODE (gen) == FUNCTION_DECL) if (TREE_CODE (gen) == FUNCTION_DECL)
{ {
tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d); tsubst (DECL_ARGUMENTS (gen), args, tf_error | tf_warning, d);
@ -10064,6 +10071,9 @@ instantiate_decl (d, defer_ok)
type = TREE_TYPE (type); type = TREE_TYPE (type);
} }
tsubst (type, args, tf_error | tf_warning, d); tsubst (type, args, tf_error | tf_warning, d);
if (DECL_CLASS_SCOPE_P (d))
popclass ();
} }
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d) if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)

View File

@ -971,8 +971,8 @@ friend_accessible_p (scope, decl, binfo)
return 0; return 0;
} }
/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE. /* Perform access control on TYPE_DECL or TEMPLATE_DECL VAL, which was
This is fairly complex, so here's the design: looked up in TYPE. This is fairly complex, so here's the design:
The lang_extdef nonterminal sets type_lookups to NULL_TREE before we The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
start to process a top-level declaration. start to process a top-level declaration.
@ -995,7 +995,8 @@ void
type_access_control (type, val) type_access_control (type, val)
tree type, val; tree type, val;
{ {
if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL if (val == NULL_TREE
|| (TREE_CODE (val) != TEMPLATE_DECL && TREE_CODE (val) != TYPE_DECL)
|| ! DECL_CLASS_SCOPE_P (val)) || ! DECL_CLASS_SCOPE_P (val))
return; return;

View File

@ -1,3 +1,13 @@
2002-07-22 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/7347, c++/7348
* g++.dg/template/access4.C: New test.
* g++.dg/template/access5.C: New test.
* g++.old-deja/g++.pt/memtemp85.C: Fix access problem.
* g++.old-deja/g++.pt/memtemp86.C: Likewise.
* g++.old-deja/g++.pt/ttp58.C: Likewise.
* g++.old-deja/g++.pt/memtemp89.C: Remove XFAIL.
2002-07-22 Jakub Jelinek <jakub@redhat.com> 2002-07-22 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/gnu89-init-2.c: New test. * gcc.dg/gnu89-init-2.c: New test.

View File

@ -0,0 +1,18 @@
// { dg-do compile }
// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
// PR c++/7347
// Access control for typename during instantiation
template <int dim> class Base {
protected:
typedef int T;
};
template <int dim> class D : public Base<dim> {
public:
typedef typename Base<dim>::T T1;
D (T1 t);
};
D<2> d(1);

View File

@ -0,0 +1,21 @@
// { dg-do compile }
// Origin: Wolfgang Bangerth <wolfgang.bangerth@iwr.uni-heidelberg.de>
// PR c++/7348
// Access control for typename in function return type
class Outer {
template <int dim> struct Inner {
typedef int T;
T foo ();
};
public:
Outer();
};
template <int dim>
typename Outer::Inner<dim>::T Outer::Inner<dim>::foo () {
return 1;
};
template Outer::Inner<2>;

View File

@ -4,7 +4,7 @@
// by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc. // by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
// Copyright (C) 1999 Free Software Foundation // Copyright (C) 1999 Free Software Foundation
class Q { struct Q {
template<class> template<class>
class X { class X {
}; };

View File

@ -4,7 +4,7 @@
// by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc. // by Paul Burchard <burchard@pobox.com>, Level Set Systems, Inc.
// Copyright (C) 1999 Free Software Foundation // Copyright (C) 1999 Free Software Foundation
class Q { struct Q {
template<class> template<class>
class X { class X {
}; };

View File

@ -5,11 +5,11 @@
class Q { class Q {
template<class T> template<class T>
class X { class X { // ERROR - Q::X private
}; };
}; };
template<template<class> class XX> template<template<class> class XX>
class Y { class Y {
XX<int> x_; // ERROR - Q::X inaccessible XFAIL *-*-* XX<int> x_;
}; };
Y<Q::X> y; // ERROR - instantiated from here XFAIL *-*-* Y<Q::X> y; // ERROR - instantiated from here

View File

@ -15,7 +15,7 @@ struct Z
const static int value_ = false; const static int value_ = false;
}; };
class Outer struct Outer
{ {
template <class T> template <class T>
struct A : struct A :