]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/debug/functions.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / debug / functions.h
CommitLineData
d2763ab5
BK
1// Debugging support implementation -*- C++ -*-
2
8d9254fc 3// Copyright (C) 2003-2020 Free Software Foundation, Inc.
d2763ab5
BK
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
748086b7 8// Free Software Foundation; either version 3, or (at your option)
d2763ab5
BK
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
748086b7
JJ
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
d2763ab5 24
78a53887
BK
25/** @file debug/functions.h
26 * This file is a GNU debug extension to the Standard C++ Library.
27 */
28
d2763ab5
BK
29#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
30#define _GLIBCXX_DEBUG_FUNCTIONS_H 1
31
541a9b10 32#include <bits/stl_function.h> // for less
e9afbed0 33
5720787a 34#if __cplusplus >= 201103L
e9afbed0 35# include <bits/stl_iterator.h> // for __miter_base
541a9b10 36# include <type_traits> // for is_lvalue_reference and conditional.
5720787a 37#endif
adad2a7d 38
24167c42 39#include <debug/helper_functions.h>
1f5ca1a1 40#include <debug/formatter.h>
d2763ab5
BK
41
42namespace __gnu_debug
43{
5720787a
FD
44 template<typename _Sequence>
45 struct _Insert_range_from_self_is_safe
46 { enum { __value = 0 }; };
47
72d1f255
JW
48 template<typename _Sequence>
49 struct _Is_contiguous_sequence : std::__false_type { };
50
d2763ab5
BK
51 /* Checks that [first, last) is a valid range, and then returns
52 * __first. This routine is useful when we can't use a separate
53 * assertion statement because, e.g., we are in a constructor.
54 */
55 template<typename _InputIterator>
56 inline _InputIterator
57 __check_valid_range(const _InputIterator& __first,
90aabc7e
FD
58 const _InputIterator& __last,
59 const char* __file,
60 unsigned int __line,
61 const char* __function)
d2763ab5 62 {
90aabc7e
FD
63 __glibcxx_check_valid_range_at(__first, __last,
64 __file, __line, __function);
d2763ab5
BK
65 return __first;
66 }
67
72d1f255 68 /* Handle the case where __other is a pointer to _Sequence::value_type. */
e9afbed0 69 template<typename _Iterator, typename _Sequence, typename _Category>
5720787a 70 inline bool
e9afbed0
FD
71 __foreign_iterator_aux4(
72 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
73 const typename _Sequence::value_type* __other)
5720787a 74 {
72d1f255
JW
75 typedef const typename _Sequence::value_type* _PointerType;
76 typedef std::less<_PointerType> _Less;
77#if __cplusplus >= 201103L
78 constexpr _Less __l{};
79#else
80 const _Less __l = _Less();
81#endif
82 const _Sequence* __seq = __it._M_get_sequence();
83 const _PointerType __begin = std::__addressof(*__seq->_M_base().begin());
84 const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1));
5720787a 85
72d1f255
JW
86 // Check whether __other points within the contiguous storage.
87 return __l(__other, __begin) || __l(__end, __other);
5720787a 88 }
32bb816a 89
72d1f255 90 /* Fallback overload for when we can't tell, assume it is valid. */
e9afbed0 91 template<typename _Iterator, typename _Sequence, typename _Category>
32bb816a 92 inline bool
e9afbed0
FD
93 __foreign_iterator_aux4(
94 const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...)
32bb816a
FD
95 { return true; }
96
72d1f255 97 /* Handle sequences with contiguous storage */
e9afbed0
FD
98 template<typename _Iterator, typename _Sequence, typename _Category,
99 typename _InputIterator>
5720787a 100 inline bool
e9afbed0
FD
101 __foreign_iterator_aux3(
102 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
103 const _InputIterator& __other, const _InputIterator& __other_end,
104 std::__true_type)
5720787a 105 {
72d1f255
JW
106 if (__other == __other_end)
107 return true; // inserting nothing is safe even if not foreign iters
5c441345 108 if (__it._M_get_sequence()->empty())
72d1f255
JW
109 return true; // can't be self-inserting if self is empty
110 return __foreign_iterator_aux4(__it, std::__addressof(*__other));
5720787a 111 }
72d1f255
JW
112
113 /* Handle non-contiguous containers, assume it is valid. */
e9afbed0
FD
114 template<typename _Iterator, typename _Sequence, typename _Category,
115 typename _InputIterator>
5720787a 116 inline bool
e9afbed0
FD
117 __foreign_iterator_aux3(
118 const _Safe_iterator<_Iterator, _Sequence, _Category>&,
119 const _InputIterator&, const _InputIterator&,
120 std::__false_type)
5720787a 121 { return true; }
32bb816a 122
72d1f255 123 /** Handle debug iterators from the same type of container. */
e9afbed0
FD
124 template<typename _Iterator, typename _Sequence, typename _Category,
125 typename _OtherIterator>
5720787a 126 inline bool
e9afbed0
FD
127 __foreign_iterator_aux2(
128 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
129 const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other,
130 const _Safe_iterator<_OtherIterator, _Sequence, _Category>&)
5720787a 131 { return __it._M_get_sequence() != __other._M_get_sequence(); }
72d1f255
JW
132
133 /** Handle debug iterators from different types of container. */
e9afbed0
FD
134 template<typename _Iterator, typename _Sequence, typename _Category,
135 typename _OtherIterator, typename _OtherSequence,
136 typename _OtherCategory>
72d1f255 137 inline bool
e9afbed0
FD
138 __foreign_iterator_aux2(
139 const _Safe_iterator<_Iterator, _Sequence, _Category>&,
140 const _Safe_iterator<_OtherIterator, _OtherSequence,
141 _OtherCategory>&,
142 const _Safe_iterator<_OtherIterator, _OtherSequence,
143 _OtherCategory>&)
72d1f255
JW
144 { return true; }
145
146 /* Handle non-debug iterators. */
e9afbed0
FD
147 template<typename _Iterator, typename _Sequence, typename _Category,
148 typename _InputIterator>
5720787a 149 inline bool
e9afbed0
FD
150 __foreign_iterator_aux2(
151 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
152 const _InputIterator& __other,
153 const _InputIterator& __other_end)
5720787a 154 {
8a7fb87e
FD
155#if __cplusplus < 201103L
156 typedef _Is_contiguous_sequence<_Sequence> __tag;
157#else
158 using __lvalref = std::is_lvalue_reference<
159 typename std::iterator_traits<_InputIterator>::reference>;
160 using __contiguous = _Is_contiguous_sequence<_Sequence>;
161 using __tag = typename std::conditional<__lvalref::value, __contiguous,
162 std::__false_type>::type;
163#endif
164 return __foreign_iterator_aux3(__it, __other, __other_end, __tag());
5720787a 165 }
72d1f255
JW
166
167 /* Handle the case where we aren't really inserting a range after all */
e9afbed0
FD
168 template<typename _Iterator, typename _Sequence, typename _Category,
169 typename _Integral>
5720787a 170 inline bool
e9afbed0
FD
171 __foreign_iterator_aux(
172 const _Safe_iterator<_Iterator, _Sequence, _Category>&,
173 _Integral, _Integral, std::__true_type)
5720787a
FD
174 { return true; }
175
72d1f255 176 /* Handle all iterators. */
e9afbed0 177 template<typename _Iterator, typename _Sequence, typename _Category,
5720787a
FD
178 typename _InputIterator>
179 inline bool
e9afbed0
FD
180 __foreign_iterator_aux(
181 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
182 _InputIterator __other, _InputIterator __other_end,
183 std::__false_type)
5720787a 184 {
72d1f255 185 return _Insert_range_from_self_is_safe<_Sequence>::__value
5bc1c07c
FD
186 || __foreign_iterator_aux2(__it, std::__miter_base(__other),
187 std::__miter_base(__other_end));
5720787a
FD
188 }
189
e9afbed0 190 template<typename _Iterator, typename _Sequence, typename _Category,
5720787a
FD
191 typename _InputIterator>
192 inline bool
e9afbed0
FD
193 __foreign_iterator(
194 const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
195 _InputIterator __other, _InputIterator __other_end)
5720787a
FD
196 {
197 typedef typename std::__is_integer<_InputIterator>::__type _Integral;
72d1f255 198 return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
5720787a
FD
199 }
200
d2763ab5
BK
201 // Can't check if an input iterator sequence is sorted, because we
202 // can't step through the sequence.
203 template<typename _InputIterator>
97d57665 204 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
205 inline bool
206 __check_sorted_aux(const _InputIterator&, const _InputIterator&,
207 std::input_iterator_tag)
208 { return true; }
209
210 // Can verify if a forward iterator sequence is in fact sorted using
211 // std::__is_sorted
212 template<typename _ForwardIterator>
97d57665 213 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
214 inline bool
215 __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
216 std::forward_iterator_tag)
217 {
218 if (__first == __last)
219 return true;
220
221 _ForwardIterator __next = __first;
e2897e23 222 for (++__next; __next != __last; __first = __next, (void)++__next)
d2763ab5
BK
223 if (*__next < *__first)
224 return false;
d2763ab5
BK
225
226 return true;
227 }
228
229 // Can't check if an input iterator sequence is sorted, because we can't step
230 // through the sequence.
231 template<typename _InputIterator, typename _Predicate>
97d57665 232 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
233 inline bool
234 __check_sorted_aux(const _InputIterator&, const _InputIterator&,
235 _Predicate, std::input_iterator_tag)
236 { return true; }
237
238 // Can verify if a forward iterator sequence is in fact sorted using
239 // std::__is_sorted
240 template<typename _ForwardIterator, typename _Predicate>
97d57665 241 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
242 inline bool
243 __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
244 _Predicate __pred, std::forward_iterator_tag)
245 {
246 if (__first == __last)
247 return true;
248
249 _ForwardIterator __next = __first;
e2897e23 250 for (++__next; __next != __last; __first = __next, (void)++__next)
d2763ab5
BK
251 if (__pred(*__next, *__first))
252 return false;
d2763ab5
BK
253
254 return true;
255 }
256
257 // Determine if a sequence is sorted.
258 template<typename _InputIterator>
97d57665 259 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
260 inline bool
261 __check_sorted(const _InputIterator& __first, const _InputIterator& __last)
262 {
0545ebf2
FD
263 return __check_sorted_aux(__first, __last,
264 std::__iterator_category(__first));
d2763ab5
BK
265 }
266
267 template<typename _InputIterator, typename _Predicate>
97d57665 268 _GLIBCXX20_CONSTEXPR
d2763ab5
BK
269 inline bool
270 __check_sorted(const _InputIterator& __first, const _InputIterator& __last,
271 _Predicate __pred)
272 {
0545ebf2
FD
273 return __check_sorted_aux(__first, __last, __pred,
274 std::__iterator_category(__first));
a4c07f2d
PC
275 }
276
a6becb0e 277 template<typename _InputIterator>
97d57665 278 _GLIBCXX20_CONSTEXPR
a4c07f2d 279 inline bool
a6becb0e
PC
280 __check_sorted_set_aux(const _InputIterator& __first,
281 const _InputIterator& __last,
282 std::__true_type)
a4c07f2d
PC
283 { return __check_sorted(__first, __last); }
284
a6becb0e 285 template<typename _InputIterator>
97d57665 286 _GLIBCXX20_CONSTEXPR
a4c07f2d 287 inline bool
a6becb0e
PC
288 __check_sorted_set_aux(const _InputIterator&,
289 const _InputIterator&,
290 std::__false_type)
a4c07f2d
PC
291 { return true; }
292
a6becb0e 293 template<typename _InputIterator, typename _Predicate>
97d57665 294 _GLIBCXX20_CONSTEXPR
a4c07f2d 295 inline bool
a6becb0e
PC
296 __check_sorted_set_aux(const _InputIterator& __first,
297 const _InputIterator& __last,
298 _Predicate __pred, std::__true_type)
a4c07f2d
PC
299 { return __check_sorted(__first, __last, __pred); }
300
a6becb0e 301 template<typename _InputIterator, typename _Predicate>
97d57665 302 _GLIBCXX20_CONSTEXPR
a4c07f2d 303 inline bool
a6becb0e
PC
304 __check_sorted_set_aux(const _InputIterator&,
305 const _InputIterator&, _Predicate,
a4c07f2d
PC
306 std::__false_type)
307 { return true; }
308
309 // ... special variant used in std::merge, std::includes, std::set_*.
310 template<typename _InputIterator1, typename _InputIterator2>
97d57665 311 _GLIBCXX20_CONSTEXPR
a4c07f2d
PC
312 inline bool
313 __check_sorted_set(const _InputIterator1& __first,
314 const _InputIterator1& __last,
315 const _InputIterator2&)
316 {
317 typedef typename std::iterator_traits<_InputIterator1>::value_type
318 _ValueType1;
319 typedef typename std::iterator_traits<_InputIterator2>::value_type
320 _ValueType2;
321
322 typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
323 _SameType;
324 return __check_sorted_set_aux(__first, __last, _SameType());
d2763ab5
BK
325 }
326
a4c07f2d
PC
327 template<typename _InputIterator1, typename _InputIterator2,
328 typename _Predicate>
97d57665 329 _GLIBCXX20_CONSTEXPR
a4c07f2d
PC
330 inline bool
331 __check_sorted_set(const _InputIterator1& __first,
332 const _InputIterator1& __last,
333 const _InputIterator2&, _Predicate __pred)
334 {
335 typedef typename std::iterator_traits<_InputIterator1>::value_type
336 _ValueType1;
337 typedef typename std::iterator_traits<_InputIterator2>::value_type
338 _ValueType2;
339
340 typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
341 _SameType;
342 return __check_sorted_set_aux(__first, __last, __pred, _SameType());
343 }
344
8915a229
FD
345 // _GLIBCXX_RESOLVE_LIB_DEFECTS
346 // 270. Binary search requirements overly strict
347 // Determine if a sequence is partitioned w.r.t. this element.
d2763ab5 348 template<typename _ForwardIterator, typename _Tp>
97d57665 349 _GLIBCXX20_CONSTEXPR
d2763ab5 350 inline bool
8915a229
FD
351 __check_partitioned_lower(_ForwardIterator __first,
352 _ForwardIterator __last, const _Tp& __value)
d2763ab5
BK
353 {
354 while (__first != __last && *__first < __value)
355 ++__first;
4d02a695
FD
356 if (__first != __last)
357 {
358 ++__first;
359 while (__first != __last && !(*__first < __value))
360 ++__first;
361 }
d2763ab5
BK
362 return __first == __last;
363 }
364
f5ad3163 365 template<typename _ForwardIterator, typename _Tp>
97d57665 366 _GLIBCXX20_CONSTEXPR
f5ad3163 367 inline bool
8915a229 368 __check_partitioned_upper(_ForwardIterator __first,
f5ad3163
PC
369 _ForwardIterator __last, const _Tp& __value)
370 {
371 while (__first != __last && !(__value < *__first))
372 ++__first;
4d02a695
FD
373 if (__first != __last)
374 {
375 ++__first;
376 while (__first != __last && __value < *__first)
377 ++__first;
378 }
f5ad3163
PC
379 return __first == __last;
380 }
381
8915a229 382 // Determine if a sequence is partitioned w.r.t. this element.
d2763ab5 383 template<typename _ForwardIterator, typename _Tp, typename _Pred>
97d57665 384 _GLIBCXX20_CONSTEXPR
d2763ab5 385 inline bool
8915a229
FD
386 __check_partitioned_lower(_ForwardIterator __first,
387 _ForwardIterator __last, const _Tp& __value,
388 _Pred __pred)
f5ad3163
PC
389 {
390 while (__first != __last && bool(__pred(*__first, __value)))
391 ++__first;
4d02a695
FD
392 if (__first != __last)
393 {
394 ++__first;
395 while (__first != __last && !bool(__pred(*__first, __value)))
396 ++__first;
397 }
f5ad3163
PC
398 return __first == __last;
399 }
400
401 template<typename _ForwardIterator, typename _Tp, typename _Pred>
97d57665 402 _GLIBCXX20_CONSTEXPR
f5ad3163 403 inline bool
8915a229 404 __check_partitioned_upper(_ForwardIterator __first,
f5ad3163
PC
405 _ForwardIterator __last, const _Tp& __value,
406 _Pred __pred)
d2763ab5 407 {
f5ad3163 408 while (__first != __last && !bool(__pred(__value, *__first)))
d2763ab5 409 ++__first;
4d02a695
FD
410 if (__first != __last)
411 {
412 ++__first;
413 while (__first != __last && bool(__pred(__value, *__first)))
414 ++__first;
415 }
d2763ab5
BK
416 return __first == __last;
417 }
0545ebf2 418
630a286a
FD
419#if __cplusplus >= 201103L
420 struct _Irreflexive_checker
421 {
422 template<typename _It>
423 static typename std::iterator_traits<_It>::reference
424 __deref();
425
426 template<typename _It,
427 typename = decltype(__deref<_It>() < __deref<_It>())>
97d57665 428 _GLIBCXX20_CONSTEXPR
630a286a
FD
429 static bool
430 _S_is_valid(_It __it)
431 { return !(*__it < *__it); }
432
433 // Fallback method if operator doesn't exist.
434 template<typename... _Args>
97d57665 435 _GLIBCXX20_CONSTEXPR
630a286a
FD
436 static bool
437 _S_is_valid(_Args...)
438 { return true; }
439
440 template<typename _It, typename _Pred, typename
441 = decltype(std::declval<_Pred>()(__deref<_It>(), __deref<_It>()))>
97d57665 442 _GLIBCXX20_CONSTEXPR
630a286a
FD
443 static bool
444 _S_is_valid_pred(_It __it, _Pred __pred)
445 { return !__pred(*__it, *__it); }
446
447 // Fallback method if predicate can't be invoked.
448 template<typename... _Args>
97d57665 449 _GLIBCXX20_CONSTEXPR
630a286a
FD
450 static bool
451 _S_is_valid_pred(_Args...)
452 { return true; }
453 };
454
455 template<typename _Iterator>
97d57665 456 _GLIBCXX20_CONSTEXPR
630a286a
FD
457 inline bool
458 __is_irreflexive(_Iterator __it)
459 { return _Irreflexive_checker::_S_is_valid(__it); }
460
461 template<typename _Iterator, typename _Pred>
97d57665 462 _GLIBCXX20_CONSTEXPR
630a286a
FD
463 inline bool
464 __is_irreflexive_pred(_Iterator __it, _Pred __pred)
465 { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); }
466#endif
467
d2763ab5
BK
468} // namespace __gnu_debug
469
470#endif