xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/debug/safe_local_iterator.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // Safe iterator implementation  -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino // any later version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*e4b17023SJohn Marino // GNU General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /** @file debug/safe_local_iterator.h
26*e4b17023SJohn Marino  *  This file is a GNU debug extension to the Standard C++ Library.
27*e4b17023SJohn Marino  */
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino #ifndef _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H
30*e4b17023SJohn Marino #define _GLIBCXX_DEBUG_SAFE_LOCAL_ITERATOR_H 1
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino #include <debug/debug.h>
33*e4b17023SJohn Marino #include <debug/macros.h>
34*e4b17023SJohn Marino #include <debug/functions.h>
35*e4b17023SJohn Marino #include <debug/safe_unordered_base.h>
36*e4b17023SJohn Marino #include <ext/type_traits.h>
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino namespace __gnu_debug
39*e4b17023SJohn Marino {
40*e4b17023SJohn Marino   /** \brief Safe iterator wrapper.
41*e4b17023SJohn Marino    *
42*e4b17023SJohn Marino    *  The class template %_Safe_local_iterator is a wrapper around an
43*e4b17023SJohn Marino    *  iterator that tracks the iterator's movement among sequences and
44*e4b17023SJohn Marino    *  checks that operations performed on the "safe" iterator are
45*e4b17023SJohn Marino    *  legal. In additional to the basic iterator operations (which are
46*e4b17023SJohn Marino    *  validated, and then passed to the underlying iterator),
47*e4b17023SJohn Marino    *  %_Safe_local_iterator has member functions for iterator invalidation,
48*e4b17023SJohn Marino    *  attaching/detaching the iterator from sequences, and querying
49*e4b17023SJohn Marino    *  the iterator's state.
50*e4b17023SJohn Marino    */
51*e4b17023SJohn Marino   template<typename _Iterator, typename _Sequence>
52*e4b17023SJohn Marino     class _Safe_local_iterator : public _Safe_local_iterator_base
53*e4b17023SJohn Marino     {
54*e4b17023SJohn Marino       typedef _Safe_local_iterator _Self;
55*e4b17023SJohn Marino       typedef typename _Sequence::size_type size_type;
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino       /// The underlying iterator
58*e4b17023SJohn Marino       _Iterator _M_current;
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino       /// The bucket this local iterator belongs to
61*e4b17023SJohn Marino       size_type _M_bucket;
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino       /// Determine if this is a constant iterator.
64*e4b17023SJohn Marino       bool
_M_constant()65*e4b17023SJohn Marino       _M_constant() const
66*e4b17023SJohn Marino       {
67*e4b17023SJohn Marino 	typedef typename _Sequence::const_local_iterator const_iterator;
68*e4b17023SJohn Marino 	return std::__are_same<const_iterator, _Safe_local_iterator>::__value;
69*e4b17023SJohn Marino       }
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino       typedef std::iterator_traits<_Iterator> _Traits;
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino     public:
74*e4b17023SJohn Marino       typedef _Iterator                           iterator_type;
75*e4b17023SJohn Marino       typedef typename _Traits::iterator_category iterator_category;
76*e4b17023SJohn Marino       typedef typename _Traits::value_type        value_type;
77*e4b17023SJohn Marino       typedef typename _Traits::difference_type   difference_type;
78*e4b17023SJohn Marino       typedef typename _Traits::reference         reference;
79*e4b17023SJohn Marino       typedef typename _Traits::pointer           pointer;
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino       /// @post the iterator is singular and unattached
_Safe_local_iterator()82*e4b17023SJohn Marino       _Safe_local_iterator() : _M_current() { }
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino       /**
85*e4b17023SJohn Marino        * @brief Safe iterator construction from an unsafe iterator and
86*e4b17023SJohn Marino        * its sequence.
87*e4b17023SJohn Marino        *
88*e4b17023SJohn Marino        * @pre @p seq is not NULL
89*e4b17023SJohn Marino        * @post this is not singular
90*e4b17023SJohn Marino        */
_Safe_local_iterator(const _Iterator & __i,size_type __bucket,const _Sequence * __seq)91*e4b17023SJohn Marino       _Safe_local_iterator(const _Iterator& __i, size_type __bucket,
92*e4b17023SJohn Marino 			   const _Sequence* __seq)
93*e4b17023SJohn Marino       : _Safe_local_iterator_base(__seq, _M_constant()), _M_current(__i),
94*e4b17023SJohn Marino 	_M_bucket(__bucket)
95*e4b17023SJohn Marino       {
96*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
97*e4b17023SJohn Marino 			      _M_message(__msg_init_singular)
98*e4b17023SJohn Marino 			      ._M_iterator(*this, "this"));
99*e4b17023SJohn Marino       }
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino       /**
102*e4b17023SJohn Marino        * @brief Copy construction.
103*e4b17023SJohn Marino        */
_Safe_local_iterator(const _Safe_local_iterator & __x)104*e4b17023SJohn Marino       _Safe_local_iterator(const _Safe_local_iterator& __x)
105*e4b17023SJohn Marino       : _Safe_local_iterator_base(__x, _M_constant()),
106*e4b17023SJohn Marino 	_M_current(__x._M_current), _M_bucket(__x._M_bucket)
107*e4b17023SJohn Marino       {
108*e4b17023SJohn Marino 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
109*e4b17023SJohn Marino 	// DR 408. Is vector<reverse_iterator<char*> > forbidden?
110*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
111*e4b17023SJohn Marino 			      || __x._M_current == _Iterator(),
112*e4b17023SJohn Marino 			      _M_message(__msg_init_copy_singular)
113*e4b17023SJohn Marino 			      ._M_iterator(*this, "this")
114*e4b17023SJohn Marino 			      ._M_iterator(__x, "other"));
115*e4b17023SJohn Marino       }
116*e4b17023SJohn Marino 
117*e4b17023SJohn Marino       /**
118*e4b17023SJohn Marino        *  @brief Converting constructor from a mutable iterator to a
119*e4b17023SJohn Marino        *  constant iterator.
120*e4b17023SJohn Marino       */
121*e4b17023SJohn Marino       template<typename _MutableIterator>
_Safe_local_iterator(const _Safe_local_iterator<_MutableIterator,typename __gnu_cxx::__enable_if<std::__are_same<_MutableIterator,typename _Sequence::local_iterator::iterator_type>::__value,_Sequence>::__type> & __x)122*e4b17023SJohn Marino 	_Safe_local_iterator(
123*e4b17023SJohn Marino 	  const _Safe_local_iterator<_MutableIterator,
124*e4b17023SJohn Marino 	  typename __gnu_cxx::__enable_if<std::__are_same<
125*e4b17023SJohn Marino 	      _MutableIterator,
126*e4b17023SJohn Marino 	      typename _Sequence::local_iterator::iterator_type>::__value,
127*e4b17023SJohn Marino 					  _Sequence>::__type>& __x)
128*e4b17023SJohn Marino 	: _Safe_local_iterator_base(__x, _M_constant()),
129*e4b17023SJohn Marino 	  _M_current(__x.base()), _M_bucket(__x._M_bucket)
130*e4b17023SJohn Marino 	{
131*e4b17023SJohn Marino 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
132*e4b17023SJohn Marino 	  // DR 408. Is vector<reverse_iterator<char*> > forbidden?
133*e4b17023SJohn Marino 	  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
134*e4b17023SJohn Marino 				|| __x.base() == _Iterator(),
135*e4b17023SJohn Marino 				_M_message(__msg_init_const_singular)
136*e4b17023SJohn Marino 				._M_iterator(*this, "this")
137*e4b17023SJohn Marino 				._M_iterator(__x, "other"));
138*e4b17023SJohn Marino 	}
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino       /**
141*e4b17023SJohn Marino        * @brief Copy assignment.
142*e4b17023SJohn Marino        */
143*e4b17023SJohn Marino       _Safe_local_iterator&
144*e4b17023SJohn Marino       operator=(const _Safe_local_iterator& __x)
145*e4b17023SJohn Marino       {
146*e4b17023SJohn Marino 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
147*e4b17023SJohn Marino 	// DR 408. Is vector<reverse_iterator<char*> > forbidden?
148*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
149*e4b17023SJohn Marino 			      || __x._M_current == _Iterator(),
150*e4b17023SJohn Marino 			      _M_message(__msg_copy_singular)
151*e4b17023SJohn Marino 			      ._M_iterator(*this, "this")
152*e4b17023SJohn Marino 			      ._M_iterator(__x, "other"));
153*e4b17023SJohn Marino 	_M_current = __x._M_current;
154*e4b17023SJohn Marino 	_M_bucket = __x._M_bucket;
155*e4b17023SJohn Marino 	this->_M_attach(__x._M_sequence);
156*e4b17023SJohn Marino 	return *this;
157*e4b17023SJohn Marino       }
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino       /**
160*e4b17023SJohn Marino        *  @brief Iterator dereference.
161*e4b17023SJohn Marino        *  @pre iterator is dereferenceable
162*e4b17023SJohn Marino        */
163*e4b17023SJohn Marino       reference
164*e4b17023SJohn Marino       operator*() const
165*e4b17023SJohn Marino       {
166*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
167*e4b17023SJohn Marino 			      _M_message(__msg_bad_deref)
168*e4b17023SJohn Marino 			      ._M_iterator(*this, "this"));
169*e4b17023SJohn Marino 	return *_M_current;
170*e4b17023SJohn Marino       }
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino       /**
173*e4b17023SJohn Marino        *  @brief Iterator dereference.
174*e4b17023SJohn Marino        *  @pre iterator is dereferenceable
175*e4b17023SJohn Marino        *  @todo Make this correct w.r.t. iterators that return proxies
176*e4b17023SJohn Marino        *  @todo Use addressof() instead of & operator
177*e4b17023SJohn Marino        */
178*e4b17023SJohn Marino       pointer
179*e4b17023SJohn Marino       operator->() const
180*e4b17023SJohn Marino       {
181*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
182*e4b17023SJohn Marino 			      _M_message(__msg_bad_deref)
183*e4b17023SJohn Marino 			      ._M_iterator(*this, "this"));
184*e4b17023SJohn Marino 	return &*_M_current;
185*e4b17023SJohn Marino       }
186*e4b17023SJohn Marino 
187*e4b17023SJohn Marino       // ------ Input iterator requirements ------
188*e4b17023SJohn Marino       /**
189*e4b17023SJohn Marino        *  @brief Iterator preincrement
190*e4b17023SJohn Marino        *  @pre iterator is incrementable
191*e4b17023SJohn Marino        */
192*e4b17023SJohn Marino       _Safe_local_iterator&
193*e4b17023SJohn Marino       operator++()
194*e4b17023SJohn Marino       {
195*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
196*e4b17023SJohn Marino 			      _M_message(__msg_bad_inc)
197*e4b17023SJohn Marino 			      ._M_iterator(*this, "this"));
198*e4b17023SJohn Marino 	++_M_current;
199*e4b17023SJohn Marino 	return *this;
200*e4b17023SJohn Marino       }
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino       /**
203*e4b17023SJohn Marino        *  @brief Iterator postincrement
204*e4b17023SJohn Marino        *  @pre iterator is incrementable
205*e4b17023SJohn Marino        */
206*e4b17023SJohn Marino       _Safe_local_iterator
207*e4b17023SJohn Marino       operator++(int)
208*e4b17023SJohn Marino       {
209*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
210*e4b17023SJohn Marino 			      _M_message(__msg_bad_inc)
211*e4b17023SJohn Marino 			      ._M_iterator(*this, "this"));
212*e4b17023SJohn Marino 	_Safe_local_iterator __tmp(*this);
213*e4b17023SJohn Marino 	++_M_current;
214*e4b17023SJohn Marino 	return __tmp;
215*e4b17023SJohn Marino       }
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino       // ------ Utilities ------
218*e4b17023SJohn Marino       /**
219*e4b17023SJohn Marino        * @brief Return the underlying iterator
220*e4b17023SJohn Marino        */
221*e4b17023SJohn Marino       _Iterator
base()222*e4b17023SJohn Marino       base() const { return _M_current; }
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino       /**
225*e4b17023SJohn Marino        * @brief Return the bucket
226*e4b17023SJohn Marino        */
227*e4b17023SJohn Marino       size_type
bucket()228*e4b17023SJohn Marino       bucket() const { return _M_bucket; }
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino       /**
231*e4b17023SJohn Marino        * @brief Conversion to underlying non-debug iterator to allow
232*e4b17023SJohn Marino        * better interaction with non-debug containers.
233*e4b17023SJohn Marino        */
_Iterator()234*e4b17023SJohn Marino       operator _Iterator() const { return _M_current; }
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino       /** Attach iterator to the given sequence. */
237*e4b17023SJohn Marino       void
_M_attach(_Safe_sequence_base * __seq)238*e4b17023SJohn Marino       _M_attach(_Safe_sequence_base* __seq)
239*e4b17023SJohn Marino       { _Safe_iterator_base::_M_attach(__seq, _M_constant()); }
240*e4b17023SJohn Marino 
241*e4b17023SJohn Marino       /** Likewise, but not thread-safe. */
242*e4b17023SJohn Marino       void
_M_attach_single(_Safe_sequence_base * __seq)243*e4b17023SJohn Marino       _M_attach_single(_Safe_sequence_base* __seq)
244*e4b17023SJohn Marino       { _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); }
245*e4b17023SJohn Marino 
246*e4b17023SJohn Marino       /// Is the iterator dereferenceable?
247*e4b17023SJohn Marino       bool
_M_dereferenceable()248*e4b17023SJohn Marino       _M_dereferenceable() const
249*e4b17023SJohn Marino       { return !this->_M_singular() && !_M_is_end(); }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino       /// Is the iterator incrementable?
252*e4b17023SJohn Marino       bool
_M_incrementable()253*e4b17023SJohn Marino       _M_incrementable() const
254*e4b17023SJohn Marino       { return !this->_M_singular() && !_M_is_end(); }
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino       // Is the iterator range [*this, __rhs) valid?
257*e4b17023SJohn Marino       template<typename _Other>
258*e4b17023SJohn Marino 	bool
259*e4b17023SJohn Marino 	_M_valid_range(const _Safe_local_iterator<_Other,
260*e4b17023SJohn Marino 						  _Sequence>& __rhs) const;
261*e4b17023SJohn Marino 
262*e4b17023SJohn Marino       // The sequence this iterator references.
263*e4b17023SJohn Marino       const _Sequence*
_M_get_sequence()264*e4b17023SJohn Marino       _M_get_sequence() const
265*e4b17023SJohn Marino       { return static_cast<const _Sequence*>(_M_sequence); }
266*e4b17023SJohn Marino 
267*e4b17023SJohn Marino       /// Is this iterator equal to the sequence's begin() iterator?
_M_is_begin()268*e4b17023SJohn Marino       bool _M_is_begin() const
269*e4b17023SJohn Marino       { return base() == _M_get_sequence()->_M_base().begin(_M_bucket); }
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino       /// Is this iterator equal to the sequence's end() iterator?
_M_is_end()272*e4b17023SJohn Marino       bool _M_is_end() const
273*e4b17023SJohn Marino       { return base() == _M_get_sequence()->_M_base().end(_M_bucket); }
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino       /// Is this iterator part of the same bucket as the other one?
276*e4b17023SJohn Marino       template <typename _Other>
_M_in_same_bucket(const _Safe_local_iterator<_Other,_Sequence> & __other)277*e4b17023SJohn Marino 	bool _M_in_same_bucket(const _Safe_local_iterator<_Other,
278*e4b17023SJohn Marino 						_Sequence>& __other) const
279*e4b17023SJohn Marino 	{ return _M_bucket == __other.bucket(); }
280*e4b17023SJohn Marino     };
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
283*e4b17023SJohn Marino     inline bool
284*e4b17023SJohn Marino     operator==(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs,
285*e4b17023SJohn Marino 	       const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs)
286*e4b17023SJohn Marino     {
287*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
288*e4b17023SJohn Marino 			    _M_message(__msg_iter_compare_bad)
289*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
290*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
291*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
292*e4b17023SJohn Marino 			    _M_message(__msg_compare_different)
293*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
294*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
295*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
296*e4b17023SJohn Marino 			    _M_message(__msg_compare_different)
297*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
298*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
299*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs),
300*e4b17023SJohn Marino 			    _M_message(__msg_local_iter_compare_bad)
301*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
302*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
303*e4b17023SJohn Marino       return __lhs.base() == __rhs.base();
304*e4b17023SJohn Marino     }
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino   template<typename _Iterator, typename _Sequence>
307*e4b17023SJohn Marino     inline bool
308*e4b17023SJohn Marino     operator==(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs,
309*e4b17023SJohn Marino 	       const _Safe_local_iterator<_Iterator, _Sequence>& __rhs)
310*e4b17023SJohn Marino     {
311*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
312*e4b17023SJohn Marino 			    _M_message(__msg_iter_compare_bad)
313*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
314*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
315*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
316*e4b17023SJohn Marino 			    _M_message(__msg_compare_different)
317*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
318*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
319*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs),
320*e4b17023SJohn Marino 			    _M_message(__msg_local_iter_compare_bad)
321*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
322*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
323*e4b17023SJohn Marino       return __lhs.base() == __rhs.base();
324*e4b17023SJohn Marino     }
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
327*e4b17023SJohn Marino     inline bool
328*e4b17023SJohn Marino     operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs,
329*e4b17023SJohn Marino 	       const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs)
330*e4b17023SJohn Marino     {
331*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
332*e4b17023SJohn Marino 			    _M_message(__msg_iter_compare_bad)
333*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
334*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
335*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
336*e4b17023SJohn Marino 			    _M_message(__msg_compare_different)
337*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
338*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
339*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs),
340*e4b17023SJohn Marino 			    _M_message(__msg_local_iter_compare_bad)
341*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
342*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
343*e4b17023SJohn Marino       return __lhs.base() != __rhs.base();
344*e4b17023SJohn Marino     }
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino   template<typename _Iterator, typename _Sequence>
347*e4b17023SJohn Marino     inline bool
348*e4b17023SJohn Marino     operator!=(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs,
349*e4b17023SJohn Marino 	       const _Safe_local_iterator<_Iterator, _Sequence>& __rhs)
350*e4b17023SJohn Marino     {
351*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
352*e4b17023SJohn Marino 			    _M_message(__msg_iter_compare_bad)
353*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
354*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
355*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
356*e4b17023SJohn Marino 			    _M_message(__msg_compare_different)
357*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
358*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
359*e4b17023SJohn Marino       _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs),
360*e4b17023SJohn Marino 			    _M_message(__msg_local_iter_compare_bad)
361*e4b17023SJohn Marino 			    ._M_iterator(__lhs, "lhs")
362*e4b17023SJohn Marino 			    ._M_iterator(__rhs, "rhs"));
363*e4b17023SJohn Marino       return __lhs.base() != __rhs.base();
364*e4b17023SJohn Marino     }
365*e4b17023SJohn Marino } // namespace __gnu_debug
366*e4b17023SJohn Marino 
367*e4b17023SJohn Marino #include <debug/safe_local_iterator.tcc>
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino #endif
370