xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/debug/helper_functions.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg // Debugging support implementation -*- C++ -*-
236ac495dSmrg 
3*8feb0f0bSmrg // Copyright (C) 2003-2020 Free Software Foundation, Inc.
436ac495dSmrg //
536ac495dSmrg // This file is part of the GNU ISO C++ Library.  This library is free
636ac495dSmrg // software; you can redistribute it and/or modify it under the
736ac495dSmrg // terms of the GNU General Public License as published by the
836ac495dSmrg // Free Software Foundation; either version 3, or (at your option)
936ac495dSmrg // any later version.
1036ac495dSmrg 
1136ac495dSmrg // This library is distributed in the hope that it will be useful,
1236ac495dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1436ac495dSmrg // GNU General Public License for more details.
1536ac495dSmrg 
1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg // 3.1, as published by the Free Software Foundation.
1936ac495dSmrg 
2036ac495dSmrg // You should have received a copy of the GNU General Public License and
2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2336ac495dSmrg // <http://www.gnu.org/licenses/>.
2436ac495dSmrg 
2536ac495dSmrg /** @file debug/helper_functions.h
2636ac495dSmrg  *  This file is a GNU debug extension to the Standard C++ Library.
2736ac495dSmrg  */
2836ac495dSmrg 
2936ac495dSmrg #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
3036ac495dSmrg #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
3136ac495dSmrg 
32*8feb0f0bSmrg #include <bits/move.h>				// for __addressof
3336ac495dSmrg #include <bits/stl_iterator_base_types.h>	// for iterator_traits,
3436ac495dSmrg 						// categories and _Iter_base
3536ac495dSmrg #include <bits/cpp_type_traits.h>		// for __is_integer
3636ac495dSmrg 
3736ac495dSmrg #include <bits/stl_pair.h>			// for pair
3836ac495dSmrg 
3936ac495dSmrg namespace __gnu_debug
4036ac495dSmrg {
41c0a68be4Smrg   template<typename _Iterator, typename _Sequence, typename _Category>
42c0a68be4Smrg     class _Safe_iterator;
43c0a68be4Smrg 
44c0a68be4Smrg #if __cplusplus >= 201103L
45c0a68be4Smrg   template<typename _Iterator, typename _Sequence>
46c0a68be4Smrg     class _Safe_local_iterator;
47c0a68be4Smrg #endif
48c0a68be4Smrg 
4936ac495dSmrg   /** The precision to which we can calculate the distance between
5036ac495dSmrg    *  two iterators.
5136ac495dSmrg    */
5236ac495dSmrg   enum _Distance_precision
5336ac495dSmrg     {
5436ac495dSmrg       __dp_none,		// Not even an iterator type
5536ac495dSmrg       __dp_equality,		//< Can compare iterator equality, only
5636ac495dSmrg       __dp_sign,		//< Can determine equality and ordering
57*8feb0f0bSmrg       __dp_sign_max_size,	//< __dp_sign and gives max range size
5836ac495dSmrg       __dp_exact		//< Can determine distance precisely
5936ac495dSmrg     };
6036ac495dSmrg 
6136ac495dSmrg   template<typename _Iterator,
6236ac495dSmrg 	   typename = typename std::__is_integer<_Iterator>::__type>
6336ac495dSmrg     struct _Distance_traits
6436ac495dSmrg     {
6536ac495dSmrg     private:
6636ac495dSmrg       typedef
6736ac495dSmrg 	typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
6836ac495dSmrg 
6936ac495dSmrg       template<typename _DiffType,
7036ac495dSmrg 	       typename = typename std::__is_void<_DiffType>::__type>
7136ac495dSmrg 	struct _DiffTraits
7236ac495dSmrg 	{ typedef _DiffType __type; };
7336ac495dSmrg 
7436ac495dSmrg       template<typename _DiffType>
7536ac495dSmrg 	struct _DiffTraits<_DiffType, std::__true_type>
7636ac495dSmrg 	{ typedef std::ptrdiff_t __type; };
7736ac495dSmrg 
7836ac495dSmrg       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
7936ac495dSmrg 
8036ac495dSmrg     public:
8136ac495dSmrg       typedef std::pair<_DiffType, _Distance_precision> __type;
8236ac495dSmrg     };
8336ac495dSmrg 
8436ac495dSmrg   template<typename _Integral>
8536ac495dSmrg     struct _Distance_traits<_Integral, std::__true_type>
8636ac495dSmrg     { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
8736ac495dSmrg 
8836ac495dSmrg   /** Determine the distance between two iterators with some known
8936ac495dSmrg    *	precision.
9036ac495dSmrg   */
9136ac495dSmrg   template<typename _Iterator>
92*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
9336ac495dSmrg     inline typename _Distance_traits<_Iterator>::__type
94c0a68be4Smrg     __get_distance(_Iterator __lhs, _Iterator __rhs,
9536ac495dSmrg 		   std::random_access_iterator_tag)
9636ac495dSmrg     { return std::make_pair(__rhs - __lhs, __dp_exact); }
9736ac495dSmrg 
9836ac495dSmrg   template<typename _Iterator>
99*8feb0f0bSmrg     _GLIBCXX14_CONSTEXPR
10036ac495dSmrg     inline typename _Distance_traits<_Iterator>::__type
101c0a68be4Smrg     __get_distance(_Iterator __lhs, _Iterator __rhs,
10236ac495dSmrg 		   std::input_iterator_tag)
10336ac495dSmrg     {
10436ac495dSmrg       if (__lhs == __rhs)
10536ac495dSmrg 	return std::make_pair(0, __dp_exact);
10636ac495dSmrg 
10736ac495dSmrg       return std::make_pair(1, __dp_equality);
10836ac495dSmrg     }
10936ac495dSmrg 
11036ac495dSmrg   template<typename _Iterator>
111*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
11236ac495dSmrg     inline typename _Distance_traits<_Iterator>::__type
113c0a68be4Smrg     __get_distance(_Iterator __lhs, _Iterator __rhs)
11436ac495dSmrg     { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
11536ac495dSmrg 
116*8feb0f0bSmrg   // An arbitrary iterator pointer is not singular.
117*8feb0f0bSmrg   inline bool
118*8feb0f0bSmrg   __check_singular_aux(const void*) { return false; }
119*8feb0f0bSmrg 
120*8feb0f0bSmrg   // We may have an iterator that derives from _Safe_iterator_base but isn't
121*8feb0f0bSmrg   // a _Safe_iterator.
122*8feb0f0bSmrg   template<typename _Iterator>
123*8feb0f0bSmrg     inline bool
124*8feb0f0bSmrg     __check_singular(_Iterator const& __x)
125*8feb0f0bSmrg     { return __check_singular_aux(std::__addressof(__x)); }
126*8feb0f0bSmrg 
127*8feb0f0bSmrg   /** Non-NULL pointers are nonsingular. */
128*8feb0f0bSmrg   template<typename _Tp>
129*8feb0f0bSmrg     inline bool
130*8feb0f0bSmrg     __check_singular(_Tp* const& __ptr)
131*8feb0f0bSmrg     { return __ptr == 0; }
132*8feb0f0bSmrg 
13336ac495dSmrg   /** We say that integral types for a valid range, and defer to other
13436ac495dSmrg    *  routines to realize what to do with integral types instead of
13536ac495dSmrg    *  iterators.
13636ac495dSmrg   */
13736ac495dSmrg   template<typename _Integral>
138*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
139*8feb0f0bSmrg     inline bool
140*8feb0f0bSmrg     __valid_range_aux(_Integral, _Integral, std::__true_type)
141*8feb0f0bSmrg     { return true; }
142*8feb0f0bSmrg 
143*8feb0f0bSmrg   template<typename _Integral>
144*8feb0f0bSmrg     _GLIBCXX20_CONSTEXPR
14536ac495dSmrg     inline bool
146c0a68be4Smrg     __valid_range_aux(_Integral, _Integral,
14736ac495dSmrg 		      typename _Distance_traits<_Integral>::__type& __dist,
14836ac495dSmrg 		      std::__true_type)
14936ac495dSmrg     {
15036ac495dSmrg       __dist = std::make_pair(0, __dp_none);
15136ac495dSmrg       return true;
15236ac495dSmrg     }
15336ac495dSmrg 
154*8feb0f0bSmrg   template<typename _InputIterator>
155*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
156*8feb0f0bSmrg     inline bool
157*8feb0f0bSmrg     __valid_range_aux(_InputIterator __first, _InputIterator __last,
158*8feb0f0bSmrg 		      std::input_iterator_tag)
159*8feb0f0bSmrg     {
160*8feb0f0bSmrg       return __first == __last
161*8feb0f0bSmrg 	|| (!__check_singular(__first) && !__check_singular(__last));
162*8feb0f0bSmrg     }
163*8feb0f0bSmrg 
164*8feb0f0bSmrg   template<typename _InputIterator>
165*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
166*8feb0f0bSmrg     inline bool
167*8feb0f0bSmrg     __valid_range_aux(_InputIterator __first, _InputIterator __last,
168*8feb0f0bSmrg 		      std::random_access_iterator_tag)
169*8feb0f0bSmrg     {
170*8feb0f0bSmrg       return
171*8feb0f0bSmrg 	__valid_range_aux(__first, __last, std::input_iterator_tag())
172*8feb0f0bSmrg 	&& __first <= __last;
173*8feb0f0bSmrg     }
174*8feb0f0bSmrg 
175c0a68be4Smrg   /** We have iterators, so figure out what kind of iterators they are
17636ac495dSmrg    *  to see if we can check the range ahead of time.
17736ac495dSmrg   */
17836ac495dSmrg   template<typename _InputIterator>
179*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
180*8feb0f0bSmrg     inline bool
181*8feb0f0bSmrg     __valid_range_aux(_InputIterator __first, _InputIterator __last,
182*8feb0f0bSmrg 		      std::__false_type)
183*8feb0f0bSmrg     {
184*8feb0f0bSmrg       return __valid_range_aux(__first, __last,
185*8feb0f0bSmrg 			       std::__iterator_category(__first));
186*8feb0f0bSmrg     }
187*8feb0f0bSmrg 
188*8feb0f0bSmrg   template<typename _InputIterator>
189*8feb0f0bSmrg     _GLIBCXX20_CONSTEXPR
19036ac495dSmrg     inline bool
191c0a68be4Smrg     __valid_range_aux(_InputIterator __first, _InputIterator __last,
19236ac495dSmrg 		      typename _Distance_traits<_InputIterator>::__type& __dist,
19336ac495dSmrg 		      std::__false_type)
19436ac495dSmrg     {
195*8feb0f0bSmrg       if (!__valid_range_aux(__first, __last, std::input_iterator_tag()))
196*8feb0f0bSmrg 	return false;
197*8feb0f0bSmrg 
19836ac495dSmrg       __dist = __get_distance(__first, __last);
19936ac495dSmrg       switch (__dist.second)
20036ac495dSmrg 	{
20136ac495dSmrg 	case __dp_none:
20236ac495dSmrg 	  break;
20336ac495dSmrg 	case __dp_equality:
20436ac495dSmrg 	  if (__dist.first == 0)
20536ac495dSmrg 	    return true;
20636ac495dSmrg 	  break;
20736ac495dSmrg 	case __dp_sign:
208*8feb0f0bSmrg 	case __dp_sign_max_size:
20936ac495dSmrg 	case __dp_exact:
21036ac495dSmrg 	  return __dist.first >= 0;
21136ac495dSmrg 	}
21236ac495dSmrg 
21336ac495dSmrg       // Can't tell so assume it is fine.
21436ac495dSmrg       return true;
21536ac495dSmrg     }
21636ac495dSmrg 
21736ac495dSmrg   /** Don't know what these iterators are, or if they are even
21836ac495dSmrg    *  iterators (we may get an integral type for InputIterator), so
21936ac495dSmrg    *  see if they are integral and pass them on to the next phase
22036ac495dSmrg    *  otherwise.
22136ac495dSmrg   */
22236ac495dSmrg   template<typename _InputIterator>
223*8feb0f0bSmrg     _GLIBCXX20_CONSTEXPR
22436ac495dSmrg     inline bool
225c0a68be4Smrg     __valid_range(_InputIterator __first, _InputIterator __last,
22636ac495dSmrg 		  typename _Distance_traits<_InputIterator>::__type& __dist)
22736ac495dSmrg     {
228*8feb0f0bSmrg #ifdef __cpp_lib_is_constant_evaluated
229*8feb0f0bSmrg       if (std::is_constant_evaluated())
230*8feb0f0bSmrg 	// Detected by the compiler directly.
231*8feb0f0bSmrg 	return true;
232*8feb0f0bSmrg #endif
23336ac495dSmrg       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
23436ac495dSmrg       return __valid_range_aux(__first, __last, __dist, _Integral());
23536ac495dSmrg     }
23636ac495dSmrg 
237c0a68be4Smrg   template<typename _Iterator, typename _Sequence, typename _Category>
238c0a68be4Smrg     bool
239c0a68be4Smrg     __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
240c0a68be4Smrg 		  const _Safe_iterator<_Iterator, _Sequence, _Category>&,
241c0a68be4Smrg 		  typename _Distance_traits<_Iterator>::__type&);
242c0a68be4Smrg 
243c0a68be4Smrg #if __cplusplus >= 201103L
244c0a68be4Smrg   template<typename _Iterator,typename _Sequence>
245c0a68be4Smrg     bool
246c0a68be4Smrg     __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
247c0a68be4Smrg 		  const _Safe_local_iterator<_Iterator, _Sequence>&,
248c0a68be4Smrg 		  typename _Distance_traits<_Iterator>::__type&);
249c0a68be4Smrg #endif
250c0a68be4Smrg 
25136ac495dSmrg   template<typename _InputIterator>
252*8feb0f0bSmrg     _GLIBCXX14_CONSTEXPR
25336ac495dSmrg     inline bool
254c0a68be4Smrg     __valid_range(_InputIterator __first, _InputIterator __last)
25536ac495dSmrg     {
256*8feb0f0bSmrg #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
257*8feb0f0bSmrg       if (__builtin_is_constant_evaluated())
258*8feb0f0bSmrg 	// Detected by the compiler directly.
259*8feb0f0bSmrg 	return true;
260*8feb0f0bSmrg #endif
261*8feb0f0bSmrg       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
262*8feb0f0bSmrg       return __valid_range_aux(__first, __last, _Integral());
26336ac495dSmrg     }
26436ac495dSmrg 
265c0a68be4Smrg   template<typename _Iterator, typename _Sequence, typename _Category>
266c0a68be4Smrg     bool
267c0a68be4Smrg     __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
268c0a68be4Smrg 		  const _Safe_iterator<_Iterator, _Sequence, _Category>&);
26936ac495dSmrg 
270c0a68be4Smrg #if __cplusplus >= 201103L
271c0a68be4Smrg   template<typename _Iterator, typename _Sequence>
272c0a68be4Smrg     bool
273c0a68be4Smrg     __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
274c0a68be4Smrg 		  const _Safe_local_iterator<_Iterator, _Sequence>&);
275c0a68be4Smrg #endif
276c0a68be4Smrg 
277c0a68be4Smrg   // Fallback method, always ok.
278c0a68be4Smrg   template<typename _InputIterator, typename _Size>
279*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
280c0a68be4Smrg     inline bool
281c0a68be4Smrg     __can_advance(_InputIterator, _Size)
282c0a68be4Smrg     { return true; }
283c0a68be4Smrg 
284c0a68be4Smrg   template<typename _Iterator, typename _Sequence, typename _Category,
285c0a68be4Smrg 	   typename _Size>
286c0a68be4Smrg     bool
287c0a68be4Smrg     __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
288c0a68be4Smrg 		  _Size);
28936ac495dSmrg 
290*8feb0f0bSmrg   template<typename _InputIterator, typename _Diff>
291*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
292*8feb0f0bSmrg     inline bool
293*8feb0f0bSmrg     __can_advance(_InputIterator, const std::pair<_Diff, _Distance_precision>&, int)
294*8feb0f0bSmrg     { return true; }
295*8feb0f0bSmrg 
296*8feb0f0bSmrg   template<typename _Iterator, typename _Sequence, typename _Category,
297*8feb0f0bSmrg 	   typename _Diff>
298*8feb0f0bSmrg     bool
299*8feb0f0bSmrg     __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
300*8feb0f0bSmrg 		  const std::pair<_Diff, _Distance_precision>&, int);
301*8feb0f0bSmrg 
30236ac495dSmrg   /** Helper function to extract base iterator of random access safe iterator
303c0a68be4Smrg    *  in order to reduce performance impact of debug mode.  Limited to random
304c0a68be4Smrg    *  access iterator because it is the only category for which it is possible
305c0a68be4Smrg    *  to check for correct iterators order in the __valid_range function
306c0a68be4Smrg    *  thanks to the < operator.
30736ac495dSmrg    */
30836ac495dSmrg   template<typename _Iterator>
309*8feb0f0bSmrg     _GLIBCXX_CONSTEXPR
31036ac495dSmrg     inline _Iterator
31136ac495dSmrg     __base(_Iterator __it)
31236ac495dSmrg     { return __it; }
31336ac495dSmrg 
31436ac495dSmrg #if __cplusplus < 201103L
31536ac495dSmrg   template<typename _Iterator>
31636ac495dSmrg     struct _Unsafe_type
31736ac495dSmrg     { typedef _Iterator _Type; };
31836ac495dSmrg #endif
31936ac495dSmrg 
32036ac495dSmrg   /* Remove debug mode safe iterator layer, if any. */
32136ac495dSmrg   template<typename _Iterator>
32236ac495dSmrg     inline _Iterator
32336ac495dSmrg     __unsafe(_Iterator __it)
32436ac495dSmrg     { return __it; }
32536ac495dSmrg }
32636ac495dSmrg 
32736ac495dSmrg #endif
328