(root)/
gcc-13.2.0/
libstdc++-v3/
include/
debug/
functions.h
       1  // Debugging support implementation -*- C++ -*-
       2  
       3  // Copyright (C) 2003-2023 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_t.
      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
      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
      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
      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
     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
     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
     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
     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
     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 = std::__conditional_t<__lvalref::value, __contiguous,
     162  					 std::__false_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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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
     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        __ref();
     425  
     426      template<typename _It,
     427  	     typename = decltype(__ref<_It>() < __ref<_It>())>
     428        _GLIBCXX20_CONSTEXPR
     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>
     435        _GLIBCXX20_CONSTEXPR
     436        static bool
     437        _S_is_valid(_Args...)
     438        { return true; }
     439  
     440      template<typename _It, typename _Pred, typename
     441  	= decltype(std::declval<_Pred>()(__ref<_It>(), __ref<_It>()))>
     442        _GLIBCXX20_CONSTEXPR
     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>
     449        _GLIBCXX20_CONSTEXPR
     450        static bool
     451        _S_is_valid_pred(_Args...)
     452        { return true; }
     453    };
     454  
     455    template<typename _Iterator>
     456      _GLIBCXX20_CONSTEXPR
     457      inline bool
     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
     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