GCC Bugzilla – Attachment 26323 Details for
Bug 51823
[DR 198] [DR 2204] reverse iterator returns uninitialized values
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
implement DR 198
51823.txt (text/plain), 12.85 KB, created by
Jonathan Wakely
on 2012-01-14 15:43:52 UTC
(
hide
)
Description:
implement DR 198
Filename:
MIME Type:
Creator:
Jonathan Wakely
Created:
2012-01-14 15:43:52 UTC
Size:
12.85 KB
patch
obsolete
>diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog >index fa87445..bbdad00 100644 >--- a/libstdc++-v3/ChangeLog >+++ b/libstdc++-v3/ChangeLog >@@ -1,3 +1,11 @@ >+2012-01-14 Jonathan Wakely <jwakely.gcc@gmail.com> >+ >+ PR libstdc++/51823 >+ * include/bits/stl_iterator.h (reverse_iterator): Implement DR 198, >+ disabling the auxiliary member for the library's own iterator types. >+ * testsuite/24_iterators/reverse_iterator/51823.cc: New. >+ * testsuite/24_iterators/reverse_iterator/51823-2.cc: New. >+ > 2012-01-13 François Dumont <fdumont@gcc.gnu.org> > > * include/bits/hashtable_policy.h (_Hash_node_base): New, use it as >diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h >index 624ae64..eae1ce2 100644 >--- a/libstdc++-v3/include/bits/stl_iterator.h >+++ b/libstdc++-v3/include/bits/stl_iterator.h >@@ -75,6 +75,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > * @{ > */ > >+ template<typename _Iterator> >+ struct __cache_rev_iter_deref >+ { >+ static const bool __value = true; >+ }; >+ template<typename _Iterator> >+ const bool __cache_rev_iter_deref<_Iterator>::__value; >+ >+ template<typename _Tp> >+ struct __cache_rev_iter_deref<_Tp*> >+ { >+ static const bool __value = false; >+ }; >+ template<typename _Tp> >+ const bool __cache_rev_iter_deref<_Tp*>::__value; >+ >+ template<typename _Iterator, >+ bool = __cache_rev_iter_deref<_Iterator>::__value> >+ class __reverse_iter_deref_cache >+ { >+ mutable _Iterator _M_deref_tmp; >+ >+ protected: >+ typename iterator_traits<_Iterator>::reference >+ _M_deref(_Iterator __it) const >+ { >+ _M_deref_tmp = __it; >+ return *--_M_deref_tmp; >+ } >+ }; >+ >+ template<typename _Iterator> >+ class __reverse_iter_deref_cache<_Iterator, false> >+ { >+ protected: >+ typename iterator_traits<_Iterator>::reference >+ _M_deref(_Iterator __it) const >+ { >+ _Iterator __deref_tmp = __it; >+ return *--__deref_tmp; >+ } >+ }; >+ > // 24.4.1 Reverse iterators > /** > * Bidirectional and random access iterators have corresponding reverse >@@ -100,7 +143,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > typename iterator_traits<_Iterator>::value_type, > typename iterator_traits<_Iterator>::difference_type, > typename iterator_traits<_Iterator>::pointer, >- typename iterator_traits<_Iterator>::reference> >+ typename iterator_traits<_Iterator>::reference>, >+ private __reverse_iter_deref_cache<_Iterator> > { > protected: > _Iterator current; >@@ -148,6 +192,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > base() const > { return current; } > >+ // _GLIBCXX_RESOLVE_LIB_DEFECTS >+ // DR 198 Avoid returning a reference that persists beyond the >+ // lifetime of its associated iterator. > /** > * @return TODO > * >@@ -155,10 +202,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > */ > reference > operator*() const >- { >- _Iterator __tmp = current; >- return *--__tmp; >- } >+ { return this->_M_deref(current); } > > /** > * @return TODO >@@ -901,7 +945,101 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > _GLIBCXX_END_NAMESPACE_VERSION > } // namespace > >+namespace std _GLIBCXX_VISIBILITY(default) >+{ >+_GLIBCXX_BEGIN_NAMESPACE_VERSION >+ // __normal_iterator does not need to cache the result of dereferencing >+ template<typename _Iter, typename _Cont> >+ struct __cache_rev_iter_deref<__gnu_cxx::__normal_iterator<_Iter, _Cont> > >+ : __cache_rev_iter_deref<_Iter> >+ { }; >+ >+ // deque iterator >+ template<typename _Tp, typename _Ref, typename _Ptr> struct _Deque_iterator; >+ >+ template<typename _Tp, typename _Ref, typename _Ptr> >+ struct __cache_rev_iter_deref<_Deque_iterator<_Tp, _Ref, _Ptr> > >+ { static const bool __value = false; }; >+ >+ template<typename _Tp, typename _Ref, typename _Ptr> >+ const bool >+ __cache_rev_iter_deref<_Deque_iterator<_Tp, _Ref, _Ptr> >::__value; >+ >+ // list iterators >+ template<typename _Tp> struct _List_iterator; >+ >+ template<typename _Tp> >+ struct __cache_rev_iter_deref<_List_iterator<_Tp> > >+ { static const bool __value = false; }; >+ >+ template<typename _Tp> >+ const bool __cache_rev_iter_deref<_List_iterator<_Tp> >::__value; >+ >+ template<typename _Tp> struct _List_const_iterator; >+ >+ template<typename _Tp> >+ struct __cache_rev_iter_deref<_List_const_iterator<_Tp> > >+ { static const bool __value = false; }; >+ >+ template<typename _Tp> >+ const bool __cache_rev_iter_deref<_List_const_iterator<_Tp> >::__value; >+ >+ // associative container iterators >+ template<typename _Tp> struct _Rb_tree_iterator; >+ >+ template<typename _Tp> >+ struct __cache_rev_iter_deref<_Rb_tree_iterator<_Tp> > >+ { static const bool __value = false; }; >+ >+ template<typename _Tp> >+ const bool __cache_rev_iter_deref<_Rb_tree_iterator<_Tp> >::__value; >+ >+ template<typename _Tp> struct _Rb_tree_const_iterator; >+ >+ template<typename _Tp> >+ struct __cache_rev_iter_deref<_Rb_tree_const_iterator<_Tp> > >+ { static const bool __value = false; }; >+ >+ template<typename _Tp> >+ const bool __cache_rev_iter_deref<_Rb_tree_const_iterator<_Tp> >::__value; >+ >+_GLIBCXX_END_NAMESPACE_VERSION >+} // namespace >+ > #ifdef __GXX_EXPERIMENTAL_CXX0X__ >+namespace std _GLIBCXX_VISIBILITY(default) >+{ >+namespace __detail >+{ >+_GLIBCXX_BEGIN_NAMESPACE_VERSION >+ // unordered container iterators >+ template<typename, bool, bool> struct _Node_iterator; >+ template<typename, bool, bool> struct _Node_const_iterator; >+_GLIBCXX_END_NAMESPACE_VERSION >+} // namespace __detail >+ >+_GLIBCXX_BEGIN_NAMESPACE_VERSION >+ template<typename _Value, bool _B1, bool _B2> >+ struct __cache_rev_iter_deref<__detail::_Node_iterator<_Value, _B1, _B2>> >+ { static const bool __value = false; }; >+ >+ template<typename _Value, bool _B1, bool _B2> >+ const bool >+ __cache_rev_iter_deref<__detail::_Node_iterator<_Value, >+ _B1, _B2>>::__value; >+ >+ >+ template<typename _Value, bool _B1, bool _B2> >+ struct __cache_rev_iter_deref<__detail::_Node_const_iterator<_Value, >+ _B1, _B2>> >+ { static const bool __value = false; }; >+ >+ template<typename _Value, bool _B1, bool _B2> >+ const bool >+ __cache_rev_iter_deref<__detail::_Node_const_iterator<_Value, >+ _B1, _B2>>::__value; >+_GLIBCXX_END_NAMESPACE_VERSION >+} // namespace std > > namespace std _GLIBCXX_VISIBILITY(default) > { >@@ -1127,6 +1265,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > __make_move_if_noexcept_iterator(_Iterator __i) > { return _ReturnType(__i); } > >+ template<typename _Iterator> >+ struct __cache_rev_iter_deref<move_iterator<_Iterator>> >+ : __cache_rev_iter_deref<_Iterator> >+ { }; >+ > // @} group iterators > > _GLIBCXX_END_NAMESPACE_VERSION >diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823-2.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823-2.cc >new file mode 100644 >index 0000000..7d5efe2 >--- /dev/null >+++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823-2.cc >@@ -0,0 +1,77 @@ >+// Copyright (C) 2012 Free Software Foundation, Inc. >+// >+// This file is part of the GNU ISO C++ Library. This library is free >+// software; you can redistribute it and/or modify it under the >+// terms of the GNU General Public License as published by the >+// Free Software Foundation; either version 3, or (at your option) >+// any later version. >+ >+// This library is distributed in the hope that it will be useful, >+// but WITHOUT ANY WARRANTY; without even the implied warranty of >+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+// GNU General Public License for more details. >+ >+// You should have received a copy of the GNU General Public License along >+// with this library; see the file COPYING3. If not see >+// <http://www.gnu.org/licenses/>. >+ >+// 24.5.1 Reverse iterators >+ >+// DR 198. >+// Validity of pointers and references unspecified after iterator destruction. >+ >+// libstdc++/51823 >+ >+// { do-do compile } >+// { do-options "-std=gnu++11" } >+ >+#include <iterator> >+#include <array> >+#include <deque> >+#include <list> >+#include <vector> >+#include <map> >+#include <set> >+#include <unordered_map> >+#include <unordered_set> >+ >+template<typename T> >+constexpr bool test() >+{ >+ return sizeof(T) == sizeof(std::reverse_iterator<T>); >+} >+ >+static_assert( test<int*>(), "pointer" ); >+static_assert( test<const int*>(), "pointer const" ); >+ >+static_assert( test<std::string::iterator>(), "string" ); >+static_assert( test<std::string::const_iterator>(), "string const" ); >+ >+static_assert( test<std::array<int, 2>::iterator>(), "array" ); >+static_assert( test<std::array<int, 2>::const_iterator>(), "array const" ); >+ >+static_assert( test<std::list<int>::iterator>(), "list" ); >+static_assert( test<std::list<int>::const_iterator>(), "list const" ); >+ >+static_assert( test<std::deque<int>::iterator>(), "deque" ); >+static_assert( test<std::deque<int>::const_iterator>(), "deque const" ); >+ >+static_assert( test<std::vector<int>::iterator>(), "vector" ); >+static_assert( test<std::vector<int>::const_iterator>(), "vector const" ); >+ >+static_assert( test<std::map<int,int>::iterator>(), "map" ); >+static_assert( test<std::map<int,int>::const_iterator>(), "map const" ); >+ >+static_assert( test<std::set<int>::iterator>(), "set" ); >+static_assert( test<std::set<int>::const_iterator>(), "set const" ); >+ >+static_assert( test<std::unordered_map<int,int>::iterator>(), >+ "unordered_map" ); >+static_assert( test<std::unordered_map<int,int>::const_iterator>(), >+ "unordered_map const" ); >+ >+static_assert( test<std::unordered_set<int>::iterator>(), >+ "unordered_set" ); >+static_assert( test<std::unordered_set<int>::const_iterator>(), >+ "unordered_set const" ); >+ >diff --git a/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823.cc b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823.cc >new file mode 100644 >index 0000000..a8c733f >--- /dev/null >+++ b/libstdc++-v3/testsuite/24_iterators/reverse_iterator/51823.cc >@@ -0,0 +1,108 @@ >+// Copyright (C) 2012 Free Software Foundation, Inc. >+// >+// This file is part of the GNU ISO C++ Library. This library is free >+// software; you can redistribute it and/or modify it under the >+// terms of the GNU General Public License as published by the >+// Free Software Foundation; either version 3, or (at your option) >+// any later version. >+ >+// This library is distributed in the hope that it will be useful, >+// but WITHOUT ANY WARRANTY; without even the implied warranty of >+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+// GNU General Public License for more details. >+ >+// You should have received a copy of the GNU General Public License along >+// with this library; see the file COPYING3. If not see >+// <http://www.gnu.org/licenses/>. >+ >+// 24.5.1 Reverse iterators >+ >+// DR 198. >+// Validity of pointers and references unspecified after iterator destruction. >+ >+// libstdc++/51823 >+ >+#include <iterator> >+#include <vector> >+#include <testsuite_hooks.h> >+ >+struct datum >+{ >+ unsigned use_count; >+}; >+ >+std::vector<datum> data(6); >+unsigned iterator_id = 0; >+ >+struct iterator >+{ >+ typedef datum value_type; >+ typedef datum& reference; >+ typedef datum* pointer; >+ typedef std::ptrdiff_t difference_type; >+ typedef std::bidirectional_iterator_tag iterator_category; >+ >+ iterator() : id(-1) { } >+ iterator(unsigned id) : id(id) { data[id].use_count++; } >+ iterator(const iterator& i) : id(i.id) { data[id].use_count++; } >+ >+ ~iterator() { if (id < data.size()) data[id].use_count--; } >+ >+ iterator& operator=(iterator i) { swap(i); } >+ >+ reference operator*() const { return data[id]; } >+ pointer operator->() const { return &data[id]; } >+ >+ iterator& operator++() >+ { >+ data[id].use_count--; >+ ++id; >+ data[id].use_count++; >+ return *this; >+ } >+ >+ iterator& operator--() >+ { >+ data[id].use_count--; >+ --id; >+ data[id].use_count++; >+ return *this; >+ } >+ >+ iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; } >+ iterator operator--(int) { iterator tmp = *this; --*this; return tmp; } >+ >+private: >+ void swap(iterator& i) { std::swap(id, i.id); } >+ >+ unsigned id; >+}; >+ >+void test01() >+{ >+ bool test __attribute__((unused)) = true; >+ >+ typedef std::reverse_iterator<iterator> reverse_iterator; >+ >+ iterator it1(2); >+ reverse_iterator rit1(it1); >+ VERIFY( (*rit1).use_count != 0 ); >+ VERIFY( rit1->use_count != 0 ); >+ ++rit1; >+ VERIFY( (*rit1).use_count != 0 ); >+ VERIFY( rit1->use_count != 0 ); >+ >+ iterator it2(3); >+ reverse_iterator rit2(it2); >+ VERIFY( (*rit2).use_count != 0 ); >+ VERIFY( rit2->use_count != 0 ); >+ --rit2; >+ VERIFY( (*rit2).use_count != 0 ); >+ VERIFY( rit2->use_count != 0 ); >+} >+ >+int main() >+{ >+ test01(); >+ return 0; >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 51823
:
26299
|
26300
| 26323