LCOV - code coverage report
Current view: top level - gcc - iterator-utils.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 21 21
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Iterator-related utilities.
       2              : // Copyright (C) 2002-2026 Free Software Foundation, Inc.
       3              : //
       4              : // This file is part of GCC.
       5              : //
       6              : // GCC is free software; you can redistribute it and/or modify it under
       7              : // the terms of the GNU General Public License as published by the Free
       8              : // Software Foundation; either version 3, or (at your option) any later
       9              : // version.
      10              : //
      11              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : // for more details.
      15              : //
      16              : // You should have received a copy of the GNU General Public License
      17              : // along with GCC; see the file COPYING3.  If not see
      18              : // <http://www.gnu.org/licenses/>.
      19              : 
      20              : #ifndef GCC_ITERATOR_UTILS_H
      21              : #define GCC_ITERATOR_UTILS_H 1
      22              : 
      23              : // A half-open [begin, end) range of iterators.
      24              : template<typename T>
      25              : struct iterator_range
      26              : {
      27              : public:
      28              :   using const_iterator = T;
      29              : 
      30              :   iterator_range () = default;
      31   1601873216 :   iterator_range (const T &begin, const T &end)
      32   1330741077 :     : m_begin (begin), m_end (end) {}
      33              : 
      34              :   T begin () const { return m_begin; }
      35              :   T end () const { return m_end; }
      36              : 
      37      2181179 :   explicit operator bool () const { return m_begin != m_end; }
      38              : 
      39              : private:
      40              :   T m_begin;
      41              :   T m_end;
      42              : };
      43              : 
      44              : // Provide an iterator like BaseIT, except that it yields values of type T,
      45              : // which is derived from the type that BaseIT normally yields.
      46              : //
      47              : // The class doesn't inherit from BaseIT for two reasons:
      48              : // - using inheritance would stop the class working with plain pointers
      49              : // - not using inheritance increases type-safety for writable iterators
      50              : //
      51              : // Constructing this class from a BaseIT involves an assertion that all
      52              : // contents really do have type T.  The constructor is therefore explicit.
      53              : template<typename T, typename BaseIT>
      54              : class derived_iterator
      55              : {
      56              : public:
      57              :   using value_type = T;
      58              : 
      59              :   derived_iterator () = default;
      60              : 
      61              :   template<typename... Ts>
      62    906502394 :   explicit derived_iterator (Ts... args)
      63              :     : m_base (std::forward<Ts> (args)...) {}
      64              : 
      65   1094535802 :   derived_iterator &operator++ () { ++m_base; return *this; }
      66              :   derived_iterator operator++ (int);
      67              : 
      68   1113540645 :   T operator* () const { return static_cast<T> (*m_base); }
      69              :   T *operator-> () const { return static_cast<T *> (m_base.operator-> ()); }
      70              : 
      71              :   bool operator== (const derived_iterator &other) const;
      72              :   bool operator!= (const derived_iterator &other) const;
      73              : 
      74              : protected:
      75              :   BaseIT m_base;
      76              : };
      77              : 
      78              : template<typename T, typename BaseIT>
      79              : inline derived_iterator<T, BaseIT>
      80              : derived_iterator<T, BaseIT>::operator++ (int)
      81              : {
      82              :   derived_iterator ret = *this;
      83              :   ++m_base;
      84              :   return ret;
      85              : }
      86              : 
      87              : template<typename T, typename BaseIT>
      88              : inline bool
      89              : derived_iterator<T, BaseIT>::operator== (const derived_iterator &other) const
      90              : {
      91              :   return m_base == other.m_base;
      92              : }
      93              : 
      94              : template<typename T, typename BaseIT>
      95              : inline bool
      96              : derived_iterator<T, BaseIT>::operator!= (const derived_iterator &other) const
      97              : {
      98              :   return m_base != other.m_base;
      99              : }
     100              : 
     101              : // Provide a constant view of a BaseCT in which every value is known to
     102              : // have type T, which is derived from the type that BaseCT normally presents.
     103              : //
     104              : // Constructing this class from a BaseCT involves an assertion that all
     105              : // contents really do have type T.  The constructor is therefore explicit.
     106              : template<typename T, typename BaseCT>
     107              : class const_derived_container : public BaseCT
     108              : {
     109              :   using base_const_iterator = typename BaseCT::const_iterator;
     110              : 
     111              : public:
     112              :   using value_type = T;
     113              :   using const_iterator = derived_iterator<T, base_const_iterator>;
     114              : 
     115     25125558 :   const_derived_container () = default;
     116              : 
     117              :   template<typename... Ts>
     118   1202799177 :   explicit const_derived_container (Ts... args)
     119   1096903916 :     : BaseCT (std::forward<Ts> (args)...) {}
     120              : 
     121    906502394 :   const_iterator begin () const { return const_iterator (BaseCT::begin ()); }
     122    906502394 :   const_iterator end () const { return const_iterator (BaseCT::end ()); }
     123              : 
     124              :   T front () const { return static_cast<T> (BaseCT::front ()); }
     125    112268371 :   T back () const { return static_cast<T> (BaseCT::back ()); }
     126              :   T operator[] (unsigned int i) const;
     127              : };
     128              : 
     129              : template<typename T, typename BaseCT>
     130              : inline T
     131     95338145 : const_derived_container<T, BaseCT>::operator[] (unsigned int i) const
     132              : {
     133    140469984 :   return static_cast<T> (BaseCT::operator[] (i));
     134              : }
     135              : 
     136              : // A base class for iterators whose contents consist of a StoredT and that
     137              : // when dereferenced yield those StoredT contents as a T.  Derived classes
     138              : // should implement at least operator++ or operator--.
     139              : template<typename T, typename StoredT = T>
     140              : class wrapper_iterator
     141              : {
     142              : public:
     143              :   using value_type = T;
     144              : 
     145              :   wrapper_iterator () = default;
     146              : 
     147              :   template<typename... Ts>
     148    330160848 :   wrapper_iterator (Ts... args) : m_contents (std::forward<Ts> (args)...) {}
     149              : 
     150              :   T operator* () const { return static_cast<T> (m_contents); }
     151              :   bool operator== (const wrapper_iterator &) const;
     152              :   bool operator!= (const wrapper_iterator &) const;
     153              : 
     154              : protected:
     155              :   StoredT m_contents;
     156              : };
     157              : 
     158              : template<typename T, typename StoredT>
     159              : inline bool
     160              : wrapper_iterator<T, StoredT>::operator== (const wrapper_iterator &other) const
     161              : {
     162              :   return m_contents == other.m_contents;
     163              : }
     164              : 
     165              : template<typename T, typename StoredT>
     166              : inline bool
     167    171182855 : wrapper_iterator<T, StoredT>::operator!= (const wrapper_iterator &other) const
     168              : {
     169    171182855 :   return m_contents != other.m_contents;
     170              : }
     171              : 
     172              : // A forward iterator for a linked list whose nodes are referenced using
     173              : // type T.  Given a node "T N", the next element is given by (N->*Next) ().
     174              : template<typename T, T *(T::*Next) () const>
     175              : class list_iterator : public wrapper_iterator<T *>
     176              : {
     177              : private:
     178              :   using parent = wrapper_iterator<T *>;
     179              : 
     180              : public:
     181    330160848 :   using parent::parent;
     182              :   list_iterator &operator++ ();
     183              :   list_iterator operator++ (int);
     184              : };
     185              : 
     186              : template<typename T, T *(T::*Next) () const>
     187              : inline list_iterator<T, Next> &
     188    470788634 : list_iterator<T, Next>::operator++ ()
     189              : {
     190    751976674 :   this->m_contents = (this->m_contents->*Next) ();
     191    279787868 :   return *this;
     192              : }
     193              : 
     194              : template<typename T, T *(T::*Next) () const>
     195              : inline list_iterator<T, Next>
     196              : list_iterator<T, Next>::operator++ (int)
     197              : {
     198              :   list_iterator ret = *this;
     199              :   this->m_contents = (this->m_contents->*Next) ();
     200              :   return ret;
     201              : }
     202              : 
     203              : // An iterator that pre-computes the next value if we haven't already got to the
     204              : // end.  This is useful in cases where a standard iterator would get invalidated
     205              : // (e.g. elements getting removed from a container) during the body of a loop.
     206              : template<typename T>
     207              : class safe_iterator
     208              : {
     209              :   T m_current;
     210              :   const T m_end;
     211              :   T m_next;
     212              : 
     213              :   T get_next ()
     214              :   {
     215              :     if (m_current != m_end)
     216              :       {
     217              :         // FIXME: we should use std::next here but that would mean having
     218              :         // #include <iterator> everywhere that iterator-utils.h is included.
     219              :         //
     220              :         // For now we just implement it directly.
     221              :         T iter = m_current;
     222              :         return ++iter;
     223              :       }
     224              :     return m_end;
     225              :   }
     226              : 
     227              :   void advance ()
     228              :   {
     229              :     m_current = m_next;
     230              :     if (m_next != m_end)
     231              :       ++m_next;
     232              :   }
     233              : 
     234              : public:
     235              :   bool operator== (const safe_iterator &other) const
     236              :   {
     237              :     return m_current == other.m_current;
     238              :   }
     239              : 
     240              :   bool operator!= (const safe_iterator &other) const
     241              :   {
     242              :     return m_current != other.m_current;
     243              :   }
     244              : 
     245              :   typename T::value_type operator*() const { return *m_current; }
     246              : 
     247              :   safe_iterator &operator++ ()
     248              :   {
     249              :     advance ();
     250              :     return *this;
     251              :   }
     252              : 
     253              :   safe_iterator operator++ (int)
     254              :   {
     255              :     auto ret = *this;
     256              :     advance ();
     257              :     return ret;
     258              :   }
     259              : 
     260              :   safe_iterator (T iter, T end)
     261              :     : m_current (iter), m_end (end), m_next (get_next ()) {}
     262              : };
     263              : 
     264              : // Convert a container RANGE into a container of safe_iterators.
     265              : template<typename Container>
     266              : inline
     267              : iterator_range<safe_iterator<typename Container::const_iterator>>
     268              : iterate_safely (Container range)
     269              : {
     270              :   return {
     271              :     { range.begin (), range.end () },
     272              :     { range.end (), range.end () }
     273              :   };
     274              : }
     275              : 
     276              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.