LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/ADT - ilist_iterator.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 95.5 % 22 21
Test Date: 2026-02-27 04:14:43 Functions: 76.5 % 17 13
Legend: Lines:     hit not hit

            Line data    Source code
       1              : //===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===//
       2              : //
       3              : // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4              : // See https://llvm.org/LICENSE.txt for license information.
       5              : // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6              : //
       7              : //===----------------------------------------------------------------------===//
       8              : 
       9              : #ifndef LLVM_ADT_ILIST_ITERATOR_H
      10              : #define LLVM_ADT_ILIST_ITERATOR_H
      11              : 
      12              : #include "llvm/ADT/ilist_node.h"
      13              : #include <cassert>
      14              : #include <cstddef>
      15              : #include <iterator>
      16              : #include <type_traits>
      17              : 
      18              : namespace llvm {
      19              : 
      20              : namespace ilist_detail {
      21              : 
      22              : /// Find const-correct node types.
      23              : template <class OptionsT, bool IsConst> struct IteratorTraits;
      24              : template <class OptionsT> struct IteratorTraits<OptionsT, false> {
      25              :   using value_type = typename OptionsT::value_type;
      26              :   using pointer = typename OptionsT::pointer;
      27              :   using reference = typename OptionsT::reference;
      28              :   using node_pointer = ilist_node_impl<OptionsT> *;
      29              :   using node_reference = ilist_node_impl<OptionsT> &;
      30              : };
      31              : template <class OptionsT> struct IteratorTraits<OptionsT, true> {
      32              :   using value_type = const typename OptionsT::value_type;
      33              :   using pointer = typename OptionsT::const_pointer;
      34              :   using reference = typename OptionsT::const_reference;
      35              :   using node_pointer = const ilist_node_impl<OptionsT> *;
      36              :   using node_reference = const ilist_node_impl<OptionsT> &;
      37              : };
      38              : 
      39              : template <bool IsReverse> struct IteratorHelper;
      40              : template <> struct IteratorHelper<false> : ilist_detail::NodeAccess {
      41              :   using Access = ilist_detail::NodeAccess;
      42              : 
      43              :   template <class T> static void increment(T *&I) { I = Access::getNext(*I); }
      44              :   template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); }
      45              : };
      46              : template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
      47              :   using Access = ilist_detail::NodeAccess;
      48              : 
      49              :   template <class T> static void increment(T *&I) { I = Access::getPrev(*I); }
      50              :   template <class T> static void decrement(T *&I) { I = Access::getNext(*I); }
      51              : };
      52              : 
      53              : /// Mixin class used to add a \a getNodeParent() function to iterators iff the
      54              : /// list uses \a ilist_parent, calling through to the node's \a getParent(). For
      55              : /// more details see \a ilist_node.
      56              : template <class IteratorTy, class ParentTy, bool IsConst>
      57              : class iterator_parent_access;
      58              : template <class IteratorTy, class ParentTy>
      59              : class iterator_parent_access<IteratorTy, ParentTy, true> {
      60              : public:
      61              :   inline const ParentTy *getNodeParent() const {
      62              :     return static_cast<IteratorTy *>(this)->NodePtr->getParent();
      63              :   }
      64              : };
      65              : template <class IteratorTy, class ParentTy>
      66              : class iterator_parent_access<IteratorTy, ParentTy, false> {
      67              : public:
      68              :   inline ParentTy *getNodeParent() {
      69              :     return static_cast<IteratorTy *>(this)->NodePtr->getParent();
      70              :   }
      71              : };
      72              : template <class IteratorTy>
      73              : class iterator_parent_access<IteratorTy, void, true> {};
      74              : template <class IteratorTy>
      75              : class iterator_parent_access<IteratorTy, void, false> {};
      76              : 
      77              : } // end namespace ilist_detail
      78              : 
      79              : /// Iterator for intrusive lists  based on ilist_node.
      80              : template <class OptionsT, bool IsReverse, bool IsConst>
      81              : class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT>,
      82              :                        public ilist_detail::iterator_parent_access<
      83              :                            ilist_iterator<OptionsT, IsReverse, IsConst>,
      84              :                            typename OptionsT::parent_ty, IsConst> {
      85              :   friend ilist_iterator<OptionsT, IsReverse, !IsConst>;
      86              :   friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
      87              :   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
      88              :   friend ilist_detail::iterator_parent_access<
      89              :       ilist_iterator<OptionsT, IsReverse, IsConst>,
      90              :       typename OptionsT::parent_ty, IsConst>;
      91              : 
      92              :   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
      93              :   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
      94              : 
      95              : public:
      96              :   using value_type = typename Traits::value_type;
      97              :   using pointer = typename Traits::pointer;
      98              :   using reference = typename Traits::reference;
      99              :   using difference_type = ptrdiff_t;
     100              :   using iterator_category = std::bidirectional_iterator_tag;
     101              :   using const_pointer = typename OptionsT::const_pointer;
     102              :   using const_reference = typename OptionsT::const_reference;
     103              : 
     104              : private:
     105              :   using node_pointer = typename Traits::node_pointer;
     106              :   using node_reference = typename Traits::node_reference;
     107              : 
     108              :   node_pointer NodePtr = nullptr;
     109              : 
     110              : public:
     111              :   /// Create from an ilist_node.
     112         8666 :   explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
     113              : 
     114              :   explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {}
     115              :   explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {}
     116              :   ilist_iterator() = default;
     117              : 
     118              :   // This is templated so that we can allow constructing a const iterator from
     119              :   // a nonconst iterator...
     120              :   template <bool RHSIsConst>
     121              :   ilist_iterator(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS,
     122              :                  std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
     123              :       : NodePtr(RHS.NodePtr) {}
     124              : 
     125              :   // This is templated so that we can allow assigning to a const iterator from
     126              :   // a nonconst iterator...
     127              :   template <bool RHSIsConst>
     128              :   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator &>
     129              :   operator=(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS) {
     130              :     NodePtr = RHS.NodePtr;
     131              :     return *this;
     132              :   }
     133              : 
     134              :   /// Explicit conversion between forward/reverse iterators.
     135              :   ///
     136              :   /// Translate between forward and reverse iterators without changing range
     137              :   /// boundaries.  The resulting iterator will dereference (and have a handle)
     138              :   /// to the previous node, which is somewhat unexpected; but converting the
     139              :   /// two endpoints in a range will give the same range in reverse.
     140              :   ///
     141              :   /// This matches std::reverse_iterator conversions.
     142              :   explicit ilist_iterator(
     143              :       const ilist_iterator<OptionsT, !IsReverse, IsConst> &RHS)
     144              :       : ilist_iterator(++RHS.getReverse()) {}
     145              : 
     146              :   /// Get a reverse iterator to the same node.
     147              :   ///
     148              :   /// Gives a reverse iterator that will dereference (and have a handle) to the
     149              :   /// same node.  Converting the endpoint iterators in a range will give a
     150              :   /// different range; for range operations, use the explicit conversions.
     151              :   ilist_iterator<OptionsT, !IsReverse, IsConst> getReverse() const {
     152              :     if (NodePtr)
     153              :       return ilist_iterator<OptionsT, !IsReverse, IsConst>(*NodePtr);
     154              :     return ilist_iterator<OptionsT, !IsReverse, IsConst>();
     155              :   }
     156              : 
     157              :   /// Const-cast.
     158              :   ilist_iterator<OptionsT, IsReverse, false> getNonConst() const {
     159              :     if (NodePtr)
     160              :       return ilist_iterator<OptionsT, IsReverse, false>(
     161              :           const_cast<typename ilist_iterator<OptionsT, IsReverse,
     162              :                                              false>::node_reference>(*NodePtr));
     163              :     return ilist_iterator<OptionsT, IsReverse, false>();
     164              :   }
     165              : 
     166              :   // Accessors...
     167        60983 :   reference operator*() const {
     168        60983 :     assert(!NodePtr->isKnownSentinel());
     169        60983 :     return *Access::getValuePtr(NodePtr);
     170              :   }
     171              :   pointer operator->() const { return &operator*(); }
     172              : 
     173              :   // Comparison operators
     174              :   friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
     175              :     return LHS.NodePtr == RHS.NodePtr;
     176              :   }
     177        65316 :   friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
     178        65316 :     return LHS.NodePtr != RHS.NodePtr;
     179              :   }
     180              : 
     181              :   // Increment and decrement operators...
     182              :   ilist_iterator &operator--() {
     183              :     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
     184              :     return *this;
     185              :   }
     186        65316 :   ilist_iterator &operator++() {
     187        65316 :     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
     188        65316 :     return *this;
     189              :   }
     190              :   ilist_iterator operator--(int) {
     191              :     ilist_iterator tmp = *this;
     192              :     --*this;
     193              :     return tmp;
     194              :   }
     195              :   ilist_iterator operator++(int) {
     196              :     ilist_iterator tmp = *this;
     197              :     ++*this;
     198              :     return tmp;
     199              :   }
     200              : 
     201              :   bool isValid() const { return NodePtr; }
     202              : 
     203              :   /// Get the underlying ilist_node.
     204              :   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
     205              : 
     206              :   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
     207              :   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
     208              : };
     209              : 
     210              : /// Iterator for intrusive lists  based on ilist_node. Much like ilist_iterator,
     211              : /// but with the addition of two bits recording whether this position (when in
     212              : /// a range) is half or fully open.
     213              : template <class OptionsT, bool IsReverse, bool IsConst>
     214              : class ilist_iterator_w_bits
     215              :     : ilist_detail::SpecificNodeAccess<OptionsT>,
     216              :       public ilist_detail::iterator_parent_access<
     217              :           ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
     218              :           typename OptionsT::parent_ty, IsConst> {
     219              :   friend ilist_iterator_w_bits<OptionsT, IsReverse, !IsConst>;
     220              :   friend ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>;
     221              :   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
     222              :   friend ilist_detail::iterator_parent_access<
     223              :       ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
     224              :       typename OptionsT::parent_ty, IsConst>;
     225              : 
     226              :   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
     227              :   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
     228              : 
     229              : public:
     230              :   using value_type = typename Traits::value_type;
     231              :   using pointer = typename Traits::pointer;
     232              :   using reference = typename Traits::reference;
     233              :   using difference_type = ptrdiff_t;
     234              :   using iterator_category = std::bidirectional_iterator_tag;
     235              :   using const_pointer = typename OptionsT::const_pointer;
     236              :   using const_reference = typename OptionsT::const_reference;
     237              : 
     238              : private:
     239              :   using node_pointer = typename Traits::node_pointer;
     240              :   using node_reference = typename Traits::node_reference;
     241              : 
     242              :   node_pointer NodePtr = nullptr;
     243              : 
     244              :   /// Is this position intended to contain any debug-info immediately before
     245              :   /// the position?
     246              :   mutable bool HeadInclusiveBit = false;
     247              :   /// Is this position intended to contain any debug-info immediately after
     248              :   /// the position?
     249              :   mutable bool TailInclusiveBit = false;
     250              : 
     251              : public:
     252              :   /// Create from an ilist_node.
     253       117082 :   explicit ilist_iterator_w_bits(node_reference N) : NodePtr(&N) {}
     254              : 
     255              :   explicit ilist_iterator_w_bits(pointer NP)
     256              :       : NodePtr(Access::getNodePtr(NP)) {}
     257              :   explicit ilist_iterator_w_bits(reference NR)
     258              :       : NodePtr(Access::getNodePtr(&NR)) {}
     259            0 :   ilist_iterator_w_bits() = default;
     260              : 
     261              :   // This is templated so that we can allow constructing a const iterator from
     262              :   // a nonconst iterator...
     263              :   template <bool RHSIsConst>
     264              :   ilist_iterator_w_bits(
     265              :       const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS,
     266              :       std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
     267              :       : NodePtr(RHS.NodePtr) {
     268              :     HeadInclusiveBit = RHS.HeadInclusiveBit;
     269              :     TailInclusiveBit = RHS.TailInclusiveBit;
     270              :   }
     271              : 
     272              :   // This is templated so that we can allow assigning to a const iterator from
     273              :   // a nonconst iterator...
     274              :   template <bool RHSIsConst>
     275              :   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator_w_bits &>
     276              :   operator=(const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS) {
     277              :     NodePtr = RHS.NodePtr;
     278              :     HeadInclusiveBit = RHS.HeadInclusiveBit;
     279              :     TailInclusiveBit = RHS.TailInclusiveBit;
     280              :     return *this;
     281              :   }
     282              : 
     283              :   /// Explicit conversion between forward/reverse iterators.
     284              :   ///
     285              :   /// Translate between forward and reverse iterators without changing range
     286              :   /// boundaries.  The resulting iterator will dereference (and have a handle)
     287              :   /// to the previous node, which is somewhat unexpected; but converting the
     288              :   /// two endpoints in a range will give the same range in reverse.
     289              :   ///
     290              :   /// This matches std::reverse_iterator conversions.
     291              :   explicit ilist_iterator_w_bits(
     292              :       const ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> &RHS)
     293              :       : ilist_iterator_w_bits(++RHS.getReverse()) {}
     294              : 
     295              :   /// Get a reverse iterator to the same node.
     296              :   ///
     297              :   /// Gives a reverse iterator that will dereference (and have a handle) to the
     298              :   /// same node.  Converting the endpoint iterators in a range will give a
     299              :   /// different range; for range operations, use the explicit conversions.
     300              :   ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> getReverse() const {
     301              :     if (NodePtr)
     302              :       return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>(*NodePtr);
     303              :     return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>();
     304              :   }
     305              : 
     306              :   /// Const-cast.
     307              :   ilist_iterator_w_bits<OptionsT, IsReverse, false> getNonConst() const {
     308              :     if (NodePtr) {
     309              :       auto New = ilist_iterator_w_bits<OptionsT, IsReverse, false>(
     310              :           const_cast<typename ilist_iterator_w_bits<OptionsT, IsReverse,
     311              :                                                     false>::node_reference>(
     312              :               *NodePtr));
     313              :       New.HeadInclusiveBit = HeadInclusiveBit;
     314              :       New.TailInclusiveBit = TailInclusiveBit;
     315              :       return New;
     316              :     }
     317              :     return ilist_iterator_w_bits<OptionsT, IsReverse, false>();
     318              :   }
     319              : 
     320              :   // Accessors...
     321       284157 :   reference operator*() const {
     322       284157 :     assert(!NodePtr->isKnownSentinel());
     323       284157 :     return *Access::getValuePtr(NodePtr);
     324              :   }
     325              :   pointer operator->() const { return &operator*(); }
     326              : 
     327              :   // Comparison operators
     328              :   friend bool operator==(const ilist_iterator_w_bits &LHS,
     329              :                          const ilist_iterator_w_bits &RHS) {
     330              :     return LHS.NodePtr == RHS.NodePtr;
     331              :   }
     332       342698 :   friend bool operator!=(const ilist_iterator_w_bits &LHS,
     333              :                          const ilist_iterator_w_bits &RHS) {
     334       342698 :     return LHS.NodePtr != RHS.NodePtr;
     335              :   }
     336              : 
     337              :   // Increment and decrement operators...
     338              :   ilist_iterator_w_bits &operator--() {
     339              :     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
     340              :     HeadInclusiveBit = false;
     341              :     TailInclusiveBit = false;
     342              :     return *this;
     343              :   }
     344       342698 :   ilist_iterator_w_bits &operator++() {
     345       342698 :     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
     346       342698 :     HeadInclusiveBit = false;
     347       342698 :     TailInclusiveBit = false;
     348       342698 :     return *this;
     349              :   }
     350              :   ilist_iterator_w_bits operator--(int) {
     351              :     ilist_iterator_w_bits tmp = *this;
     352              :     --*this;
     353              :     return tmp;
     354              :   }
     355              :   ilist_iterator_w_bits operator++(int) {
     356              :     ilist_iterator_w_bits tmp = *this;
     357              :     ++*this;
     358              :     return tmp;
     359              :   }
     360              : 
     361              :   bool isValid() const { return NodePtr; }
     362              : 
     363              :   /// Get the underlying ilist_node.
     364              :   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
     365              : 
     366              :   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
     367              :   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
     368              : 
     369              :   bool getHeadBit() const { return HeadInclusiveBit; }
     370              :   bool getTailBit() const { return TailInclusiveBit; }
     371        58541 :   void setHeadBit(bool SetBit) const { HeadInclusiveBit = SetBit; }
     372              :   void setTailBit(bool SetBit) const { TailInclusiveBit = SetBit; }
     373              : };
     374              : 
     375              : template <typename From> struct simplify_type;
     376              : 
     377              : /// Allow ilist_iterators to convert into pointers to a node automatically when
     378              : /// used by the dyn_cast, cast, isa mechanisms...
     379              : ///
     380              : /// FIXME: remove this, since there is no implicit conversion to NodeTy.
     381              : template <class OptionsT, bool IsConst>
     382              : struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> {
     383              :   using iterator = ilist_iterator<OptionsT, false, IsConst>;
     384              :   using SimpleType = typename iterator::pointer;
     385              : 
     386              :   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
     387              : };
     388              : template <class OptionsT, bool IsConst>
     389              : struct simplify_type<const ilist_iterator<OptionsT, false, IsConst>>
     390              :     : simplify_type<ilist_iterator<OptionsT, false, IsConst>> {};
     391              : 
     392              : // ilist_iterator_w_bits should also be accessible via isa/dyn_cast.
     393              : template <class OptionsT, bool IsConst>
     394              : struct simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {
     395              :   using iterator = ilist_iterator_w_bits<OptionsT, false, IsConst>;
     396              :   using SimpleType = typename iterator::pointer;
     397              : 
     398              :   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
     399              : };
     400              : template <class OptionsT, bool IsConst>
     401              : struct simplify_type<const ilist_iterator_w_bits<OptionsT, false, IsConst>>
     402              :     : simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {};
     403              : 
     404              : } // end namespace llvm
     405              : 
     406              : #endif // LLVM_ADT_ILIST_ITERATOR_H
        

Generated by: LCOV version 2.0-1