From aa373032bfd895dc6eb671308b68163f2971ffd2 Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Mon, 23 Nov 2009 13:29:50 +0000 Subject: [PATCH] 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 : 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 --- gcc/cp/ChangeLog | 38 ++++++++ gcc/cp/call.c | 2 +- gcc/cp/cp-objcp-common.c | 2 + gcc/cp/cp-tree.def | 10 ++ gcc/cp/cp-tree.h | 47 +++++++++- gcc/cp/decl.c | 8 +- gcc/cp/pt.c | 109 ++++++++++++++-------- gcc/cp/semantics.c | 57 ++++++----- gcc/cp/tree.c | 3 +- gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/g++.dg/template/typedef13.C | 4 +- gcc/testsuite/g++.dg/template/typedef19.C | 4 +- gcc/testsuite/g++.dg/template/typedef20.C | 4 +- gcc/testsuite/g++.dg/template/typedef22.C | 18 ++++ 14 files changed, 240 insertions(+), 74 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/typedef22.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b9f1cbebbfb..3f28a949906 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,41 @@ +2009-11-23 Dodji Seketeli + + PR c++/14777 + * cp-tree.def : 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 PR c++/9050, DR 147, DR 318 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b4c8176c626..70a5b1efbf5 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2581,7 +2581,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, for this will point at template template <> S::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); diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index da6f8291ba4..f06ad5b86c8 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -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 (); } diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 28ecc5bf681..c71f94caa61 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 88387705a1b..c6de2b488d9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7f5a688873b..db289b50197 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0a194440ae6..2e58ed9e757 100644 --- a/gcc/cp/pt.c +++ b/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 struct S { - C::myint mi; + C::myint mi; // <-- usage point of the typedef C::myint }; S 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. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 7401593bcc6..34b5d574d07 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index f9e1cd707a9..d431b3109a6 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9aafea5a7e3..3a5389090ad 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2009-11-23 Dodji Seketeli + + 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 PR target/42113 diff --git a/gcc/testsuite/g++.dg/template/typedef13.C b/gcc/testsuite/g++.dg/template/typedef13.C index aa8bb326829..a22e1cb11ca 100644 --- a/gcc/testsuite/g++.dg/template/typedef13.C +++ b/gcc/testsuite/g++.dg/template/typedef13.C @@ -8,8 +8,8 @@ class A }; template class B : public A -{ // { dg-error "within this context" } - mytype mem; +{ + mytype mem; // { dg-error "within this context" } }; B b; // { dg-message "instantiated from here" } diff --git a/gcc/testsuite/g++.dg/template/typedef19.C b/gcc/testsuite/g++.dg/template/typedef19.C index f576d4828e4..2fac20ea065 100644 --- a/gcc/testsuite/g++.dg/template/typedef19.C +++ b/gcc/testsuite/g++.dg/template/typedef19.C @@ -14,8 +14,8 @@ class B : public A template class B : public A -{ // { dg-error "within this context" } - mytype mem; +{ + mytype mem; // { dg-error "within this context" } }; B b; diff --git a/gcc/testsuite/g++.dg/template/typedef20.C b/gcc/testsuite/g++.dg/template/typedef20.C index a5cbdeb236b..c768ce0a78a 100644 --- a/gcc/testsuite/g++.dg/template/typedef20.C +++ b/gcc/testsuite/g++.dg/template/typedef20.C @@ -18,9 +18,9 @@ struct y : public x template struct y : 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; diff --git a/gcc/testsuite/g++.dg/template/typedef22.C b/gcc/testsuite/g++.dg/template/typedef22.C new file mode 100644 index 00000000000..e3ecfcb3673 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef22.C @@ -0,0 +1,18 @@ +// Contributed by Dodji Seketeli +// Origin: PR c++/14777 +// { dg-do compile } + +template +struct B +{ +protected: + typedef int M; // { dg-error "protected" } +}; + +template +struct A : B { + typedef typename B::M N; // { dg-error "context" } + A (int = N ()); +}; + +A a = A ();