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:
parent
75d05d2ab7
commit
aa373032bf
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
109
gcc/cp/pt.c
109
gcc/cp/pt.c
@ -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. */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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>;
|
||||
|
18
gcc/testsuite/g++.dg/template/typedef22.C
Normal file
18
gcc/testsuite/g++.dg/template/typedef22.C
Normal 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> ();
|
Loading…
Reference in New Issue
Block a user