diff options
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/class.c | 54 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/init6.C | 31 |
6 files changed, 98 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1ed12d6..b386ef4 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 86dbcca..bd89b55 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 bcd115d..1c66e11 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 4a6c627..02fc272 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 d901d41..62deeda 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 0000000..1437466 --- /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*>(); +} |