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