Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:06

0001 //===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_ADT_ILIST_ITERATOR_H
0010 #define LLVM_ADT_ILIST_ITERATOR_H
0011 
0012 #include "llvm/ADT/ilist_node.h"
0013 #include <cassert>
0014 #include <cstddef>
0015 #include <iterator>
0016 #include <type_traits>
0017 
0018 namespace llvm {
0019 
0020 namespace ilist_detail {
0021 
0022 /// Find const-correct node types.
0023 template <class OptionsT, bool IsConst> struct IteratorTraits;
0024 template <class OptionsT> struct IteratorTraits<OptionsT, false> {
0025   using value_type = typename OptionsT::value_type;
0026   using pointer = typename OptionsT::pointer;
0027   using reference = typename OptionsT::reference;
0028   using node_pointer = ilist_node_impl<OptionsT> *;
0029   using node_reference = ilist_node_impl<OptionsT> &;
0030 };
0031 template <class OptionsT> struct IteratorTraits<OptionsT, true> {
0032   using value_type = const typename OptionsT::value_type;
0033   using pointer = typename OptionsT::const_pointer;
0034   using reference = typename OptionsT::const_reference;
0035   using node_pointer = const ilist_node_impl<OptionsT> *;
0036   using node_reference = const ilist_node_impl<OptionsT> &;
0037 };
0038 
0039 template <bool IsReverse> struct IteratorHelper;
0040 template <> struct IteratorHelper<false> : ilist_detail::NodeAccess {
0041   using Access = ilist_detail::NodeAccess;
0042 
0043   template <class T> static void increment(T *&I) { I = Access::getNext(*I); }
0044   template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); }
0045 };
0046 template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
0047   using Access = ilist_detail::NodeAccess;
0048 
0049   template <class T> static void increment(T *&I) { I = Access::getPrev(*I); }
0050   template <class T> static void decrement(T *&I) { I = Access::getNext(*I); }
0051 };
0052 
0053 /// Mixin class used to add a \a getNodeParent() function to iterators iff the
0054 /// list uses \a ilist_parent, calling through to the node's \a getParent(). For
0055 /// more details see \a ilist_node.
0056 template <class IteratorTy, class ParentTy, bool IsConst>
0057 class iterator_parent_access;
0058 template <class IteratorTy, class ParentTy>
0059 class iterator_parent_access<IteratorTy, ParentTy, true> {
0060 public:
0061   inline const ParentTy *getNodeParent() const {
0062     return static_cast<IteratorTy *>(this)->NodePtr->getParent();
0063   }
0064 };
0065 template <class IteratorTy, class ParentTy>
0066 class iterator_parent_access<IteratorTy, ParentTy, false> {
0067 public:
0068   inline ParentTy *getNodeParent() {
0069     return static_cast<IteratorTy *>(this)->NodePtr->getParent();
0070   }
0071 };
0072 template <class IteratorTy>
0073 class iterator_parent_access<IteratorTy, void, true> {};
0074 template <class IteratorTy>
0075 class iterator_parent_access<IteratorTy, void, false> {};
0076 
0077 } // end namespace ilist_detail
0078 
0079 /// Iterator for intrusive lists  based on ilist_node.
0080 template <class OptionsT, bool IsReverse, bool IsConst>
0081 class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT>,
0082                        public ilist_detail::iterator_parent_access<
0083                            ilist_iterator<OptionsT, IsReverse, IsConst>,
0084                            typename OptionsT::parent_ty, IsConst> {
0085   friend ilist_iterator<OptionsT, IsReverse, !IsConst>;
0086   friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
0087   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
0088   friend ilist_detail::iterator_parent_access<
0089       ilist_iterator<OptionsT, IsReverse, IsConst>,
0090       typename OptionsT::parent_ty, IsConst>;
0091 
0092   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
0093   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
0094 
0095 public:
0096   using value_type = typename Traits::value_type;
0097   using pointer = typename Traits::pointer;
0098   using reference = typename Traits::reference;
0099   using difference_type = ptrdiff_t;
0100   using iterator_category = std::bidirectional_iterator_tag;
0101   using const_pointer = typename OptionsT::const_pointer;
0102   using const_reference = typename OptionsT::const_reference;
0103 
0104 private:
0105   using node_pointer = typename Traits::node_pointer;
0106   using node_reference = typename Traits::node_reference;
0107 
0108   node_pointer NodePtr = nullptr;
0109 
0110 public:
0111   /// Create from an ilist_node.
0112   explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
0113 
0114   explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {}
0115   explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {}
0116   ilist_iterator() = default;
0117 
0118   // This is templated so that we can allow constructing a const iterator from
0119   // a nonconst iterator...
0120   template <bool RHSIsConst>
0121   ilist_iterator(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS,
0122                  std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
0123       : NodePtr(RHS.NodePtr) {}
0124 
0125   // This is templated so that we can allow assigning to a const iterator from
0126   // a nonconst iterator...
0127   template <bool RHSIsConst>
0128   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator &>
0129   operator=(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS) {
0130     NodePtr = RHS.NodePtr;
0131     return *this;
0132   }
0133 
0134   /// Explicit conversion between forward/reverse iterators.
0135   ///
0136   /// Translate between forward and reverse iterators without changing range
0137   /// boundaries.  The resulting iterator will dereference (and have a handle)
0138   /// to the previous node, which is somewhat unexpected; but converting the
0139   /// two endpoints in a range will give the same range in reverse.
0140   ///
0141   /// This matches std::reverse_iterator conversions.
0142   explicit ilist_iterator(
0143       const ilist_iterator<OptionsT, !IsReverse, IsConst> &RHS)
0144       : ilist_iterator(++RHS.getReverse()) {}
0145 
0146   /// Get a reverse iterator to the same node.
0147   ///
0148   /// Gives a reverse iterator that will dereference (and have a handle) to the
0149   /// same node.  Converting the endpoint iterators in a range will give a
0150   /// different range; for range operations, use the explicit conversions.
0151   ilist_iterator<OptionsT, !IsReverse, IsConst> getReverse() const {
0152     if (NodePtr)
0153       return ilist_iterator<OptionsT, !IsReverse, IsConst>(*NodePtr);
0154     return ilist_iterator<OptionsT, !IsReverse, IsConst>();
0155   }
0156 
0157   /// Const-cast.
0158   ilist_iterator<OptionsT, IsReverse, false> getNonConst() const {
0159     if (NodePtr)
0160       return ilist_iterator<OptionsT, IsReverse, false>(
0161           const_cast<typename ilist_iterator<OptionsT, IsReverse,
0162                                              false>::node_reference>(*NodePtr));
0163     return ilist_iterator<OptionsT, IsReverse, false>();
0164   }
0165 
0166   // Accessors...
0167   reference operator*() const {
0168     assert(!NodePtr->isKnownSentinel());
0169     return *Access::getValuePtr(NodePtr);
0170   }
0171   pointer operator->() const { return &operator*(); }
0172 
0173   // Comparison operators
0174   friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
0175     return LHS.NodePtr == RHS.NodePtr;
0176   }
0177   friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
0178     return LHS.NodePtr != RHS.NodePtr;
0179   }
0180 
0181   // Increment and decrement operators...
0182   ilist_iterator &operator--() {
0183     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
0184     return *this;
0185   }
0186   ilist_iterator &operator++() {
0187     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
0188     return *this;
0189   }
0190   ilist_iterator operator--(int) {
0191     ilist_iterator tmp = *this;
0192     --*this;
0193     return tmp;
0194   }
0195   ilist_iterator operator++(int) {
0196     ilist_iterator tmp = *this;
0197     ++*this;
0198     return tmp;
0199   }
0200 
0201   bool isValid() const { return NodePtr; }
0202 
0203   /// Get the underlying ilist_node.
0204   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
0205 
0206   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
0207   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
0208 };
0209 
0210 /// Iterator for intrusive lists  based on ilist_node. Much like ilist_iterator,
0211 /// but with the addition of two bits recording whether this position (when in
0212 /// a range) is half or fully open.
0213 template <class OptionsT, bool IsReverse, bool IsConst>
0214 class ilist_iterator_w_bits
0215     : ilist_detail::SpecificNodeAccess<OptionsT>,
0216       public ilist_detail::iterator_parent_access<
0217           ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
0218           typename OptionsT::parent_ty, IsConst> {
0219   friend ilist_iterator_w_bits<OptionsT, IsReverse, !IsConst>;
0220   friend ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>;
0221   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
0222   friend ilist_detail::iterator_parent_access<
0223       ilist_iterator_w_bits<OptionsT, IsReverse, IsConst>,
0224       typename OptionsT::parent_ty, IsConst>;
0225 
0226   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
0227   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
0228 
0229 public:
0230   using value_type = typename Traits::value_type;
0231   using pointer = typename Traits::pointer;
0232   using reference = typename Traits::reference;
0233   using difference_type = ptrdiff_t;
0234   using iterator_category = std::bidirectional_iterator_tag;
0235   using const_pointer = typename OptionsT::const_pointer;
0236   using const_reference = typename OptionsT::const_reference;
0237 
0238 private:
0239   using node_pointer = typename Traits::node_pointer;
0240   using node_reference = typename Traits::node_reference;
0241 
0242   node_pointer NodePtr = nullptr;
0243 
0244   /// Is this position intended to contain any debug-info immediately before
0245   /// the position?
0246   mutable bool HeadInclusiveBit = false;
0247   /// Is this position intended to contain any debug-info immediately after
0248   /// the position?
0249   mutable bool TailInclusiveBit = false;
0250 
0251 public:
0252   /// Create from an ilist_node.
0253   explicit ilist_iterator_w_bits(node_reference N) : NodePtr(&N) {}
0254 
0255   explicit ilist_iterator_w_bits(pointer NP)
0256       : NodePtr(Access::getNodePtr(NP)) {}
0257   explicit ilist_iterator_w_bits(reference NR)
0258       : NodePtr(Access::getNodePtr(&NR)) {}
0259   ilist_iterator_w_bits() = default;
0260 
0261   // This is templated so that we can allow constructing a const iterator from
0262   // a nonconst iterator...
0263   template <bool RHSIsConst>
0264   ilist_iterator_w_bits(
0265       const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS,
0266       std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
0267       : NodePtr(RHS.NodePtr) {
0268     HeadInclusiveBit = RHS.HeadInclusiveBit;
0269     TailInclusiveBit = RHS.TailInclusiveBit;
0270   }
0271 
0272   // This is templated so that we can allow assigning to a const iterator from
0273   // a nonconst iterator...
0274   template <bool RHSIsConst>
0275   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator_w_bits &>
0276   operator=(const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS) {
0277     NodePtr = RHS.NodePtr;
0278     HeadInclusiveBit = RHS.HeadInclusiveBit;
0279     TailInclusiveBit = RHS.TailInclusiveBit;
0280     return *this;
0281   }
0282 
0283   /// Explicit conversion between forward/reverse iterators.
0284   ///
0285   /// Translate between forward and reverse iterators without changing range
0286   /// boundaries.  The resulting iterator will dereference (and have a handle)
0287   /// to the previous node, which is somewhat unexpected; but converting the
0288   /// two endpoints in a range will give the same range in reverse.
0289   ///
0290   /// This matches std::reverse_iterator conversions.
0291   explicit ilist_iterator_w_bits(
0292       const ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> &RHS)
0293       : ilist_iterator_w_bits(++RHS.getReverse()) {}
0294 
0295   /// Get a reverse iterator to the same node.
0296   ///
0297   /// Gives a reverse iterator that will dereference (and have a handle) to the
0298   /// same node.  Converting the endpoint iterators in a range will give a
0299   /// different range; for range operations, use the explicit conversions.
0300   ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> getReverse() const {
0301     if (NodePtr)
0302       return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>(*NodePtr);
0303     return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>();
0304   }
0305 
0306   /// Const-cast.
0307   ilist_iterator_w_bits<OptionsT, IsReverse, false> getNonConst() const {
0308     if (NodePtr) {
0309       auto New = ilist_iterator_w_bits<OptionsT, IsReverse, false>(
0310           const_cast<typename ilist_iterator_w_bits<OptionsT, IsReverse,
0311                                                     false>::node_reference>(
0312               *NodePtr));
0313       New.HeadInclusiveBit = HeadInclusiveBit;
0314       New.TailInclusiveBit = TailInclusiveBit;
0315       return New;
0316     }
0317     return ilist_iterator_w_bits<OptionsT, IsReverse, false>();
0318   }
0319 
0320   // Accessors...
0321   reference operator*() const {
0322     assert(!NodePtr->isKnownSentinel());
0323     return *Access::getValuePtr(NodePtr);
0324   }
0325   pointer operator->() const { return &operator*(); }
0326 
0327   // Comparison operators
0328   friend bool operator==(const ilist_iterator_w_bits &LHS,
0329                          const ilist_iterator_w_bits &RHS) {
0330     return LHS.NodePtr == RHS.NodePtr;
0331   }
0332   friend bool operator!=(const ilist_iterator_w_bits &LHS,
0333                          const ilist_iterator_w_bits &RHS) {
0334     return LHS.NodePtr != RHS.NodePtr;
0335   }
0336 
0337   // Increment and decrement operators...
0338   ilist_iterator_w_bits &operator--() {
0339     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
0340     HeadInclusiveBit = false;
0341     TailInclusiveBit = false;
0342     return *this;
0343   }
0344   ilist_iterator_w_bits &operator++() {
0345     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
0346     HeadInclusiveBit = false;
0347     TailInclusiveBit = false;
0348     return *this;
0349   }
0350   ilist_iterator_w_bits operator--(int) {
0351     ilist_iterator_w_bits tmp = *this;
0352     --*this;
0353     return tmp;
0354   }
0355   ilist_iterator_w_bits operator++(int) {
0356     ilist_iterator_w_bits tmp = *this;
0357     ++*this;
0358     return tmp;
0359   }
0360 
0361   bool isValid() const { return NodePtr; }
0362 
0363   /// Get the underlying ilist_node.
0364   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
0365 
0366   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
0367   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
0368 
0369   bool getHeadBit() const { return HeadInclusiveBit; }
0370   bool getTailBit() const { return TailInclusiveBit; }
0371   void setHeadBit(bool SetBit) const { HeadInclusiveBit = SetBit; }
0372   void setTailBit(bool SetBit) const { TailInclusiveBit = SetBit; }
0373 };
0374 
0375 template <typename From> struct simplify_type;
0376 
0377 /// Allow ilist_iterators to convert into pointers to a node automatically when
0378 /// used by the dyn_cast, cast, isa mechanisms...
0379 ///
0380 /// FIXME: remove this, since there is no implicit conversion to NodeTy.
0381 template <class OptionsT, bool IsConst>
0382 struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> {
0383   using iterator = ilist_iterator<OptionsT, false, IsConst>;
0384   using SimpleType = typename iterator::pointer;
0385 
0386   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
0387 };
0388 template <class OptionsT, bool IsConst>
0389 struct simplify_type<const ilist_iterator<OptionsT, false, IsConst>>
0390     : simplify_type<ilist_iterator<OptionsT, false, IsConst>> {};
0391 
0392 // ilist_iterator_w_bits should also be accessible via isa/dyn_cast.
0393 template <class OptionsT, bool IsConst>
0394 struct simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {
0395   using iterator = ilist_iterator_w_bits<OptionsT, false, IsConst>;
0396   using SimpleType = typename iterator::pointer;
0397 
0398   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
0399 };
0400 template <class OptionsT, bool IsConst>
0401 struct simplify_type<const ilist_iterator_w_bits<OptionsT, false, IsConst>>
0402     : simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {};
0403 
0404 } // end namespace llvm
0405 
0406 #endif // LLVM_ADT_ILIST_ITERATOR_H