diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1ed12d615e8d02f677bad859a1e2fac5d2155b81..b386ef4e66fd7682fb3487d958af474db7fb27e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2006-01-18  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/25836
+	* cp-tree.h (push_class_stack): New function.
+	(pop_class_stack): Likewise.
+	* class.c (class_stack_node): Add hidden field.
+	(pushclass): Clear it.
+	(push_class_stack): New function.
+	(pop_class_stack): Likewise.
+	(currently_open_class): Ignore hidden classes.
+	(currently_open_derived_class): Likewise.
+	* name-lookup.c (push_to_top_level): Call push_class_stack.
+	(pop_from_top_level): Call pop_class_stack.
+
 2006-01-18  Kazu Hirata  <kazu@codesourcery.com>
 
 	* tree.c (find_tree_t, find_tree): Remove.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 86dbcca14e62ba06a1af4846852716b3c5e1ef24..bd89b558abda430f7c24b7dc2f5cebdc3d59d906 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -60,6 +60,10 @@ typedef struct class_stack_node {
 
   /* If were defining TYPE, the names used in this class.  */
   splay_tree names_used;
+
+  /* Nonzero if this class is no longer open, because of a call to
+     push_to_top_level.  */
+  size_t hidden;
 }* class_stack_node_t;
 
 typedef struct vtbl_init_data_s
@@ -5387,6 +5391,8 @@ restore_class_cache (void)
 void
 pushclass (tree type)
 {
+  class_stack_node_t csn;
+
   type = TYPE_MAIN_VARIANT (type);
 
   /* Make sure there is enough room for the new entry on the stack.  */
@@ -5399,10 +5405,12 @@ pushclass (tree type)
     }
 
   /* Insert a new entry on the class stack.  */
-  current_class_stack[current_class_depth].name = current_class_name;
-  current_class_stack[current_class_depth].type = current_class_type;
-  current_class_stack[current_class_depth].access = current_access_specifier;
-  current_class_stack[current_class_depth].names_used = 0;
+  csn = current_class_stack + current_class_depth;
+  csn->name = current_class_name;
+  csn->type = current_class_type;
+  csn->access = current_access_specifier;
+  csn->names_used = 0;
+  csn->hidden = 0;
   current_class_depth++;
 
   /* Now set up the new type.  */
@@ -5459,6 +5467,24 @@ popclass (void)
     splay_tree_delete (current_class_stack[current_class_depth].names_used);
 }
 
+/* Mark the top of the class stack as hidden.  */
+
+void
+push_class_stack (void)
+{
+  if (current_class_depth)
+    ++current_class_stack[current_class_depth - 1].hidden;
+}
+
+/* Mark the top of the class stack as un-hidden.  */
+
+void
+pop_class_stack (void)
+{
+  if (current_class_depth)
+    --current_class_stack[current_class_depth - 1].hidden;
+}
+
 /* Returns 1 if current_class_type is either T or a nested type of T.
    We start looking from 1 because entry 0 is from global scope, and has
    no type.  */
@@ -5469,10 +5495,14 @@ currently_open_class (tree t)
   int i;
   if (current_class_type && same_type_p (t, current_class_type))
     return 1;
-  for (i = 1; i < current_class_depth; ++i)
-    if (current_class_stack[i].type
-	&& same_type_p (current_class_stack [i].type, t))
-      return 1;
+  for (i = current_class_depth - 1; i > 0; --i)
+    {
+      if (current_class_stack[i].hidden)
+	break;
+      if (current_class_stack[i].type
+	  && same_type_p (current_class_stack [i].type, t))
+	return 1;
+    }
   return 0;
 }
 
@@ -5496,8 +5526,12 @@ currently_open_derived_class (tree t)
     return current_class_type;
 
   for (i = current_class_depth - 1; i > 0; --i)
-    if (DERIVED_FROM_P (t, current_class_stack[i].type))
-      return current_class_stack[i].type;
+    {
+      if (current_class_stack[i].hidden)
+	break;
+      if (DERIVED_FROM_P (t, current_class_stack[i].type))
+	return current_class_stack[i].type;
+    }
 
   return NULL_TREE;
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bcd115dddf1ad7d2dbcea9b4545d125ad3038faa..1c66e11aedc784870b3a47f9538f80856f2f3466 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3748,6 +3748,8 @@ extern tree cp_fold_obj_type_ref		(tree, tree);
 extern void set_linkage_according_to_type	(tree, tree);
 extern void determine_key_method		(tree);
 extern void check_for_override			(tree, tree);
+extern void push_class_stack                    (void);
+extern void pop_class_stack                     (void);
 
 /* in cvt.c */
 extern tree convert_to_reference		(tree, tree, int, int, tree);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 4a6c627a72806ab02f13e7b23ab477e3aa7c99aa..02fc27277a310912c9aad7a8c20b129b434b6d3d 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4938,6 +4938,7 @@ push_to_top_level (void)
   current_lang_base = VEC_alloc (tree, gc, 10);
   current_lang_name = lang_name_cplusplus;
   current_namespace = global_namespace;
+  push_class_stack ();
   skip_evaluation = 0;
   timevar_pop (TV_NAME_LOOKUP);
 }
@@ -4953,6 +4954,7 @@ pop_from_top_level (void)
   /* Clear out class-level bindings cache.  */
   if (previous_class_level)
     invalidate_class_lookup_cache ();
+  pop_class_stack ();
 
   current_lang_base = 0;
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d901d41476800d00f34ed5677d4b225151b5b903..62deedaff30ae00b544737fe262328c7ca15e1ca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-01-18  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/25836
+	* g++.dg/template/init6.C: New test.
+
 2006-01-18  Daniel Berlin  <dberlin@dberlin.org>
 
 	* gcc.dg/tree-ssa/pr24287.c: New test
diff --git a/gcc/testsuite/g++.dg/template/init6.C b/gcc/testsuite/g++.dg/template/init6.C
new file mode 100644
index 0000000000000000000000000000000000000000..143746642fcb1df1e85dff50f28dd9d8100d6f35
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/init6.C
@@ -0,0 +1,31 @@
+// PR c++/25836
+
+template <class T>
+class Iter {};
+
+template <class T>
+class SubIter : public Iter<T> {
+  void insert(T);
+};
+
+class GraphBase {
+public:
+  class Node;
+};
+
+template<class T>
+class Graph : public GraphBase {
+  class Inner {
+    Iter<typename Graph<T>::Node*> *get();
+  };
+};
+
+template<class T>
+Iter<typename Graph<T>::Node*> *Graph<T>::Inner::get() {
+  SubIter<typename Graph<T>::Node*> *iter;
+  iter->insert(0);
+}
+
+int main() {
+  Iter<Graph<int>::Node*> *n2_iter = new SubIter<Graph<int>::Node*>();
+}