On Fri, 25 Nov 2016, Jakub Jelinek wrote: > Hi! > > IPA-ICF performs some code-generation visible changes from hash table > traversal, where the hash values can be different between -g and -g0 > (I bet it hashes DECL_UID in somewhere, perhaps other things). > The following patch fixes it by adding a vector next to the hash table, > which tracks the groups in the order they were created. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Richard. > 2016-11-25 Jakub Jelinek <ja...@redhat.com> > > PR lto/78211 > * ipa-icf.h (sem_item_optimizer): Add m_classes_vec member. > * ipa-icf.c (sem_item_optimizer::sem_item_optimizer): Initialize > it. > (sem_item_optimizer::~sem_item_optimizer): Traverse m_classes_vec > vector instead of traversing m_classes hash table. Release > m_classes_vec. > (sem_item_optimizer::read_section, sem_item_optimizer::add_class): > Formatting fixes. > (sem_item_optimizer::get_group_by_hash): When inserting a new group, > add it also to m_classes_vec vector. > (sem_item_optimizer::remove_symtab_node, > sem_item_optimizer::build_hash_based_classes, > sem_item_optimizer::parse_nonsingleton_classes): Formatting fixes. > (sem_item_optimizer::subdivide_classes_by_equality, > sem_item_optimizer::subdivide_classes_by_sensitive_refs, > sem_item_optimizer::verify_classes): Traverse m_classes_vec vector > instead of traversing m_classes hash table. Formatting fixes. > (sem_item_optimizer::traverse_congruence_split, > sem_item_optimizer::do_congruence_step_for_index, > sem_item_optimizer::do_congruence_step): Formatting fixes. > (sem_item_optimizer::process_cong_reduction): Traverse m_classes_vec > vector instead of traversing m_classes hash table. > (sem_item_optimizer::dump_cong_classes): Likewise. Formatting fixes. > (sem_item_optimizer::merge_classes): Traverse m_classes_vec vector > instead of traversing m_classes hash table. > > * g++.dg/ipa/pr78211.C: New test. > > --- gcc/ipa-icf.h.jj 2016-11-22 11:05:58.000000000 +0100 > +++ gcc/ipa-icf.h 2016-11-25 11:41:18.210144897 +0100 > @@ -609,9 +609,12 @@ private: > /* A set containing all items removed by hooks. */ > hash_set <symtab_node *> m_removed_items_set; > > - /* Hashtable of congruence classes */ > + /* Hashtable of congruence classes. */ > hash_table <congruence_class_group_hash> m_classes; > > + /* Vector of congruence classes. */ > + vec <congruence_class_group *> m_classes_vec; > + > /* Count of congruence classes. */ > unsigned int m_classes_count; > > --- gcc/ipa-icf.c.jj 2016-11-22 11:05:58.000000000 +0100 > +++ gcc/ipa-icf.c 2016-11-25 12:05:31.765505438 +0100 > @@ -2284,6 +2284,7 @@ sem_item_optimizer::sem_item_optimizer ( > m_varpool_node_hooks (NULL) > { > m_items.create (0); > + m_classes_vec.create (0); > bitmap_obstack_initialize (&m_bmstack); > } > > @@ -2292,17 +2293,19 @@ sem_item_optimizer::~sem_item_optimizer > for (unsigned int i = 0; i < m_items.length (); i++) > delete m_items[i]; > > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > { > - for (unsigned int i = 0; i < (*it)->classes.length (); i++) > - delete (*it)->classes[i]; > + for (unsigned int i = 0; i < it->classes.length (); i++) > + delete it->classes[i]; > > - (*it)->classes.release (); > - free (*it); > + it->classes.release (); > + free (it); > } > > m_items.release (); > + m_classes_vec.release (); > > bitmap_obstack_release (&m_bmstack); > } > @@ -2361,8 +2364,8 @@ void > sem_item_optimizer::read_section (lto_file_decl_data *file_data, > const char *data, size_t len) > { > - const lto_function_header *header = > - (const lto_function_header *) data; > + const lto_function_header *header > + = (const lto_function_header *) data; > const int cfg_offset = sizeof (lto_function_header); > const int main_offset = cfg_offset + header->cfg_size; > const int string_offset = main_offset + header->main_size; > @@ -2373,9 +2376,9 @@ sem_item_optimizer::read_section (lto_fi > lto_input_block ib_main ((const char *) data + main_offset, 0, > header->main_size, file_data->mode_table); > > - data_in = > - lto_data_in_create (file_data, (const char *) data + string_offset, > - header->string_size, vNULL); > + data_in > + = lto_data_in_create (file_data, (const char *) data + string_offset, > + header->string_size, vNULL); > > count = streamer_read_uhwi (&ib_main); > > @@ -2473,9 +2476,9 @@ sem_item_optimizer::add_class (congruenc > { > gcc_assert (cls->members.length ()); > > - congruence_class_group *group = get_group_by_hash ( > - cls->members[0]->get_hash (), > - cls->members[0]->type); > + congruence_class_group *group > + = get_group_by_hash (cls->members[0]->get_hash (), > + cls->members[0]->type); > group->classes.safe_push (cls); > } > > @@ -2495,6 +2498,7 @@ sem_item_optimizer::get_group_by_hash (h > else > { > item->classes.create (1); > + m_classes_vec.safe_push (item); > *slot = item; > } > > @@ -2524,7 +2528,7 @@ sem_item_optimizer::varpool_removal_hook > void > sem_item_optimizer::remove_symtab_node (symtab_node *node) > { > - gcc_assert (!m_classes.elements()); > + gcc_assert (!m_classes.elements ()); > > m_removed_items_set.add (node); > } > @@ -2752,8 +2756,8 @@ sem_item_optimizer::build_hash_based_cla > { > sem_item *item = m_items[i]; > > - congruence_class_group *group = get_group_by_hash (item->get_hash (), > - item->type); > + congruence_class_group *group > + = get_group_by_hash (item->get_hash (), item->type); > > if (!group->classes.length ()) > { > @@ -2827,8 +2831,10 @@ sem_item_optimizer::parse_nonsingleton_c > } > > if (dump_file) > - fprintf (dump_file, "Init called for %u items (%.2f%%).\n", > init_called_count, > - m_items.length () ? 100.0f * init_called_count / m_items.length > (): 0.0f); > + fprintf (dump_file, "Init called for %u items (%.2f%%).\n", > + init_called_count, > + m_items.length () ? 100.0f * init_called_count / m_items.length () > + : 0.0f); > } > > /* Equality function for semantic items is used to subdivide existing > @@ -2837,14 +2843,15 @@ sem_item_optimizer::parse_nonsingleton_c > void > sem_item_optimizer::subdivide_classes_by_equality (bool in_wpa) > { > - for (hash_table <congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > { > - unsigned int class_count = (*it)->classes.length (); > + unsigned int class_count = it->classes.length (); > > for (unsigned i = 0; i < class_count; i++) > { > - congruence_class *c = (*it)->classes [i]; > + congruence_class *c = it->classes[i]; > > if (c->members.length() > 1) > { > @@ -2853,14 +2860,15 @@ sem_item_optimizer::subdivide_classes_by > sem_item *first = c->members[0]; > new_vector.safe_push (first); > > - unsigned class_split_first = (*it)->classes.length (); > + unsigned class_split_first = it->classes.length (); > > for (unsigned j = 1; j < c->members.length (); j++) > { > sem_item *item = c->members[j]; > > - bool equals = in_wpa ? first->equals_wpa (item, > - m_symtab_node_map) : first->equals (item, > m_symtab_node_map); > + bool equals > + = in_wpa ? first->equals_wpa (item, m_symtab_node_map) > + : first->equals (item, m_symtab_node_map); > > if (equals) > new_vector.safe_push (item); > @@ -2868,16 +2876,18 @@ sem_item_optimizer::subdivide_classes_by > { > bool integrated = false; > > - for (unsigned k = class_split_first; k < > (*it)->classes.length (); k++) > + for (unsigned k = class_split_first; > + k < it->classes.length (); k++) > { > - sem_item *x = (*it)->classes[k]->members[0]; > - bool equals = in_wpa ? x->equals_wpa (item, > - > m_symtab_node_map) : x->equals (item, m_symtab_node_map); > + sem_item *x = it->classes[k]->members[0]; > + bool equals > + = in_wpa ? x->equals_wpa (item, m_symtab_node_map) > + : x->equals (item, m_symtab_node_map); > > if (equals) > { > integrated = true; > - add_item_to_class ((*it)->classes[k], item); > + add_item_to_class (it->classes[k], item); > > break; > } > @@ -2885,16 +2895,18 @@ sem_item_optimizer::subdivide_classes_by > > if (!integrated) > { > - congruence_class *c = new congruence_class > (class_id++); > + congruence_class *c > + = new congruence_class (class_id++); > m_classes_count++; > add_item_to_class (c, item); > > - (*it)->classes.safe_push (c); > + it->classes.safe_push (c); > } > } > } > > - // we replace newly created new_vector for the class we've just > splitted > + // We replace newly created new_vector for the class we've just > + // splitted. > c->members.release (); > c->members.create (new_vector.length ()); > > @@ -2919,15 +2931,16 @@ sem_item_optimizer::subdivide_classes_by > > unsigned newly_created_classes = 0; > > - for (hash_table <congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > { > - unsigned int class_count = (*it)->classes.length (); > + unsigned int class_count = it->classes.length (); > auto_vec<congruence_class *> new_classes; > > for (unsigned i = 0; i < class_count; i++) > { > - congruence_class *c = (*it)->classes [i]; > + congruence_class *c = it->classes[i]; > > if (c->members.length() > 1) > { > @@ -2937,11 +2950,12 @@ sem_item_optimizer::subdivide_classes_by > { > sem_item *source_node = c->members[j]; > > - symbol_compare_collection *collection = new > symbol_compare_collection (source_node->node); > + symbol_compare_collection *collection > + = new symbol_compare_collection (source_node->node); > > bool existed; > - vec <sem_item *> *slot = &split_map.get_or_insert (collection, > - &existed); > + vec <sem_item *> *slot > + = &split_map.get_or_insert (collection, &existed); > gcc_checking_assert (slot); > > slot->safe_push (source_node); > @@ -2950,8 +2964,8 @@ sem_item_optimizer::subdivide_classes_by > delete collection; > } > > - /* If the map contains more than one key, we have to split the > map > - appropriately. */ > + /* If the map contains more than one key, we have to split > + the map appropriately. */ > if (split_map.elements () != 1) > { > bool first_class = true; > @@ -2970,7 +2984,7 @@ sem_item_optimizer::subdivide_classes_by > > if (first_class) > { > - (*it)->classes[i] = new_cls; > + it->classes[i] = new_cls; > first_class = false; > } > else > @@ -2992,7 +3006,7 @@ sem_item_optimizer::subdivide_classes_by > } > > for (unsigned i = 0; i < new_classes.length (); i++) > - (*it)->classes.safe_push (new_classes[i]); > + it->classes.safe_push (new_classes[i]); > } > > return newly_created_classes; > @@ -3012,12 +3026,13 @@ sem_item_optimizer::checking_verify_clas > void > sem_item_optimizer::verify_classes (void) > { > - for (hash_table <congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > { > - for (unsigned int i = 0; i < (*it)->classes.length (); i++) > + for (unsigned int i = 0; i < it->classes.length (); i++) > { > - congruence_class *cls = (*it)->classes[i]; > + congruence_class *cls = it->classes[i]; > > gcc_assert (cls); > gcc_assert (cls->members.length () > 0); > @@ -3032,8 +3047,8 @@ sem_item_optimizer::verify_classes (void > for (unsigned k = 0; k < item->usages.length (); k++) > { > sem_usage_pair *usage = item->usages[k]; > - gcc_assert (usage->item->index_in_class < > - usage->item->cls->members.length ()); > + gcc_assert (usage->item->index_in_class > + < usage->item->cls->members.length ()); > } > } > } > @@ -3061,7 +3076,8 @@ sem_item_optimizer::release_split_map (c > > bool > sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls, > - bitmap const &b, traverse_split_pair *pair) > + bitmap const &b, > + traverse_split_pair *pair) > { > sem_item_optimizer *optimizer = pair->optimizer; > const congruence_class *splitter_cls = pair->cls; > @@ -3103,7 +3119,7 @@ sem_item_optimizer::traverse_congruence_ > g.hash = cls->members[0]->get_hash (); > g.type = cls->members[0]->type; > > - congruence_class_group *slot = optimizer->m_classes.find(&g); > + congruence_class_group *slot = optimizer->m_classes.find (&g); > > for (unsigned int i = 0; i < slot->classes.length (); i++) > if (slot->classes[i] == cls) > @@ -3126,9 +3142,10 @@ sem_item_optimizer::traverse_congruence_ > optimizer->worklist_push (newclasses[i]); > else /* Just smaller class is inserted. */ > { > - unsigned int smaller_index = newclasses[0]->members.length () < > - newclasses[1]->members.length () ? > - 0 : 1; > + unsigned int smaller_index > + = (newclasses[0]->members.length () > + < newclasses[1]->members.length () > + ? 0 : 1); > optimizer->worklist_push (newclasses[smaller_index]); > } > > @@ -3156,7 +3173,7 @@ sem_item_optimizer::traverse_congruence_ > > void > sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls, > - unsigned int index) > + unsigned int index) > { > hash_map <congruence_class *, bitmap> split_map; > > @@ -3184,8 +3201,8 @@ sem_item_optimizer::do_congruence_step_f > b = *slot; > > gcc_checking_assert (usage->item->cls); > - gcc_checking_assert (usage->item->index_in_class < > - usage->item->cls->members.length ()); > + gcc_checking_assert (usage->item->index_in_class > + < usage->item->cls->members.length ()); > > bitmap_set_bit (b, usage->item->index_in_class); > } > @@ -3196,12 +3213,12 @@ sem_item_optimizer::do_congruence_step_f > pair.cls = cls; > > splitter_class_removed = false; > - split_map.traverse > - <traverse_split_pair *, sem_item_optimizer::traverse_congruence_split> > (&pair); > + split_map.traverse <traverse_split_pair *, > + sem_item_optimizer::traverse_congruence_split> (&pair); > > /* Bitmap clean-up. */ > - split_map.traverse > - <traverse_split_pair *, sem_item_optimizer::release_split_map> (NULL); > + split_map.traverse <traverse_split_pair *, > + sem_item_optimizer::release_split_map> (NULL); > } > > /* Every usage of a congruence class CLS is a candidate that can split the > @@ -3222,8 +3239,8 @@ sem_item_optimizer::do_congruence_step ( > EXECUTE_IF_SET_IN_BITMAP (usage, 0, i, bi) > { > if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, " processing congruence step for class: %u, > index: %u\n", > - cls->id, i); > + fprintf (dump_file, " processing congruence step for class: %u, " > + "index: %u\n", cls->id, i); > > do_congruence_step_for_index (cls, i); > > @@ -3281,11 +3298,12 @@ sem_item_optimizer::worklist_pop (void) > void > sem_item_optimizer::process_cong_reduction (void) > { > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > - for (unsigned i = 0; i < (*it)->classes.length (); i++) > - if ((*it)->classes[i]->is_class_used ()) > - worklist_push ((*it)->classes[i]); > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > + for (unsigned i = 0; i < it->classes.length (); i++) > + if (it->classes[i]->is_class_used ()) > + worklist_push (it->classes[i]); > > if (dump_file) > fprintf (dump_file, "Worklist has been filled with: %lu\n", > @@ -3317,19 +3335,20 @@ sem_item_optimizer::dump_cong_classes (v > return; > > fprintf (dump_file, > - "Congruence classes: %u (unique hash values: %lu), with total: %u > items\n", > - m_classes_count, (unsigned long) m_classes.elements(), > m_items.length ()); > + "Congruence classes: %u (unique hash values: %lu), with total: " > + "%u items\n", m_classes_count, > + (unsigned long) m_classes.elements (), m_items.length ()); > > /* Histogram calculation. */ > unsigned int max_index = 0; > unsigned int* histogram = XCNEWVEC (unsigned int, m_items.length () + 1); > > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > - > - for (unsigned i = 0; i < (*it)->classes.length (); i++) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > + for (unsigned i = 0; i < it->classes.length (); i++) > { > - unsigned int c = (*it)->classes[i]->members.length (); > + unsigned int c = it->classes[i]->members.length (); > histogram[c]++; > > if (c > max_index) > @@ -3337,7 +3356,8 @@ sem_item_optimizer::dump_cong_classes (v > } > > fprintf (dump_file, > - "Class size histogram [num of members]: number of classe number of > classess\n"); > + "Class size histogram [num of members]: number of classe number " > + "of classess\n"); > > for (unsigned int i = 0; i <= max_index; i++) > if (histogram[i]) > @@ -3347,16 +3367,16 @@ sem_item_optimizer::dump_cong_classes (v > > > if (dump_flags & TDF_DETAILS) > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > { > - fprintf (dump_file, " group: with %u classes:\n", > (*it)->classes.length ()); > + fprintf (dump_file, " group: with %u classes:\n", > + it->classes.length ()); > > - for (unsigned i = 0; i < (*it)->classes.length (); i++) > + for (unsigned i = 0; i < it->classes.length (); i++) > { > - (*it)->classes[i]->dump (dump_file, 4); > + it->classes[i]->dump (dump_file, 4); > > - if(i < (*it)->classes.length () - 1) > + if (i < it->classes.length () - 1) > fprintf (dump_file, " "); > } > } > @@ -3381,11 +3401,12 @@ sem_item_optimizer::merge_classes (unsig > > bool merged_p = false; > > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > - for (unsigned int i = 0; i < (*it)->classes.length (); i++) > + unsigned int l; > + congruence_class_group *it; > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > + for (unsigned int i = 0; i < it->classes.length (); i++) > { > - congruence_class *c = (*it)->classes[i]; > + congruence_class *c = it->classes[i]; > if (c->members.length () > 1) > { > non_singular_classes_count++; > @@ -3410,11 +3431,10 @@ sem_item_optimizer::merge_classes (unsig > item_count ? 100.0f * equal_items / item_count : 0.0f); > } > > - for (hash_table<congruence_class_group_hash>::iterator it = > m_classes.begin (); > - it != m_classes.end (); ++it) > - for (unsigned int i = 0; i < (*it)->classes.length (); i++) > + FOR_EACH_VEC_ELT (m_classes_vec, l, it) > + for (unsigned int i = 0; i < it->classes.length (); i++) > { > - congruence_class *c = (*it)->classes[i]; > + congruence_class *c = it->classes[i]; > > if (c->members.length () == 1) > continue; > --- gcc/testsuite/g++.dg/ipa/pr78211.C.jj 2016-11-25 12:16:44.643933656 > +0100 > +++ gcc/testsuite/g++.dg/ipa/pr78211.C 2016-11-25 12:17:42.972190613 > +0100 > @@ -0,0 +1,120 @@ > +// PR lto/78211 > +// { dg-do compile { target { lto && c++11 } } } > +// { dg-options "-fcompare-debug -fno-printf-return-value -flto > -fno-use-linker-plugin -O3" } > + > +namespace std { > + typedef __SIZE_TYPE__ size_t; > + inline namespace __cxx11 { } > + template<typename...> using __void_t = void; > + template<class _E> > + class initializer_list { > + typedef size_t size_type; > + typedef const _E* iterator; > + iterator _M_array; > + size_type _M_len; > + }; > +} > +extern "C++" { > + namespace std { > + template<typename _Tp> struct __is_char { enum { __value = 1 }; }; > + } > + namespace __gnu_cxx { > + template<bool, typename> struct __enable_if { }; > + template<typename _Tp> struct __enable_if<true, _Tp> { typedef _Tp > __type; }; > + } > +} > +namespace std { > + template<typename _Iterator, typename = __void_t<>> struct > __iterator_traits { }; > + template<typename _Iterator> struct iterator_traits : public > __iterator_traits<_Iterator> { }; > + template<typename _Tp> struct iterator_traits<_Tp*> { typedef _Tp& > reference; }; > +} > +namespace __gnu_cxx { > + using std::iterator_traits; > + template<typename _Iterator, typename _Container> class __normal_iterator { > + typedef iterator_traits<_Iterator> __traits_type; > + public: > + typedef typename __traits_type::reference reference; > + reference operator*() const noexcept { } > + }; > + template<typename _IteratorL, typename _IteratorR, typename _Container> > + inline bool operator!=(const __normal_iterator<_IteratorL, _Container>& > __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept { } > +} > +namespace std { > + template<typename _CharT> struct char_traits; > + template<typename> class allocator; > + template<typename _Alloc> struct allocator_traits { }; > + template<typename _Tp> struct allocator_traits<allocator<_Tp>> { > + using const_pointer = const _Tp*; > + template<typename _Up> using rebind_alloc = allocator<_Up>; > + }; > +} > +namespace __gnu_cxx { > + template<typename _Alloc> struct __alloc_traits : > std::allocator_traits<_Alloc> { > + typedef std::allocator_traits<_Alloc> _Base_type; > + template<typename _Tp> struct rebind { > + typedef typename _Base_type::template rebind_alloc<_Tp> other; > + }; > + }; > +} > +namespace std { > + namespace __cxx11 { > + template<typename _CharT, typename _Traits = char_traits<_CharT>, > typename _Alloc = allocator<_CharT> > class basic_string; > + typedef basic_string<char> string; > + } > + template<typename _CharT> inline typename > __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type > + operator==(const basic_string<_CharT>& __lhs, const basic_string<_CharT>& > __rhs) noexcept { } > + template<typename _Tp, typename _Alloc> struct _Vector_base { > + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template > rebind<_Tp>::other _Tp_alloc_type; > + }; > + template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class > vector { > + typedef _Vector_base<_Tp, _Alloc> _Base; > + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; > + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; > + public: > + typedef typename _Alloc_traits::const_pointer const_pointer; > + typedef __gnu_cxx::__normal_iterator<const_pointer, vector> > const_iterator; > + const_iterator end() const noexcept { } > + }; > +} > +class VwViewPlane; > +class VwViewer { > + std::vector<VwViewPlane*> mViewPlaneList; > + VwViewPlane* FindViewPlane (const std::string& name); > + const VwViewPlane* FindViewPlane (const std::string& name) const; > +}; > +class VwAssimilatorStickyBox; > +class VwViewer_2D final { > + VwAssimilatorStickyBox* mp_stickyAssimilator; > + void drawStickyBox(); > + void undrawStickyBox(); > +}; > +struct VwViewPlane { > + const std::string& GetName() const { } > +}; > +struct VwAssimilator_2D { > + virtual int DrawNext() = 0; > +}; > +class VwAssimilator_2D_Geometry : public VwAssimilator_2D { }; > +class VwAssimilatorStickyBox final : public VwAssimilator_2D_Geometry { }; > +VwViewPlane* VwViewer::FindViewPlane (const std::string& name) { > + VwViewPlane* p_result = __null; > + std::vector<VwViewPlane*>::const_iterator it; > + while (it != mViewPlaneList.end()) { > + if ((*it) -> GetName() == name ) break; > + } > + return p_result; > +} > +const VwViewPlane* VwViewer::FindViewPlane (const std::string& name) const { > + VwViewPlane* p_result = __null; > + std::vector<VwViewPlane*>::const_iterator it; > + while (it != mViewPlaneList.end()) { > + if ((*it) -> GetName() == name ) break; > + } > + return p_result; > +} > +void VwViewer_2D::drawStickyBox() { > + mp_stickyAssimilator->DrawNext(); > +} > +void VwViewer_2D::undrawStickyBox() { > + mp_stickyAssimilator->DrawNext(); > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)