aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2009-11-23 13:29:50 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2009-11-23 14:29:50 +0100
commitaa373032bfd895dc6eb671308b68163f2971ffd2 (patch)
tree89a5ca8d719266689c7a82d65e3492021cebf4ec /gcc/cp
parent75d05d2ab74bf3d2fd9ceac0d7b2e45a75aae0bb (diff)
downloadgcc-aa373032bfd895dc6eb671308b68163f2971ffd2.zip
gcc-aa373032bfd895dc6eb671308b68163f2971ffd2.tar.gz
gcc-aa373032bfd895dc6eb671308b68163f2971ffd2.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog38
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/cp-objcp-common.c2
-rw-r--r--gcc/cp/cp-tree.def10
-rw-r--r--gcc/cp/cp-tree.h47
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/cp/pt.c109
-rw-r--r--gcc/cp/semantics.c57
-rw-r--r--gcc/cp/tree.c3
9 files changed, 208 insertions, 68 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b9f1cbe..3f28a94 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b4c8176c..70a5b1e 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 <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);
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index da6f829..f06ad5b8 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 28ecc5b..c71f94c 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 8838770..c6de2b4 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 7f5a688..db289b5 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 0a19444..2e58ed9 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<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);
-
- if (decl == type_decl && type_scope == scope)
- return;
- }
+ 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;
- 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 7401593..34b5d57 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 f9e1cd7..d431b31 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;