diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ff5509e..3b01573 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -696,18 +696,18 @@ struct GTY (()) tree_lambda_expr
 
    In bar, the triplet will be (myint, foo, #1).
    */
-struct GTY(()) qualified_typedef_usage_s {
-  tree typedef_decl;
+struct GTY(()) qualified_type_usage_s {
+  tree type_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);
+typedef struct qualified_type_usage_s qualified_type_usage_t;
+DEF_VEC_O (qualified_type_usage_t);
+DEF_VEC_ALLOC_O (qualified_type_usage_t,gc);
 
 struct GTY(()) tree_template_info {
   struct tree_common common;
-  VEC(qualified_typedef_usage_t,gc) *typedefs_needing_access_checking;
+  VEC(qualified_type_usage_t,gc) *types_needing_access_checking;
 };
 
 enum cp_tree_node_structure_enum {
@@ -2609,9 +2609,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
 #endif
 /* The list of typedefs - used in the template - that need
    access checking at template instantiation time.  */
-#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \
+#define TI_TYPES_NEEDING_ACCESS_CHECKING(NODE) \
   ((struct tree_template_info*)TEMPLATE_INFO_CHECK \
-     (NODE))->typedefs_needing_access_checking
+     (NODE))->types_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
@@ -4093,6 +4093,9 @@ extern int function_depth;
    sizeof can be nested.  */
 
 extern int cp_unevaluated_operand;
+extern int cp_parsing_class_head;
+extern bool cp_no_type_access_check_p;
+
 extern tree cp_convert_range_for (tree, tree, tree);
 
 /* in pt.c  */
@@ -5142,6 +5145,8 @@ 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,
 						      location_t);
+extern void defer_type_access_check_for_cur_template (tree, tree, location_t);
+extern void schedule_deferred_access_check_types_for_template (tree);
 extern tree splice_late_return_type		(tree, tree);
 extern bool is_auto				(const_tree);
 extern tree process_template_parm		(tree, location_t, tree, 
@@ -5181,7 +5186,7 @@ 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 VEC(qualified_typedef_usage_t,gc)* get_types_needing_access_check (tree);
+extern VEC(qualified_type_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);
@@ -5436,8 +5441,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 add_type_decl_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 c125f05..eef727b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3251,10 +3251,10 @@ 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
+  /* If we are currently parsing a template and if T is 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);
+  add_type_decl_to_current_template_for_access_check (t, context, input_location);
 
   if (want_template)
     return lookup_template_class (t, TREE_OPERAND (fullname, 1),
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 84b8c60..91ab816 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -254,6 +254,9 @@ int cp_unevaluated_operand;
 /* Dump up to NUM tokens in BUFFER to FILE.  If NUM is 0, dump all the
    tokens.  */
 
+int cp_parsing_class_head = 0;
+bool cp_no_type_access_check_p = false;
+
 void
 cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
 {
@@ -13243,7 +13246,14 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	{
 	  tree decl;
 	  tree ambiguous_decls;
-
+	  bool saved_cp_no_type_access_check_p = cp_no_type_access_check_p;
+
+	  /* So if we are parsing a friend template declaration, then
+	     we should make sure that looking up the name of the
+	     declaration doesn't schedule it for type access checking
+	     at the time of instantiation of the current containing
+	     template class, if any.  */
+	  cp_no_type_access_check_p = is_friend;
 	  decl = cp_parser_lookup_name (parser, identifier,
 					tag_type,
 					/*is_template=*/false,
@@ -13251,6 +13261,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 					/*check_dependency=*/true,
 					&ambiguous_decls,
 					token->location);
+	  cp_no_type_access_check_p = saved_cp_no_type_access_check_p;
 
 	  /* If the lookup was ambiguous, an error will already have been
 	     issued.  */
@@ -17071,6 +17082,13 @@ cp_parser_class_specifier_1 (cp_parser* parser)
 			       &nested_name_specifier_p,
 			       &attributes,
 			       &bases);
+  /* We have parsed the class head, so now we have the resulting TYPE.
+     If TYPE is a template, then we can stuff if with the type
+     references that need access checking at its instantiation time.
+     These access checks were deferred in cp_parser_class_head because
+     TYPE was not available yet.  */
+  schedule_deferred_access_check_types_for_template (type);
+
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
   if (!type)
@@ -17389,13 +17407,17 @@ cp_parser_class_head (cp_parser* parser,
      type.  */
   num_templates = 0;
   parser->colon_corrects_to_scope_p = false;
+  cp_parsing_class_head++;
 
   *bases = NULL_TREE;
 
   /* Look for the class-key.  */
   class_key = cp_parser_class_key (parser);
   if (class_key == none_type)
-    return error_mark_node;
+    {
+      type = error_mark_node;
+      goto out;
+    }
 
   /* Parse the attributes.  */
   attributes = cp_parser_attributes_opt (parser);
@@ -17764,6 +17786,7 @@ cp_parser_class_head (cp_parser* parser,
   if (type && (virt_specifiers & VIRT_SPEC_FINAL))
     CLASSTYPE_FINAL (type) = 1;
  out:
+  cp_parsing_class_head--;
   parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
   return type;
 }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9ab110a..fb4ab24 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -94,6 +94,10 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
+/*  A vector of types that needs to be scheduled for access check when
+    the current template being parsed becomes available.  */
+static GTY (()) VEC(qualified_type_usage_t,gc) *cur_template_deferred_types_to_access_check;
+
 /* Contains canonical template parameter types. The vector is indexed by
    the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
    TREE_LIST, whose TREE_VALUEs contain the canonical template
@@ -197,7 +201,7 @@ static tree tsubst_expr	(tree, tree, tsubst_flags_t, tree, bool);
 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 perform_types_access_check (tree tmpl, tree targs);
 static void append_type_to_template_for_access_check_1 (tree, tree, tree,
 							location_t);
 static tree listify (tree);
@@ -8376,18 +8380,18 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
     }
 }
 
-/* Perform (or defer) access check for typedefs that were referenced
+/* Perform (or defer) access check for types that were referenced
    from within the template TMPL code.
    This is a subroutine of instantiate_template and instantiate_class_template.
    TMPL is the template to consider and TARGS is the list of arguments of
    that template.  */
 
 static void
-perform_typedefs_access_check (tree tmpl, tree targs)
+perform_types_access_check (tree tmpl, tree targs)
 {
   location_t saved_location;
   int i;
-  qualified_typedef_usage_t *iter;
+  qualified_type_usage_t *iter;
 
   if (!tmpl
       || (!CLASS_TYPE_P (tmpl)
@@ -8395,11 +8399,11 @@ perform_typedefs_access_check (tree tmpl, tree targs)
     return;
 
   saved_location = input_location;
-  FOR_EACH_VEC_ELT (qualified_typedef_usage_t,
+  FOR_EACH_VEC_ELT (qualified_type_usage_t,
 		    get_types_needing_access_check (tmpl),
 		    i, iter)
     {
-      tree type_decl = iter->typedef_decl;
+      tree type_decl = iter->type_decl;
       tree type_scope = iter->context;
 
       if (!type_decl || !type_scope || !CLASS_TYPE_P (type_scope))
@@ -8905,7 +8909,7 @@ instantiate_class_template_1 (tree type)
      checked at template instantiation time, i.e now. These types were
      added to the template at parsing time. Let's get those and perform
      the access checks then.  */
-  perform_typedefs_access_check (pattern, args);
+  perform_types_access_check (pattern, args);
   perform_deferred_access_checks ();
   pop_nested_class ();
   maximum_field_alignment = saved_maximum_field_alignment;
@@ -14159,7 +14163,7 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      checked at template instantiation time, i.e now. These types were
      added to the template at parsing time. Let's get those and perfom
      the acces checks then.  */
-  perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
+  perform_types_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
   perform_deferred_access_checks ();
   pop_access_scope (fndecl);
   pop_deferring_access_checks ();
@@ -19912,11 +19916,11 @@ type_uses_auto (tree type)
    Those typedefs were added to T by the function
    append_type_to_template_for_access_check.  */
 
-VEC(qualified_typedef_usage_t,gc)*
+VEC(qualified_type_usage_t,gc)*
 get_types_needing_access_check (tree t)
 {
   tree ti;
-  VEC(qualified_typedef_usage_t,gc) *result = NULL;
+  VEC(qualified_type_usage_t,gc) *result = NULL;
 
   if (!t || t == error_mark_node)
     return NULL;
@@ -19930,7 +19934,7 @@ get_types_needing_access_check (tree t)
       if (!TI_TEMPLATE (ti))
 	return NULL;
 
-      result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
+      result = TI_TYPES_NEEDING_ACCESS_CHECKING (ti);
     }
 
   return result;
@@ -19953,7 +19957,7 @@ append_type_to_template_for_access_check_1 (tree t,
 					    tree scope,
 					    location_t location)
 {
-  qualified_typedef_usage_t typedef_usage;
+  qualified_type_usage_t type_usage;
   tree ti;
 
   if (!t || t == error_mark_node)
@@ -19970,13 +19974,13 @@ append_type_to_template_for_access_check_1 (tree t,
 
   gcc_assert (TI_TEMPLATE (ti));
 
-  typedef_usage.typedef_decl = type_decl;
-  typedef_usage.context = scope;
-  typedef_usage.locus = location;
+  type_usage.type_decl = type_decl;
+  type_usage.context = scope;
+  type_usage.locus = location;
 
-  VEC_safe_push (qualified_typedef_usage_t, gc,
-		 TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti),
-		 &typedef_usage);
+  VEC_safe_push (qualified_type_usage_t, gc,
+		 TI_TYPES_NEEDING_ACCESS_CHECKING (ti),
+		 &type_usage);
 }
 
 /* Append TYPE_DECL to the template TEMPL.
@@ -20014,16 +20018,16 @@ append_type_to_template_for_access_check (tree templ,
 					  tree scope,
 					  location_t location)
 {
-  qualified_typedef_usage_t *iter;
+  qualified_type_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_EACH_VEC_ELT (qualified_typedef_usage_t,
+  FOR_EACH_VEC_ELT (qualified_type_usage_t,
 		    get_types_needing_access_check (templ),
 		    i, iter)
-    if (iter->typedef_decl == type_decl && scope == iter->context)
+    if (iter->type_decl == type_decl && scope == iter->context)
       return;
 
   append_type_to_template_for_access_check_1 (templ, type_decl,
@@ -20060,4 +20064,50 @@ print_template_statistics (void)
 	   htab_collisions (type_specializations));
 }
 
+/* Save the type access check of T through SCOPE, so that it can be
+   scheduled later when
+   schedule_deferred_access_check_types_for_template is called.  */
+
+void
+defer_type_access_check_for_cur_template (tree t, tree scope, location_t location)
+{
+  qualified_type_usage_t type_usage;
+
+  if (t == NULL_TREE || TREE_CODE (t) != TYPE_DECL)
+    return;
+
+  type_usage.type_decl = t;
+  type_usage.context = scope;
+  type_usage.locus = location;
+
+  VEC_safe_push (qualified_type_usage_t, gc,
+		 cur_template_deferred_types_to_access_check,
+		 &type_usage);
+}
+
+/* Add the type access checks stashed away by
+   defer_type_access_check_for_cur_template to the list of type
+   access checks to be done at the instantiation time of TEMPL.  */
+
+void
+schedule_deferred_access_check_types_for_template (tree templ)
+{
+  int i;
+  qualified_type_usage_t *type_usage;
+
+  FOR_EACH_VEC_ELT (qualified_type_usage_t,
+		    cur_template_deferred_types_to_access_check,
+		    i, type_usage)
+    append_type_to_template_for_access_check (templ, type_usage->type_decl,
+					      type_usage->context,
+					      type_usage->locus);
+
+  if (cur_template_deferred_types_to_access_check != NULL)
+    {
+      VEC_free (qualified_type_usage_t, gc,
+		cur_template_deferred_types_to_access_check);
+      cur_template_deferred_types_to_access_check = NULL;
+    }
+}
+
 #include "gt-cp-pt.h"
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 59b25e5..99f5e83 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1606,35 +1606,52 @@ 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.  */
+/* If we are currently parsing a template and we encountered a type
+   decl DECL that is being accessed though CONTEXT, this function adds
+   that DECL to a list tied to the current template.  At template
+   instantiatin time, that list is walked and access check performed
+   for each DECL.
+
+   Note that if we are parsing a class head or a list
+   of template parameters, there is no "current template" defined yet.
+   In that case, the function stashes DECL away, until the "current
+   template" is built and
+   schedule_deferred_access_check_types_for_template is called.
+
+   LOCATION is the location of the usage point of DECL.  */
 
 void
-add_typedef_to_current_template_for_access_check (tree typedef_decl,
-                                                  tree context,
-						  location_t location)
+add_type_decl_to_current_template_for_access_check (tree decl,
+						    tree context,
+						    location_t location)
 {
     tree template_info = NULL;
     tree cs = current_scope ();
 
-    if (!is_typedef_decl (typedef_decl)
+    if (decl == NULL_TREE
+	|| TREE_CODE (decl) != TYPE_DECL
 	|| !context
 	|| !CLASS_TYPE_P (context)
-	|| !cs)
+	|| cp_no_type_access_check_p
+	|| (at_namespace_scope_p ()
+	    && !cp_parsing_class_head)
+	|| currently_open_class (context)
+	|| currently_open_class (TREE_TYPE (decl)))
       return;
 
+    if ((cp_parsing_class_head && processing_template_decl)
+	|| processing_template_parmlist)
+      {
+	defer_type_access_check_for_cur_template (decl, context, location);
+	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);
+	&& TI_TEMPLATE (template_info))
+      append_type_to_template_for_access_check (cs, decl, context, location);
 }
 
 /* DECL was the declaration to which a qualified-id resolved.  Issue
@@ -1651,15 +1668,15 @@ check_accessibility_of_qualified_id (tree decl,
   tree scope;
   tree qualifying_type = NULL_TREE;
 
-  /* If we are parsing a template declaration and if decl is a typedef,
+  /* If we are parsing a template declaration and if decl is a TYPE_DECL,
      add it to a list tied to the template.
      At template instantiation time, that list will be walked and
      access check performed.  */
-  add_typedef_to_current_template_for_access_check (decl,
-						    nested_name_specifier
-						    ? nested_name_specifier
-						    : DECL_CONTEXT (decl),
-						    input_location);
+  add_type_decl_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/testsuite/g++.dg/lto/20081219_1.C b/gcc/testsuite/g++.dg/lto/20081219_1.C
index 1bb96ef..9e80836 100644
--- a/gcc/testsuite/g++.dg/lto/20081219_1.C
+++ b/gcc/testsuite/g++.dg/lto/20081219_1.C
@@ -9,6 +9,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
   typedef int *__c_locale;
   class locale
   {
+  public:
     class facet;
   };
   class locale::facet
diff --git a/gcc/testsuite/g++.dg/lto/20091002-1_0.C b/gcc/testsuite/g++.dg/lto/20091002-1_0.C
index c63b079..025939d 100644
--- a/gcc/testsuite/g++.dg/lto/20091002-1_0.C
+++ b/gcc/testsuite/g++.dg/lto/20091002-1_0.C
@@ -14,6 +14,7 @@ namespace std __attribute__ ((__visibility__ ("default")))
   template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
       class num_get;
   class locale   {
+  public:
       class facet;
   };
   class locale::facet   {
diff --git a/gcc/testsuite/g++.dg/template/access23.C b/gcc/testsuite/g++.dg/template/access23.C
new file mode 100644
index 0000000..b9c9d49
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access23.C
@@ -0,0 +1,33 @@
+class C
+{
+  struct Private { }; // { dg-error "is private" }
+};
+
+template<typename T>
+struct exploit1
+{
+  typedef C::Private type; // { dg-error "in this context" }
+};
+
+template<typename T>
+struct exploit2 : C::Private  // { dg-error "in this context" }
+{
+};
+
+template<typename T>
+struct exploit3
+{
+  C::Private a; // { dg-error "in this context" }
+};
+
+template<typename T>
+struct exploit4
+{
+  template<class U = C::Private> // { dg-error "in this context" }
+  struct E {};
+};
+
+exploit1<int>::type x1;
+exploit2<int> x2;
+exploit3<int> x3;
+exploit4<int>::E<> x4;
