1 // Debugging support implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2020 Free Software Foundation, Inc.
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
8 // Free Software Foundation; either version 3, or (at your option)
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 
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/>.
24 
25 /** @file debug/functions.h
26  *  This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
30 #define _GLIBCXX_DEBUG_FUNCTIONS_H 1
31 
32 #include <bits/stl_function.h>	// for less
33 
34 #if __cplusplus >= 201103L
35 # include <bits/stl_iterator.h>	// for __miter_base
36 # include <type_traits>		// for is_lvalue_reference and conditional.
37 #endif
38 
39 #include <debug/helper_functions.h>
40 #include <debug/formatter.h>
41 
42 namespace __gnu_debug
43 {
44   template<typename _Sequence>
45     struct _Insert_range_from_self_is_safe
46     { enum { __value = 0 }; };
47 
48   template<typename _Sequence>
49     struct _Is_contiguous_sequence : std::__false_type { };
50 
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
__check_valid_range(const _InputIterator & __first,const _InputIterator & __last,const char * __file,unsigned int __line,const char * __function)57     __check_valid_range(const _InputIterator& __first,
58 			const _InputIterator& __last,
59 			const char* __file,
60 			unsigned int __line,
61 			const char* __function)
62     {
63       __glibcxx_check_valid_range_at(__first, __last,
64 				     __file, __line, __function);
65       return __first;
66     }
67 
68   /* Handle the case where __other is a pointer to _Sequence::value_type. */
69   template<typename _Iterator, typename _Sequence, typename _Category>
70     inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,const typename _Sequence::value_type * __other)71     __foreign_iterator_aux4(
72 	const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
73 	const typename _Sequence::value_type* __other)
74     {
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));
85 
86       // Check whether __other points within the contiguous storage.
87       return __l(__other, __begin) || __l(__end, __other);
88     }
89 
90   /* Fallback overload for when we can't tell, assume it is valid. */
91   template<typename _Iterator, typename _Sequence, typename _Category>
92     inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator,_Sequence,_Category> &,...)93     __foreign_iterator_aux4(
94 	const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...)
95     { return true; }
96 
97   /* Handle sequences with contiguous storage */
98   template<typename _Iterator, typename _Sequence, typename _Category,
99 	   typename _InputIterator>
100     inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,const _InputIterator & __other,const _InputIterator & __other_end,std::__true_type)101     __foreign_iterator_aux3(
102 	const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
103 	const _InputIterator& __other, const _InputIterator& __other_end,
104 	std::__true_type)
105     {
106       if (__other == __other_end)
107 	return true;  // inserting nothing is safe even if not foreign iters
108       if (__it._M_get_sequence()->empty())
109 	return true;  // can't be self-inserting if self is empty
110       return __foreign_iterator_aux4(__it, std::__addressof(*__other));
111     }
112 
113   /* Handle non-contiguous containers, assume it is valid. */
114   template<typename _Iterator, typename _Sequence, typename _Category,
115 	   typename _InputIterator>
116     inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator,_Sequence,_Category> &,const _InputIterator &,const _InputIterator &,std::__false_type)117     __foreign_iterator_aux3(
118 	const _Safe_iterator<_Iterator, _Sequence, _Category>&,
119 	const _InputIterator&, const _InputIterator&,
120 	std::__false_type)
121     { return true; }
122 
123   /** Handle debug iterators from the same type of container. */
124   template<typename _Iterator, typename _Sequence, typename _Category,
125 	   typename _OtherIterator>
126     inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,const _Safe_iterator<_OtherIterator,_Sequence,_Category> & __other,const _Safe_iterator<_OtherIterator,_Sequence,_Category> &)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>&)
131     { return __it._M_get_sequence() != __other._M_get_sequence(); }
132 
133   /** Handle debug iterators from different types of container. */
134   template<typename _Iterator, typename _Sequence, typename _Category,
135 	   typename _OtherIterator, typename _OtherSequence,
136 	   typename _OtherCategory>
137     inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator,_Sequence,_Category> &,const _Safe_iterator<_OtherIterator,_OtherSequence,_OtherCategory> &,const _Safe_iterator<_OtherIterator,_OtherSequence,_OtherCategory> &)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>&)
144     { return true; }
145 
146   /* Handle non-debug iterators. */
147   template<typename _Iterator, typename _Sequence, typename _Category,
148 	   typename _InputIterator>
149     inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,const _InputIterator & __other,const _InputIterator & __other_end)150     __foreign_iterator_aux2(
151 	const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
152 	const _InputIterator& __other,
153 	const _InputIterator& __other_end)
154     {
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());
165     }
166 
167   /* Handle the case where we aren't really inserting a range after all */
168   template<typename _Iterator, typename _Sequence, typename _Category,
169 	   typename _Integral>
170     inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator,_Sequence,_Category> &,_Integral,_Integral,std::__true_type)171     __foreign_iterator_aux(
172 	const _Safe_iterator<_Iterator, _Sequence, _Category>&,
173 	_Integral, _Integral, std::__true_type)
174     { return true; }
175 
176   /* Handle all iterators. */
177   template<typename _Iterator, typename _Sequence, typename _Category,
178 	   typename _InputIterator>
179     inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,_InputIterator __other,_InputIterator __other_end,std::__false_type)180     __foreign_iterator_aux(
181 	const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
182 	_InputIterator __other, _InputIterator __other_end,
183 	std::__false_type)
184     {
185       return _Insert_range_from_self_is_safe<_Sequence>::__value
186 	|| __foreign_iterator_aux2(__it, std::__miter_base(__other),
187 				   std::__miter_base(__other_end));
188     }
189 
190   template<typename _Iterator, typename _Sequence, typename _Category,
191 	   typename _InputIterator>
192     inline bool
__foreign_iterator(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,_InputIterator __other,_InputIterator __other_end)193     __foreign_iterator(
194 	const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
195 	_InputIterator __other, _InputIterator __other_end)
196     {
197       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
198       return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
199     }
200 
201   // Can't check if an input iterator sequence is sorted, because we
202   // can't step through the sequence.
203   template<typename _InputIterator>
204     _GLIBCXX20_CONSTEXPR
205     inline bool
__check_sorted_aux(const _InputIterator &,const _InputIterator &,std::input_iterator_tag)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>
213     _GLIBCXX20_CONSTEXPR
214     inline bool
__check_sorted_aux(_ForwardIterator __first,_ForwardIterator __last,std::forward_iterator_tag)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;
222       for (++__next; __next != __last; __first = __next, (void)++__next)
223         if (*__next < *__first)
224           return false;
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>
232     _GLIBCXX20_CONSTEXPR
233     inline bool
__check_sorted_aux(const _InputIterator &,const _InputIterator &,_Predicate,std::input_iterator_tag)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>
241     _GLIBCXX20_CONSTEXPR
242     inline bool
__check_sorted_aux(_ForwardIterator __first,_ForwardIterator __last,_Predicate __pred,std::forward_iterator_tag)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;
250       for (++__next; __next != __last; __first = __next, (void)++__next)
251         if (__pred(*__next, *__first))
252           return false;
253 
254       return true;
255     }
256 
257   // Determine if a sequence is sorted.
258   template<typename _InputIterator>
259     _GLIBCXX20_CONSTEXPR
260     inline bool
__check_sorted(const _InputIterator & __first,const _InputIterator & __last)261     __check_sorted(const _InputIterator& __first, const _InputIterator& __last)
262     {
263       return __check_sorted_aux(__first, __last,
264 				std::__iterator_category(__first));
265     }
266 
267   template<typename _InputIterator, typename _Predicate>
268     _GLIBCXX20_CONSTEXPR
269     inline bool
__check_sorted(const _InputIterator & __first,const _InputIterator & __last,_Predicate __pred)270     __check_sorted(const _InputIterator& __first, const _InputIterator& __last,
271                    _Predicate __pred)
272     {
273       return __check_sorted_aux(__first, __last, __pred,
274 				std::__iterator_category(__first));
275     }
276 
277   template<typename _InputIterator>
278     _GLIBCXX20_CONSTEXPR
279     inline bool
__check_sorted_set_aux(const _InputIterator & __first,const _InputIterator & __last,std::__true_type)280     __check_sorted_set_aux(const _InputIterator& __first,
281 			   const _InputIterator& __last,
282 			   std::__true_type)
283     { return __check_sorted(__first, __last); }
284 
285   template<typename _InputIterator>
286     _GLIBCXX20_CONSTEXPR
287     inline bool
__check_sorted_set_aux(const _InputIterator &,const _InputIterator &,std::__false_type)288     __check_sorted_set_aux(const _InputIterator&,
289 			   const _InputIterator&,
290 			   std::__false_type)
291     { return true; }
292 
293   template<typename _InputIterator, typename _Predicate>
294     _GLIBCXX20_CONSTEXPR
295     inline bool
__check_sorted_set_aux(const _InputIterator & __first,const _InputIterator & __last,_Predicate __pred,std::__true_type)296     __check_sorted_set_aux(const _InputIterator& __first,
297 			   const _InputIterator& __last,
298 			   _Predicate __pred, std::__true_type)
299     { return __check_sorted(__first, __last, __pred); }
300 
301   template<typename _InputIterator, typename _Predicate>
302     _GLIBCXX20_CONSTEXPR
303     inline bool
__check_sorted_set_aux(const _InputIterator &,const _InputIterator &,_Predicate,std::__false_type)304     __check_sorted_set_aux(const _InputIterator&,
305 			   const _InputIterator&, _Predicate,
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>
311     _GLIBCXX20_CONSTEXPR
312     inline bool
__check_sorted_set(const _InputIterator1 & __first,const _InputIterator1 & __last,const _InputIterator2 &)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());
325     }
326 
327   template<typename _InputIterator1, typename _InputIterator2,
328 	   typename _Predicate>
329     _GLIBCXX20_CONSTEXPR
330     inline bool
__check_sorted_set(const _InputIterator1 & __first,const _InputIterator1 & __last,const _InputIterator2 &,_Predicate __pred)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 
345   // _GLIBCXX_RESOLVE_LIB_DEFECTS
346   // 270. Binary search requirements overly strict
347   // Determine if a sequence is partitioned w.r.t. this element.
348   template<typename _ForwardIterator, typename _Tp>
349     _GLIBCXX20_CONSTEXPR
350     inline bool
__check_partitioned_lower(_ForwardIterator __first,_ForwardIterator __last,const _Tp & __value)351     __check_partitioned_lower(_ForwardIterator __first,
352 			      _ForwardIterator __last, const _Tp& __value)
353     {
354       while (__first != __last && *__first < __value)
355 	++__first;
356       if (__first != __last)
357 	{
358 	  ++__first;
359 	  while (__first != __last && !(*__first < __value))
360 	    ++__first;
361 	}
362       return __first == __last;
363     }
364 
365   template<typename _ForwardIterator, typename _Tp>
366     _GLIBCXX20_CONSTEXPR
367     inline bool
__check_partitioned_upper(_ForwardIterator __first,_ForwardIterator __last,const _Tp & __value)368     __check_partitioned_upper(_ForwardIterator __first,
369 			      _ForwardIterator __last, const _Tp& __value)
370     {
371       while (__first != __last && !(__value < *__first))
372 	++__first;
373       if (__first != __last)
374 	{
375 	  ++__first;
376 	  while (__first != __last && __value < *__first)
377 	    ++__first;
378 	}
379       return __first == __last;
380     }
381 
382   // Determine if a sequence is partitioned w.r.t. this element.
383   template<typename _ForwardIterator, typename _Tp, typename _Pred>
384     _GLIBCXX20_CONSTEXPR
385     inline bool
__check_partitioned_lower(_ForwardIterator __first,_ForwardIterator __last,const _Tp & __value,_Pred __pred)386     __check_partitioned_lower(_ForwardIterator __first,
387 			      _ForwardIterator __last, const _Tp& __value,
388 			      _Pred __pred)
389     {
390       while (__first != __last && bool(__pred(*__first, __value)))
391 	++__first;
392       if (__first != __last)
393 	{
394 	  ++__first;
395 	  while (__first != __last && !bool(__pred(*__first, __value)))
396 	    ++__first;
397 	}
398       return __first == __last;
399     }
400 
401   template<typename _ForwardIterator, typename _Tp, typename _Pred>
402     _GLIBCXX20_CONSTEXPR
403     inline bool
__check_partitioned_upper(_ForwardIterator __first,_ForwardIterator __last,const _Tp & __value,_Pred __pred)404     __check_partitioned_upper(_ForwardIterator __first,
405 			      _ForwardIterator __last, const _Tp& __value,
406 			      _Pred __pred)
407     {
408       while (__first != __last && !bool(__pred(__value, *__first)))
409 	++__first;
410       if (__first != __last)
411 	{
412 	  ++__first;
413 	  while (__first != __last && bool(__pred(__value, *__first)))
414 	    ++__first;
415 	}
416       return __first == __last;
417     }
418 
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>())>
428       _GLIBCXX20_CONSTEXPR
429       static bool
_S_is_valid_Irreflexive_checker430       _S_is_valid(_It __it)
431       { return !(*__it < *__it); }
432 
433     // Fallback method if operator doesn't exist.
434     template<typename... _Args>
435       _GLIBCXX20_CONSTEXPR
436       static bool
_S_is_valid_Irreflexive_checker437       _S_is_valid(_Args...)
438       { return true; }
439 
440     template<typename _It, typename _Pred, typename
441 	= decltype(std::declval<_Pred>()(__deref<_It>(), __deref<_It>()))>
442       _GLIBCXX20_CONSTEXPR
443       static bool
_S_is_valid_pred_Irreflexive_checker444       _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>
449       _GLIBCXX20_CONSTEXPR
450       static bool
_S_is_valid_pred_Irreflexive_checker451       _S_is_valid_pred(_Args...)
452       { return true; }
453   };
454 
455   template<typename _Iterator>
456     _GLIBCXX20_CONSTEXPR
457     inline bool
__is_irreflexive(_Iterator __it)458     __is_irreflexive(_Iterator __it)
459     { return _Irreflexive_checker::_S_is_valid(__it); }
460 
461   template<typename _Iterator, typename _Pred>
462     _GLIBCXX20_CONSTEXPR
463     inline bool
__is_irreflexive_pred(_Iterator __it,_Pred __pred)464     __is_irreflexive_pred(_Iterator __it, _Pred __pred)
465     { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); }
466 #endif
467 
468 } // namespace __gnu_debug
469 
470 #endif
471