10b57cec5SDimitry Andric //===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_ADT_ILIST_ITERATOR_H
100b57cec5SDimitry Andric #define LLVM_ADT_ILIST_ITERATOR_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h"
130b57cec5SDimitry Andric #include <cassert>
140b57cec5SDimitry Andric #include <cstddef>
150b57cec5SDimitry Andric #include <iterator>
160b57cec5SDimitry Andric #include <type_traits>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace ilist_detail {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric /// Find const-correct node types.
230b57cec5SDimitry Andric template <class OptionsT, bool IsConst> struct IteratorTraits;
240b57cec5SDimitry Andric template <class OptionsT> struct IteratorTraits<OptionsT, false> {
250b57cec5SDimitry Andric   using value_type = typename OptionsT::value_type;
260b57cec5SDimitry Andric   using pointer = typename OptionsT::pointer;
270b57cec5SDimitry Andric   using reference = typename OptionsT::reference;
280b57cec5SDimitry Andric   using node_pointer = ilist_node_impl<OptionsT> *;
290b57cec5SDimitry Andric   using node_reference = ilist_node_impl<OptionsT> &;
300b57cec5SDimitry Andric };
310b57cec5SDimitry Andric template <class OptionsT> struct IteratorTraits<OptionsT, true> {
320b57cec5SDimitry Andric   using value_type = const typename OptionsT::value_type;
330b57cec5SDimitry Andric   using pointer = typename OptionsT::const_pointer;
340b57cec5SDimitry Andric   using reference = typename OptionsT::const_reference;
350b57cec5SDimitry Andric   using node_pointer = const ilist_node_impl<OptionsT> *;
360b57cec5SDimitry Andric   using node_reference = const ilist_node_impl<OptionsT> &;
370b57cec5SDimitry Andric };
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric template <bool IsReverse> struct IteratorHelper;
400b57cec5SDimitry Andric template <> struct IteratorHelper<false> : ilist_detail::NodeAccess {
410b57cec5SDimitry Andric   using Access = ilist_detail::NodeAccess;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   template <class T> static void increment(T *&I) { I = Access::getNext(*I); }
440b57cec5SDimitry Andric   template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); }
450b57cec5SDimitry Andric };
460b57cec5SDimitry Andric template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
470b57cec5SDimitry Andric   using Access = ilist_detail::NodeAccess;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   template <class T> static void increment(T *&I) { I = Access::getPrev(*I); }
500b57cec5SDimitry Andric   template <class T> static void decrement(T *&I) { I = Access::getNext(*I); }
510b57cec5SDimitry Andric };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric } // end namespace ilist_detail
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric /// Iterator for intrusive lists  based on ilist_node.
560b57cec5SDimitry Andric template <class OptionsT, bool IsReverse, bool IsConst>
570b57cec5SDimitry Andric class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
580b57cec5SDimitry Andric   friend ilist_iterator<OptionsT, IsReverse, !IsConst>;
590b57cec5SDimitry Andric   friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
600b57cec5SDimitry Andric   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
630b57cec5SDimitry Andric   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric public:
660b57cec5SDimitry Andric   using value_type = typename Traits::value_type;
670b57cec5SDimitry Andric   using pointer = typename Traits::pointer;
680b57cec5SDimitry Andric   using reference = typename Traits::reference;
690b57cec5SDimitry Andric   using difference_type = ptrdiff_t;
700b57cec5SDimitry Andric   using iterator_category = std::bidirectional_iterator_tag;
710b57cec5SDimitry Andric   using const_pointer = typename OptionsT::const_pointer;
720b57cec5SDimitry Andric   using const_reference = typename OptionsT::const_reference;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric private:
750b57cec5SDimitry Andric   using node_pointer = typename Traits::node_pointer;
760b57cec5SDimitry Andric   using node_reference = typename Traits::node_reference;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   node_pointer NodePtr = nullptr;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric public:
810b57cec5SDimitry Andric   /// Create from an ilist_node.
820b57cec5SDimitry Andric   explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {}
850b57cec5SDimitry Andric   explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {}
860b57cec5SDimitry Andric   ilist_iterator() = default;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // This is templated so that we can allow constructing a const iterator from
890b57cec5SDimitry Andric   // a nonconst iterator...
900b57cec5SDimitry Andric   template <bool RHSIsConst>
915ffd83dbSDimitry Andric   ilist_iterator(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS,
925ffd83dbSDimitry Andric                  std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
930b57cec5SDimitry Andric       : NodePtr(RHS.NodePtr) {}
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // This is templated so that we can allow assigning to a const iterator from
960b57cec5SDimitry Andric   // a nonconst iterator...
970b57cec5SDimitry Andric   template <bool RHSIsConst>
985ffd83dbSDimitry Andric   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator &>
990b57cec5SDimitry Andric   operator=(const ilist_iterator<OptionsT, IsReverse, RHSIsConst> &RHS) {
1000b57cec5SDimitry Andric     NodePtr = RHS.NodePtr;
1010b57cec5SDimitry Andric     return *this;
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// Explicit conversion between forward/reverse iterators.
1050b57cec5SDimitry Andric   ///
1060b57cec5SDimitry Andric   /// Translate between forward and reverse iterators without changing range
1070b57cec5SDimitry Andric   /// boundaries.  The resulting iterator will dereference (and have a handle)
1080b57cec5SDimitry Andric   /// to the previous node, which is somewhat unexpected; but converting the
1090b57cec5SDimitry Andric   /// two endpoints in a range will give the same range in reverse.
1100b57cec5SDimitry Andric   ///
1110b57cec5SDimitry Andric   /// This matches std::reverse_iterator conversions.
1120b57cec5SDimitry Andric   explicit ilist_iterator(
1130b57cec5SDimitry Andric       const ilist_iterator<OptionsT, !IsReverse, IsConst> &RHS)
1140b57cec5SDimitry Andric       : ilist_iterator(++RHS.getReverse()) {}
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   /// Get a reverse iterator to the same node.
1170b57cec5SDimitry Andric   ///
1180b57cec5SDimitry Andric   /// Gives a reverse iterator that will dereference (and have a handle) to the
1190b57cec5SDimitry Andric   /// same node.  Converting the endpoint iterators in a range will give a
1200b57cec5SDimitry Andric   /// different range; for range operations, use the explicit conversions.
1210b57cec5SDimitry Andric   ilist_iterator<OptionsT, !IsReverse, IsConst> getReverse() const {
1220b57cec5SDimitry Andric     if (NodePtr)
1230b57cec5SDimitry Andric       return ilist_iterator<OptionsT, !IsReverse, IsConst>(*NodePtr);
1240b57cec5SDimitry Andric     return ilist_iterator<OptionsT, !IsReverse, IsConst>();
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   /// Const-cast.
1280b57cec5SDimitry Andric   ilist_iterator<OptionsT, IsReverse, false> getNonConst() const {
1290b57cec5SDimitry Andric     if (NodePtr)
1300b57cec5SDimitry Andric       return ilist_iterator<OptionsT, IsReverse, false>(
1310b57cec5SDimitry Andric           const_cast<typename ilist_iterator<OptionsT, IsReverse,
1320b57cec5SDimitry Andric                                              false>::node_reference>(*NodePtr));
1330b57cec5SDimitry Andric     return ilist_iterator<OptionsT, IsReverse, false>();
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Accessors...
1370b57cec5SDimitry Andric   reference operator*() const {
1380b57cec5SDimitry Andric     assert(!NodePtr->isKnownSentinel());
1390b57cec5SDimitry Andric     return *Access::getValuePtr(NodePtr);
1400b57cec5SDimitry Andric   }
1410b57cec5SDimitry Andric   pointer operator->() const { return &operator*(); }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   // Comparison operators
1440b57cec5SDimitry Andric   friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
1450b57cec5SDimitry Andric     return LHS.NodePtr == RHS.NodePtr;
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric   friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
1480b57cec5SDimitry Andric     return LHS.NodePtr != RHS.NodePtr;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Increment and decrement operators...
1520b57cec5SDimitry Andric   ilist_iterator &operator--() {
1530b57cec5SDimitry Andric     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
1540b57cec5SDimitry Andric     return *this;
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric   ilist_iterator &operator++() {
1570b57cec5SDimitry Andric     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
1580b57cec5SDimitry Andric     return *this;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric   ilist_iterator operator--(int) {
1610b57cec5SDimitry Andric     ilist_iterator tmp = *this;
1620b57cec5SDimitry Andric     --*this;
1630b57cec5SDimitry Andric     return tmp;
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric   ilist_iterator operator++(int) {
1660b57cec5SDimitry Andric     ilist_iterator tmp = *this;
1670b57cec5SDimitry Andric     ++*this;
1680b57cec5SDimitry Andric     return tmp;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   /// Get the underlying ilist_node.
1720b57cec5SDimitry Andric   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
1750b57cec5SDimitry Andric   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
1760b57cec5SDimitry Andric };
1770b57cec5SDimitry Andric 
1785f757f3fSDimitry Andric /// Iterator for intrusive lists  based on ilist_node. Much like ilist_iterator,
1795f757f3fSDimitry Andric /// but with the addition of two bits recording whether this position (when in
1805f757f3fSDimitry Andric /// a range) is half or fully open.
1815f757f3fSDimitry Andric template <class OptionsT, bool IsReverse, bool IsConst>
1825f757f3fSDimitry Andric class ilist_iterator_w_bits : ilist_detail::SpecificNodeAccess<OptionsT> {
1835f757f3fSDimitry Andric   friend ilist_iterator_w_bits<OptionsT, IsReverse, !IsConst>;
1845f757f3fSDimitry Andric   friend ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>;
1855f757f3fSDimitry Andric   friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
1865f757f3fSDimitry Andric 
1875f757f3fSDimitry Andric   using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
1885f757f3fSDimitry Andric   using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
1895f757f3fSDimitry Andric 
1905f757f3fSDimitry Andric public:
1915f757f3fSDimitry Andric   using value_type = typename Traits::value_type;
1925f757f3fSDimitry Andric   using pointer = typename Traits::pointer;
1935f757f3fSDimitry Andric   using reference = typename Traits::reference;
1945f757f3fSDimitry Andric   using difference_type = ptrdiff_t;
1955f757f3fSDimitry Andric   using iterator_category = std::bidirectional_iterator_tag;
1965f757f3fSDimitry Andric   using const_pointer = typename OptionsT::const_pointer;
1975f757f3fSDimitry Andric   using const_reference = typename OptionsT::const_reference;
1985f757f3fSDimitry Andric 
1995f757f3fSDimitry Andric private:
2005f757f3fSDimitry Andric   using node_pointer = typename Traits::node_pointer;
2015f757f3fSDimitry Andric   using node_reference = typename Traits::node_reference;
2025f757f3fSDimitry Andric 
2035f757f3fSDimitry Andric   node_pointer NodePtr = nullptr;
2045f757f3fSDimitry Andric 
2055f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
2065f757f3fSDimitry Andric   // (Default: Off) Allow extra position-information flags to be stored
2075f757f3fSDimitry Andric   // in iterators, in aid of removing debug-info intrinsics from LLVM.
2085f757f3fSDimitry Andric 
2095f757f3fSDimitry Andric   /// Is this position intended to contain any debug-info immediately before
2105f757f3fSDimitry Andric   /// the position?
2115f757f3fSDimitry Andric   mutable bool HeadInclusiveBit = false;
2125f757f3fSDimitry Andric   /// Is this position intended to contain any debug-info immediately after
2135f757f3fSDimitry Andric   /// the position?
2145f757f3fSDimitry Andric   mutable bool TailInclusiveBit = false;
2155f757f3fSDimitry Andric #endif
2165f757f3fSDimitry Andric 
2175f757f3fSDimitry Andric public:
2185f757f3fSDimitry Andric   /// Create from an ilist_node.
2195f757f3fSDimitry Andric   explicit ilist_iterator_w_bits(node_reference N) : NodePtr(&N) {}
2205f757f3fSDimitry Andric 
2215f757f3fSDimitry Andric   explicit ilist_iterator_w_bits(pointer NP)
2225f757f3fSDimitry Andric       : NodePtr(Access::getNodePtr(NP)) {}
2235f757f3fSDimitry Andric   explicit ilist_iterator_w_bits(reference NR)
2245f757f3fSDimitry Andric       : NodePtr(Access::getNodePtr(&NR)) {}
2255f757f3fSDimitry Andric   ilist_iterator_w_bits() = default;
2265f757f3fSDimitry Andric 
2275f757f3fSDimitry Andric   // This is templated so that we can allow constructing a const iterator from
2285f757f3fSDimitry Andric   // a nonconst iterator...
2295f757f3fSDimitry Andric   template <bool RHSIsConst>
2305f757f3fSDimitry Andric   ilist_iterator_w_bits(
2315f757f3fSDimitry Andric       const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS,
2325f757f3fSDimitry Andric       std::enable_if_t<IsConst || !RHSIsConst, void *> = nullptr)
2335f757f3fSDimitry Andric       : NodePtr(RHS.NodePtr) {
2345f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
2355f757f3fSDimitry Andric     HeadInclusiveBit = RHS.HeadInclusiveBit;
2365f757f3fSDimitry Andric     TailInclusiveBit = RHS.TailInclusiveBit;
2375f757f3fSDimitry Andric #endif
2385f757f3fSDimitry Andric   }
2395f757f3fSDimitry Andric 
2405f757f3fSDimitry Andric   // This is templated so that we can allow assigning to a const iterator from
2415f757f3fSDimitry Andric   // a nonconst iterator...
2425f757f3fSDimitry Andric   template <bool RHSIsConst>
2435f757f3fSDimitry Andric   std::enable_if_t<IsConst || !RHSIsConst, ilist_iterator_w_bits &>
2445f757f3fSDimitry Andric   operator=(const ilist_iterator_w_bits<OptionsT, IsReverse, RHSIsConst> &RHS) {
2455f757f3fSDimitry Andric     NodePtr = RHS.NodePtr;
2465f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
2475f757f3fSDimitry Andric     HeadInclusiveBit = RHS.HeadInclusiveBit;
2485f757f3fSDimitry Andric     TailInclusiveBit = RHS.TailInclusiveBit;
2495f757f3fSDimitry Andric #endif
2505f757f3fSDimitry Andric     return *this;
2515f757f3fSDimitry Andric   }
2525f757f3fSDimitry Andric 
2535f757f3fSDimitry Andric   /// Explicit conversion between forward/reverse iterators.
2545f757f3fSDimitry Andric   ///
2555f757f3fSDimitry Andric   /// Translate between forward and reverse iterators without changing range
2565f757f3fSDimitry Andric   /// boundaries.  The resulting iterator will dereference (and have a handle)
2575f757f3fSDimitry Andric   /// to the previous node, which is somewhat unexpected; but converting the
2585f757f3fSDimitry Andric   /// two endpoints in a range will give the same range in reverse.
2595f757f3fSDimitry Andric   ///
2605f757f3fSDimitry Andric   /// This matches std::reverse_iterator conversions.
2615f757f3fSDimitry Andric   explicit ilist_iterator_w_bits(
2625f757f3fSDimitry Andric       const ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> &RHS)
2635f757f3fSDimitry Andric       : ilist_iterator_w_bits(++RHS.getReverse()) {}
2645f757f3fSDimitry Andric 
2655f757f3fSDimitry Andric   /// Get a reverse iterator to the same node.
2665f757f3fSDimitry Andric   ///
2675f757f3fSDimitry Andric   /// Gives a reverse iterator that will dereference (and have a handle) to the
2685f757f3fSDimitry Andric   /// same node.  Converting the endpoint iterators in a range will give a
2695f757f3fSDimitry Andric   /// different range; for range operations, use the explicit conversions.
2705f757f3fSDimitry Andric   ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst> getReverse() const {
2715f757f3fSDimitry Andric     if (NodePtr)
2725f757f3fSDimitry Andric       return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>(*NodePtr);
2735f757f3fSDimitry Andric     return ilist_iterator_w_bits<OptionsT, !IsReverse, IsConst>();
2745f757f3fSDimitry Andric   }
2755f757f3fSDimitry Andric 
2765f757f3fSDimitry Andric   /// Const-cast.
2775f757f3fSDimitry Andric   ilist_iterator_w_bits<OptionsT, IsReverse, false> getNonConst() const {
2785f757f3fSDimitry Andric     if (NodePtr) {
2795f757f3fSDimitry Andric       auto New = ilist_iterator_w_bits<OptionsT, IsReverse, false>(
2805f757f3fSDimitry Andric           const_cast<typename ilist_iterator_w_bits<OptionsT, IsReverse,
2815f757f3fSDimitry Andric                                                     false>::node_reference>(
2825f757f3fSDimitry Andric               *NodePtr));
2835f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
2845f757f3fSDimitry Andric       New.HeadInclusiveBit = HeadInclusiveBit;
2855f757f3fSDimitry Andric       New.TailInclusiveBit = TailInclusiveBit;
2865f757f3fSDimitry Andric #endif
2875f757f3fSDimitry Andric       return New;
2885f757f3fSDimitry Andric     }
2895f757f3fSDimitry Andric     return ilist_iterator_w_bits<OptionsT, IsReverse, false>();
2905f757f3fSDimitry Andric   }
2915f757f3fSDimitry Andric 
2925f757f3fSDimitry Andric   // Accessors...
2935f757f3fSDimitry Andric   reference operator*() const {
2945f757f3fSDimitry Andric     assert(!NodePtr->isKnownSentinel());
2955f757f3fSDimitry Andric     return *Access::getValuePtr(NodePtr);
2965f757f3fSDimitry Andric   }
2975f757f3fSDimitry Andric   pointer operator->() const { return &operator*(); }
2985f757f3fSDimitry Andric 
2995f757f3fSDimitry Andric   // Comparison operators
3005f757f3fSDimitry Andric   friend bool operator==(const ilist_iterator_w_bits &LHS,
3015f757f3fSDimitry Andric                          const ilist_iterator_w_bits &RHS) {
3025f757f3fSDimitry Andric     return LHS.NodePtr == RHS.NodePtr;
3035f757f3fSDimitry Andric   }
3045f757f3fSDimitry Andric   friend bool operator!=(const ilist_iterator_w_bits &LHS,
3055f757f3fSDimitry Andric                          const ilist_iterator_w_bits &RHS) {
3065f757f3fSDimitry Andric     return LHS.NodePtr != RHS.NodePtr;
3075f757f3fSDimitry Andric   }
3085f757f3fSDimitry Andric 
3095f757f3fSDimitry Andric   // Increment and decrement operators...
3105f757f3fSDimitry Andric   ilist_iterator_w_bits &operator--() {
3115f757f3fSDimitry Andric     NodePtr = IsReverse ? NodePtr->getNext() : NodePtr->getPrev();
3125f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
3135f757f3fSDimitry Andric     HeadInclusiveBit = false;
3145f757f3fSDimitry Andric     TailInclusiveBit = false;
3155f757f3fSDimitry Andric #endif
3165f757f3fSDimitry Andric     return *this;
3175f757f3fSDimitry Andric   }
3185f757f3fSDimitry Andric   ilist_iterator_w_bits &operator++() {
3195f757f3fSDimitry Andric     NodePtr = IsReverse ? NodePtr->getPrev() : NodePtr->getNext();
3205f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
3215f757f3fSDimitry Andric     HeadInclusiveBit = false;
3225f757f3fSDimitry Andric     TailInclusiveBit = false;
3235f757f3fSDimitry Andric #endif
3245f757f3fSDimitry Andric     return *this;
3255f757f3fSDimitry Andric   }
3265f757f3fSDimitry Andric   ilist_iterator_w_bits operator--(int) {
3275f757f3fSDimitry Andric     ilist_iterator_w_bits tmp = *this;
3285f757f3fSDimitry Andric     --*this;
3295f757f3fSDimitry Andric     return tmp;
3305f757f3fSDimitry Andric   }
3315f757f3fSDimitry Andric   ilist_iterator_w_bits operator++(int) {
3325f757f3fSDimitry Andric     ilist_iterator_w_bits tmp = *this;
3335f757f3fSDimitry Andric     ++*this;
3345f757f3fSDimitry Andric     return tmp;
3355f757f3fSDimitry Andric   }
3365f757f3fSDimitry Andric 
3375f757f3fSDimitry Andric   /// Get the underlying ilist_node.
3385f757f3fSDimitry Andric   node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
3395f757f3fSDimitry Andric 
3405f757f3fSDimitry Andric   /// Check for end.  Only valid if ilist_sentinel_tracking<true>.
3415f757f3fSDimitry Andric   bool isEnd() const { return NodePtr ? NodePtr->isSentinel() : false; }
3425f757f3fSDimitry Andric 
3435f757f3fSDimitry Andric #ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
3445f757f3fSDimitry Andric   bool getHeadBit() const { return HeadInclusiveBit; }
3455f757f3fSDimitry Andric   bool getTailBit() const { return TailInclusiveBit; }
3465f757f3fSDimitry Andric   void setHeadBit(bool SetBit) const { HeadInclusiveBit = SetBit; }
3475f757f3fSDimitry Andric   void setTailBit(bool SetBit) const { TailInclusiveBit = SetBit; }
3485f757f3fSDimitry Andric #else
3495f757f3fSDimitry Andric   // Store and return no information if we're not using this feature.
3505f757f3fSDimitry Andric   bool getHeadBit() const { return false; }
3515f757f3fSDimitry Andric   bool getTailBit() const { return false; }
3525f757f3fSDimitry Andric   void setHeadBit(bool SetBit) const { (void)SetBit; }
3535f757f3fSDimitry Andric   void setTailBit(bool SetBit) const { (void)SetBit; }
3545f757f3fSDimitry Andric #endif
3555f757f3fSDimitry Andric };
3565f757f3fSDimitry Andric 
3570b57cec5SDimitry Andric template <typename From> struct simplify_type;
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric /// Allow ilist_iterators to convert into pointers to a node automatically when
3600b57cec5SDimitry Andric /// used by the dyn_cast, cast, isa mechanisms...
3610b57cec5SDimitry Andric ///
3620b57cec5SDimitry Andric /// FIXME: remove this, since there is no implicit conversion to NodeTy.
3630b57cec5SDimitry Andric template <class OptionsT, bool IsConst>
3640b57cec5SDimitry Andric struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> {
3650b57cec5SDimitry Andric   using iterator = ilist_iterator<OptionsT, false, IsConst>;
3660b57cec5SDimitry Andric   using SimpleType = typename iterator::pointer;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
3690b57cec5SDimitry Andric };
3700b57cec5SDimitry Andric template <class OptionsT, bool IsConst>
3710b57cec5SDimitry Andric struct simplify_type<const ilist_iterator<OptionsT, false, IsConst>>
3720b57cec5SDimitry Andric     : simplify_type<ilist_iterator<OptionsT, false, IsConst>> {};
3730b57cec5SDimitry Andric 
3745f757f3fSDimitry Andric // ilist_iterator_w_bits should also be accessible via isa/dyn_cast.
3755f757f3fSDimitry Andric template <class OptionsT, bool IsConst>
3765f757f3fSDimitry Andric struct simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {
3775f757f3fSDimitry Andric   using iterator = ilist_iterator_w_bits<OptionsT, false, IsConst>;
3785f757f3fSDimitry Andric   using SimpleType = typename iterator::pointer;
3795f757f3fSDimitry Andric 
3805f757f3fSDimitry Andric   static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
3815f757f3fSDimitry Andric };
3825f757f3fSDimitry Andric template <class OptionsT, bool IsConst>
3835f757f3fSDimitry Andric struct simplify_type<const ilist_iterator_w_bits<OptionsT, false, IsConst>>
3845f757f3fSDimitry Andric     : simplify_type<ilist_iterator_w_bits<OptionsT, false, IsConst>> {};
3855f757f3fSDimitry Andric 
3860b57cec5SDimitry Andric } // end namespace llvm
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric #endif // LLVM_ADT_ILIST_ITERATOR_H
389