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]

C++ PATCH: PR 28536


This patch fixes PR c++/28536.

I'm somewhat surprised we never saw a problem like this before.  The
problem was that when we called push_to_top_level (to instantiate a
template class), we failed to empty the current_class_stack.  As a
result, we considered classes on the stack as "currently open", which
means that, for example, typename types referencing those classes
should be resolved.  This lead to confusion in the attached test case,
in that Iter<Graph<int>::Node*> was considered the same as
Iter<typename Graph<T>::Node*>; we then got a non-dependent class with
a basetype that was a TYPENAME_TYPE.

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.0/4.1 branches.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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  Mark Mitchell  <mark@codesourcery.com>

	PR c++/25836
	* g++.dg/template/init6.C: New test.

Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 109736)
+++ gcc/cp/class.c	(working copy)
@@ -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;
 }
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 109736)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -3748,6 +3748,8 @@ extern tree cp_fold_obj_type_ref		(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);
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 109736)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -5016,6 +5016,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);
 }
@@ -5031,6 +5032,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;
 
Index: gcc/testsuite/g++.dg/template/init6.C
===================================================================
--- gcc/testsuite/g++.dg/template/init6.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/init6.C	(revision 0)
@@ -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*>();
+}


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