re PR c++/14777 (typedef doesn't fully expose base class type)

Fix PR c++/14777

gcc/cp/ChangeLog:

	PR c++/14777
	* cp-tree.def <TEMPLATE_INFO>: Declare new kind of tree
	node.
	* cp-tree.h (struct tree_template_info,
	struct qualified_typedef_usage_s): New.
	(cp_tree_node_structure_enum): add TS_CP_TEMPLATE_INFO.
	(union lang_tree_node): Add template_info.
	(TI_TEMPLATE, TI_ARGS, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING):
	Adjust.
	(build_template_info): Declare.
	(get_types_needing_access_check): Adjust return type.
	(add_typedef_to_current_template_for_access_check): Declare.
	* cp-objcp-common.c (cp_tree_size): Handle TEMPLATE_INFO.
	* semantics.c (add_typedef_to_current_template_for_access_check):
	Split from ...
	(check_accessibility_of_qualified_id): ... here.
	* decl.c (make_typename_type): Use it.
	* pt.c (build_template_info): Define.
	(check_explicit_specialization, find_parameter_packs_r,
	push_template_decl_real, lookup_template_class,
	for_each_template_parm_r, tsubst_decl, tsubst): Use
	build_template_info.
	(get_types_needing_access_check): Adjust return type.
	(append_type_to_template_for_access_check_1): Record the
	location of the usage point of the typedef. Adjust to TEMPLATE_INFO.
	(append_type_to_template_for_access_check): Add new location
	parameter. Pass it to append_type_to_template_for_access_check_1.
	Adjust to TEMPLATE_INFO.
	(perform_typedefs_access_check): Temporarily set input_location to
	the usage point of the typedef we are checking access for. Adjust
	to new TEMPLATE_INFO tree node.
	* tree.c (bind_template_template_parm): Use build_template_info.
	* call.c (add_template_candidate_real): Likewise.
	* decl.c (grokfndecl): Likewise.
	(cp_tree_node_structure): Handle TEMPLATE_INFO.

gcc/testsuite/ChangeLog:

	PR c++/14777
	* g++.dg/template/typedef13.C: Adjust.
	* g++.dg/template/typedef19.C: Adjust.
	* g++.dg/template/typedef20.C: Adjust.
	* g++.dg/template/typedef22.C: New test.

From-SVN: r154443
This commit is contained in:
Dodji Seketeli 2009-11-23 13:29:50 +00:00 committed by Dodji Seketeli
parent 75d05d2ab7
commit aa373032bf
14 changed files with 240 additions and 74 deletions

View File

@ -1,3 +1,41 @@
2009-11-23 Dodji Seketeli <dodji@redhat.com>
PR c++/14777
* cp-tree.def <TEMPLATE_INFO>: Declare new kind of tree
node.
* cp-tree.h (struct tree_template_info,
struct qualified_typedef_usage_s): New.
(cp_tree_node_structure_enum): add TS_CP_TEMPLATE_INFO.
(union lang_tree_node): Add template_info.
(TI_TEMPLATE, TI_ARGS, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING):
Adjust.
(build_template_info): Declare.
(get_types_needing_access_check): Adjust return type.
(add_typedef_to_current_template_for_access_check): Declare.
* cp-objcp-common.c (cp_tree_size): Handle TEMPLATE_INFO.
* semantics.c (add_typedef_to_current_template_for_access_check):
Split from ...
(check_accessibility_of_qualified_id): ... here.
* decl.c (make_typename_type): Use it.
* pt.c (build_template_info): Define.
(check_explicit_specialization, find_parameter_packs_r,
push_template_decl_real, lookup_template_class,
for_each_template_parm_r, tsubst_decl, tsubst): Use
build_template_info.
(get_types_needing_access_check): Adjust return type.
(append_type_to_template_for_access_check_1): Record the
location of the usage point of the typedef. Adjust to TEMPLATE_INFO.
(append_type_to_template_for_access_check): Add new location
parameter. Pass it to append_type_to_template_for_access_check_1.
Adjust to TEMPLATE_INFO.
(perform_typedefs_access_check): Temporarily set input_location to
the usage point of the typedef we are checking access for. Adjust
to new TEMPLATE_INFO tree node.
* tree.c (bind_template_template_parm): Use build_template_info.
* call.c (add_template_candidate_real): Likewise.
* decl.c (grokfndecl): Likewise.
(cp_tree_node_structure): Handle TEMPLATE_INFO.
2009-11-20 Jason Merrill <jason@redhat.com>
PR c++/9050, DR 147, DR 318

View File

@ -2581,7 +2581,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
for this will point at template <class T> template <> S<T>::f(int),
so that we can find the definition. For the purposes of
overload resolution, however, we want the original TMPL. */
cand->template_decl = tree_cons (tmpl, targs, NULL_TREE);
cand->template_decl = build_template_info (tmpl, targs);
else
cand->template_decl = DECL_TEMPLATE_INFO (fn);

View File

@ -140,6 +140,8 @@ cp_tree_size (enum tree_code code)
case LAMBDA_EXPR: return sizeof (struct tree_lambda_expr);
case TEMPLATE_INFO: return sizeof (struct tree_template_info);
default:
gcc_unreachable ();
}

View File

@ -439,6 +439,16 @@ DEFTREECODE (LAMBDA_EXPR, "lambda_expr", tcc_exceptional, 0)
DECLTYPE_FOR_LAMBDA_RETURN is set if we want lambda return deduction. */
DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
/* Used to represent the template information stored by template
specializations.
The accessors are:
TI_TEMPLATE the template declaration associated to the specialization
TI_ARGS the arguments of the template specialization
TI_TYPEDEFS_NEEDING_ACCESS_CHECKING the vector of typedefs used in
the pattern of the template for which access check is needed at template
instantiation time. */
DEFTREECODE (TEMPLATE_INFO, "template_info", tcc_exceptional, 0)
/*
Local variables:
mode:c

View File

@ -633,6 +633,34 @@ struct GTY (()) tree_lambda_expr
int discriminator;
};
/* A (typedef,context,usage location) triplet.
It represents a typedef used through a
context at a given source location.
e.g.
struct foo {
typedef int myint;
};
struct bar {
foo::myint v; // #1<-- this location.
};
In bar, the triplet will be (myint, foo, #1).
*/
struct GTY(()) qualified_typedef_usage_s {
tree typedef_decl;
tree context;
location_t locus;
};
typedef struct qualified_typedef_usage_s qualified_typedef_usage_t;
DEF_VEC_O (qualified_typedef_usage_t);
DEF_VEC_ALLOC_O (qualified_typedef_usage_t,gc);
struct GTY(()) tree_template_info {
struct tree_common common;
VEC(qualified_typedef_usage_t,gc) *typedefs_needing_access_checking;
};
enum cp_tree_node_structure_enum {
TS_CP_GENERIC,
TS_CP_IDENTIFIER,
@ -647,6 +675,7 @@ enum cp_tree_node_structure_enum {
TS_CP_ARGUMENT_PACK_SELECT,
TS_CP_TRAIT_EXPR,
TS_CP_LAMBDA_EXPR,
TS_CP_TEMPLATE_INFO,
LAST_TS_CP_ENUM
};
@ -669,6 +698,8 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
trait_expression;
struct tree_lambda_expr GTY ((tag ("TS_CP_LAMBDA_EXPR")))
lambda_expression;
struct tree_template_info GTY ((tag ("TS_CP_TEMPLATE_INFO")))
template_info;
};
@ -2441,12 +2472,14 @@ extern void decl_shadowed_for_var_insert (tree, tree);
? (ENUM_TEMPLATE_INFO (NODE) = (VAL)) \
: (CLASSTYPE_TEMPLATE_INFO (NODE) = (VAL)))
#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE))
#define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* The list of typedefs - used in the template - that need
access checking at template instantiation time. */
#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) (TREE_CHAIN (NODE))
#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \
((struct tree_template_info*)TEMPLATE_INFO_CHECK \
(NODE))->typedefs_needing_access_checking
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@ -4809,7 +4842,8 @@ extern tree check_explicit_specialization (tree, tree, int, int);
extern tree make_auto (void);
extern tree do_auto_deduction (tree, tree, tree);
extern tree type_uses_auto (tree);
extern void append_type_to_template_for_access_check (tree, tree, tree);
extern void append_type_to_template_for_access_check (tree, tree, tree,
location_t);
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern tree process_template_parm (tree, location_t, tree,
@ -4843,8 +4877,9 @@ extern bool function_parameter_pack_p (const_tree);
extern bool function_parameter_expanded_from_pack_p (tree, tree);
extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern tree build_template_info (tree, tree);
extern tree get_template_info (const_tree);
extern tree get_types_needing_access_check (tree);
extern VEC(qualified_typedef_usage_t,gc)* get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
@ -5073,6 +5108,8 @@ extern void finish_mem_initializers (tree);
extern tree check_template_template_default_arg (tree);
extern bool expand_or_defer_fn_1 (tree);
extern void expand_or_defer_fn (tree);
extern void add_typedef_to_current_template_for_access_check (tree, tree,
location_t);
extern void check_accessibility_of_qualified_id (tree, tree, tree);
extern tree finish_qualified_id_expr (tree, tree, bool, bool,
bool, bool);

View File

@ -3089,6 +3089,11 @@ 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, t);
/* If we are currently parsing a template and if T is a typedef accessed
through CONTEXT then we need to remember and check access of T at
template instantiation time. */
add_typedef_to_current_template_for_access_check (t, context, input_location);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
@ -6713,7 +6718,7 @@ grokfndecl (tree ctype,
}
gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == OVERLOAD);
DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
@ -12881,6 +12886,7 @@ cp_tree_node_structure (union lang_tree_node * t)
case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT;
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
default: return TS_CP_GENERIC;
}
}

View File

@ -189,7 +189,8 @@ static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree);
static void append_type_to_template_for_access_check_1 (tree, tree, tree,
location_t);
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static tree listify (tree);
static tree listify_autos (tree, tree);
@ -286,6 +287,17 @@ finish_member_template_decl (tree decl)
return error_mark_node;
}
/* Create a template info node. */
tree
build_template_info (tree template_decl, tree template_args)
{
tree result = make_node (TEMPLATE_INFO);
TI_TEMPLATE (result) = template_decl;
TI_ARGS (result) = template_args;
return result;
}
/* Return the template info node corresponding to T, whatever T is. */
tree
@ -2492,7 +2504,7 @@ check_explicit_specialization (tree declarator,
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
/* Inherit default function arguments from the template
DECL is specializing. */
@ -2900,7 +2912,7 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
case UNION_TYPE:
case ENUMERAL_TYPE:
if (TYPE_TEMPLATE_INFO (t))
cp_walk_tree (&TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
cp_walk_tree (&TI_ARGS (TYPE_TEMPLATE_INFO (t)),
&find_parameter_packs_r, ppd, ppd->visited);
*walk_subtrees = 0;
@ -4351,7 +4363,7 @@ push_template_decl_real (tree decl, bool is_friend)
DECL_TI_TEMPLATE (decl) = new_tmpl;
SET_DECL_TEMPLATE_SPECIALIZATION (new_tmpl);
DECL_TEMPLATE_INFO (new_tmpl)
= tree_cons (tmpl, args, NULL_TREE);
= build_template_info (tmpl, args);
register_specialization (new_tmpl,
most_general_template (tmpl),
@ -4470,7 +4482,7 @@ template arguments to %qD do not match original template %qD",
if (DECL_TEMPLATE_INFO (tmpl))
args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
info = tree_cons (tmpl, args, NULL_TREE);
info = build_template_info (tmpl, args);
if (DECL_IMPLICIT_TYPEDEF_P (decl))
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
@ -6448,7 +6460,7 @@ lookup_template_class (tree d1,
found = CLASSTYPE_TI_TEMPLATE (found);
}
SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
slot = (spec_entry **) htab_find_slot_with_hash (type_specializations,
@ -6524,7 +6536,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
case ENUMERAL_TYPE:
if (!TYPE_TEMPLATE_INFO (t))
*walk_subtrees = 0;
else if (for_each_template_parm (TREE_VALUE (TYPE_TEMPLATE_INFO (t)),
else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
fn, data, pfd->visited,
pfd->include_nondeduced_p))
return error_mark_node;
@ -7380,17 +7392,24 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
static void
perform_typedefs_access_check (tree tmpl, tree targs)
{
tree t;
location_t saved_location;
int i;
qualified_typedef_usage_t *iter;
if (!tmpl
|| (!CLASS_TYPE_P (tmpl)
&& TREE_CODE (tmpl) != FUNCTION_DECL))
return;
for (t = get_types_needing_access_check (tmpl); t; t = TREE_CHAIN (t))
saved_location = input_location;
for (i = 0;
VEC_iterate (qualified_typedef_usage_t,
get_types_needing_access_check (tmpl),
i, iter);
++i)
{
tree type_decl = TREE_PURPOSE (t);
tree type_scope = TREE_VALUE (t);
tree type_decl = iter->typedef_decl;
tree type_scope = iter->context;
if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
continue;
@ -7400,9 +7419,13 @@ perform_typedefs_access_check (tree tmpl, tree targs)
if (uses_template_parms (type_scope))
type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
/* Make access check error messages point to the location
of the use of the typedef. */
input_location = iter->locus;
perform_or_defer_access_check (TYPE_BINFO (type_scope),
type_decl, type_decl);
}
input_location = saved_location;
}
tree
@ -8654,7 +8677,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
if (TREE_CODE (decl) == TYPE_DECL)
{
@ -8883,7 +8906,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (gen_tmpl)
{
DECL_TEMPLATE_INFO (r)
= tree_cons (gen_tmpl, argvec, NULL_TREE);
= build_template_info (gen_tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec, false, hash);
@ -9297,7 +9320,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_EXTERNAL (r) = 1;
register_specialization (r, gen_tmpl, argvec, false, hash);
DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
else if (cp_unevaluated_operand)
@ -9906,7 +9929,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
= tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
= build_template_info (TYPE_TI_TEMPLATE (t), argvec);
}
}
break;
@ -18079,28 +18102,29 @@ type_uses_auto (tree type)
return NULL_TREE;
}
/* For a given template T, return the list of typedefs referenced
/* For a given template T, return the vector of typedefs referenced
in T for which access check is needed at T instantiation time.
T is either a FUNCTION_DECL or a RECORD_TYPE.
Those typedefs were added to T by the function
append_type_to_template_for_access_check. */
tree
VEC(qualified_typedef_usage_t,gc)*
get_types_needing_access_check (tree t)
{
tree ti, result = NULL_TREE;
tree ti;
VEC(qualified_typedef_usage_t,gc) *result = NULL;
if (!t || t == error_mark_node)
return t;
return NULL;
if (!(ti = get_template_info (t)))
return NULL_TREE;
return NULL;
if (CLASS_TYPE_P (t)
|| TREE_CODE (t) == FUNCTION_DECL)
{
if (!TI_TEMPLATE (ti))
return NULL_TREE;
return NULL;
result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
}
@ -18114,6 +18138,7 @@ get_types_needing_access_check (tree t)
T is either a FUNCTION_DECL or a RECORD_TYPE.
TYPE_DECL is a TYPE_DECL node representing a typedef.
SCOPE is the scope through which TYPE_DECL is accessed.
LOCATION is the location of the usage point of TYPE_DECL.
This function is a subroutine of
append_type_to_template_for_access_check. */
@ -18121,8 +18146,10 @@ get_types_needing_access_check (tree t)
static void
append_type_to_template_for_access_check_1 (tree t,
tree type_decl,
tree scope)
tree scope,
location_t location)
{
qualified_typedef_usage_t typedef_usage;
tree ti;
if (!t || t == error_mark_node)
@ -18139,14 +18166,20 @@ append_type_to_template_for_access_check_1 (tree t,
gcc_assert (TI_TEMPLATE (ti));
TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti) =
tree_cons (type_decl, scope, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti));
typedef_usage.typedef_decl = type_decl;
typedef_usage.context = scope;
typedef_usage.locus = location;
VEC_safe_push (qualified_typedef_usage_t, gc,
TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti),
&typedef_usage);
}
/* Append TYPE_DECL to the template TEMPL.
TEMPL is either a class type, a FUNCTION_DECL or a a TEMPLATE_DECL.
At TEMPL instanciation time, TYPE_DECL will be checked to see
if it can be accessed through SCOPE.
LOCATION is the location of the usage point of TYPE_DECL.
e.g. consider the following code snippet:
@ -18157,7 +18190,7 @@ append_type_to_template_for_access_check_1 (tree t,
template<class U> struct S
{
C::myint mi;
C::myint mi; // <-- usage point of the typedef C::myint
};
S<char> s;
@ -18174,25 +18207,25 @@ append_type_to_template_for_access_check_1 (tree t,
void
append_type_to_template_for_access_check (tree templ,
tree type_decl,
tree scope)
tree scope,
location_t location)
{
tree node;
qualified_typedef_usage_t *iter;
int i;
gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
/* Make sure we don't append the type to the template twice. */
for (node = get_types_needing_access_check (templ);
node;
node = TREE_CHAIN (node))
{
tree decl = TREE_PURPOSE (node);
tree type_scope = TREE_VALUE (node);
for (i = 0;
VEC_iterate (qualified_typedef_usage_t,
get_types_needing_access_check (templ),
i, iter);
++i)
if (iter->typedef_decl == type_decl && scope == iter->context)
return;
if (decl == type_decl && type_scope == scope)
return;
}
append_type_to_template_for_access_check_1 (templ, type_decl, scope);
append_type_to_template_for_access_check_1 (templ, type_decl,
scope, location);
}
/* Set up the hash tables for template instantiations. */

View File

@ -1531,6 +1531,37 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
}
}
/* If we are currently parsing a template and we encountered a typedef
TYPEDEF_DECL that is being accessed though CONTEXT, this function
adds the typedef to a list tied to the current template.
At tempate instantiatin time, that list is walked and access check
performed for each typedef.
LOCATION is the location of the usage point of TYPEDEF_DECL. */
void
add_typedef_to_current_template_for_access_check (tree typedef_decl,
tree context,
location_t location)
{
tree template_info = NULL;
tree cs = current_scope ();
if (!is_typedef_decl (typedef_decl)
|| !context
|| !CLASS_TYPE_P (context)
|| !cs)
return;
if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)
template_info = get_template_info (cs);
if (template_info
&& TI_TEMPLATE (template_info)
&& !currently_open_class (context))
append_type_to_template_for_access_check (cs, typedef_decl,
context, location);
}
/* DECL was the declaration to which a qualified-id resolved. Issue
an error message if it is not accessible. If OBJECT_TYPE is
non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the
@ -1549,27 +1580,11 @@ check_accessibility_of_qualified_id (tree decl,
add it to a list tied to the template.
At template instantiation time, that list will be walked and
access check performed. */
if (is_typedef_decl (decl))
{
/* This the scope through which type_decl is accessed.
It will be useful information later to do access check for
type_decl usage. */
tree scope = nested_name_specifier
? nested_name_specifier
: DECL_CONTEXT (decl);
tree templ_info = NULL;
tree cs = current_scope ();
if (cs && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL))
templ_info = get_template_info (cs);
if (templ_info
&& TI_TEMPLATE (templ_info)
&& scope
&& CLASS_TYPE_P (scope)
&& !currently_open_class (scope))
append_type_to_template_for_access_check (current_scope (), decl, scope);
}
add_typedef_to_current_template_for_access_check (decl,
nested_name_specifier
? nested_name_specifier
: DECL_CONTEXT (decl),
input_location);
/* If we're not checking, return immediately. */
if (deferred_access_no_check)

View File

@ -1490,8 +1490,7 @@ bind_template_template_parm (tree t, tree newargs)
TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
= tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
newargs, NULL_TREE);
= build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs);
TREE_TYPE (decl) = t2;
TYPE_NAME (t2) = decl;

View File

@ -1,3 +1,11 @@
2009-11-23 Dodji Seketeli <dodji@redhat.com>
PR c++/14777
* g++.dg/template/typedef13.C: Adjust.
* g++.dg/template/typedef19.C: Adjust.
* g++.dg/template/typedef20.C: Adjust.
* g++.dg/template/typedef22.C: New test.
2009-11-22 Uros Bizjak <ubizjak@gmail.com>
PR target/42113

View File

@ -8,8 +8,8 @@ class A
};
template <class T> class B : public A
{ // { dg-error "within this context" }
mytype mem;
{
mytype mem; // { dg-error "within this context" }
};
B<int> b; // { dg-message "instantiated from here" }

View File

@ -14,8 +14,8 @@ class B : public A
template<class T>
class B<T*> : public A
{ // { dg-error "within this context" }
mytype mem;
{
mytype mem; // { dg-error "within this context" }
};
B<int*> b;

View File

@ -18,9 +18,9 @@ struct y : public x
template<typename T>
struct y<T*> : public x
{ // { dg-error "within this context" }
{
typedef x::type good;
typedef x::privtype bad;
typedef x::privtype bad; // { dg-error "within this context" }
};
template class y<int>;

View File

@ -0,0 +1,18 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/14777
// { dg-do compile }
template <typename T>
struct B
{
protected:
typedef int M; // { dg-error "protected" }
};
template <typename T>
struct A : B<T> {
typedef typename B<char>::M N; // { dg-error "context" }
A (int = N ());
};
A<int> a = A<int> ();