This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PR c++/141777


On Thu, Nov 19, 2009 at 03:18:32PM -0500, Jason Merrill wrote:
> On 11/19/2009 01:15 PM, Dodji Seketeli wrote:
>> The reason why I went for a tree node is that quite some places expect
>> template_info to be a tree. So it was much easier to just wrap it in a tree.
>> Should I go ahead nevertheless and use template_info_s instead?
>
> Please.

While trying to go that route, it appeared that template_info for enums
(accessed using ENUM_TEMPLATE_INFO) are stored in TYPE_LANG_SLOT_1 which is
TREE_NODE::type.binfo. Changing that to a struct template_info_s would be quite
disruptive, so I believe it argues in favour of the TEMPLATE_INFO tree
route instead.

As we discussed on IRC I have updated the patch to slim the
tree_template_info struct by using TREE_TYPE and TREE_CHAIN of the
TEMPLATE_INFO to store the template decl and args.

Tested against trunk on x86_64-unknown-linux-gnu.

        Dodji

commit 2c259705ed231fd887a074ed14c1b06ac071d102
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Mon Nov 16 22:29:06 2009 +0100

    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.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4a6bca..137b4bb 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2579,7 +2579,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..f06ad5b 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 a71dc73..f6ac5b6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -600,6 +600,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,
@@ -614,6 +642,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
 };
 
@@ -636,6 +665,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;
 };
 
 
@@ -2408,12 +2439,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
@@ -4775,7 +4808,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, 
@@ -4809,8 +4843,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);
@@ -5038,6 +5073,8 @@ extern void emit_associated_thunks		(tree);
 extern void finish_mem_initializers		(tree);
 extern tree check_template_template_default_arg (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 73bf995..73a836f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3075,6 +3075,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,
@@ -6696,7 +6701,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)
@@ -12838,6 +12843,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 b7d72c1..f332d10 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;
@@ -4352,7 +4364,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),
@@ -4471,7 +4483,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);
@@ -6409,7 +6421,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,
@@ -6485,7 +6497,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;
@@ -7341,17 +7353,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;
@@ -7361,9 +7380,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
@@ -8615,7 +8638,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)
 	  {
@@ -8844,7 +8867,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);
 
@@ -9258,7 +9281,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)
@@ -9867,7 +9890,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;
@@ -18040,28 +18063,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);
     }
@@ -18075,6 +18099,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.  */
@@ -18082,8 +18107,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)
@@ -18100,14 +18127,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:
 
@@ -18118,7 +18151,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;
@@ -18135,25 +18168,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 c1df24b..c83b796 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;
diff --git a/gcc/testsuite/g++.dg/template/typedef13.C b/gcc/testsuite/g++.dg/template/typedef13.C
index aa8bb32..a22e1cb 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 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" }
diff --git a/gcc/testsuite/g++.dg/template/typedef19.C b/gcc/testsuite/g++.dg/template/typedef19.C
index f576d48..2fac20e 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 T>
 class B<T*> : public A
-{ // { dg-error "within this context" }
-  mytype mem;
+{
+  mytype mem; // { dg-error "within this context" }
 };
 
 B<int*> b;
diff --git a/gcc/testsuite/g++.dg/template/typedef20.C b/gcc/testsuite/g++.dg/template/typedef20.C
index a5cbdeb..c768ce0 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<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>;
diff --git a/gcc/testsuite/g++.dg/template/typedef22.C b/gcc/testsuite/g++.dg/template/typedef22.C
new file mode 100644
index 0000000..e3ecfcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef22.C
@@ -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> ();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]