X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FADT%2Filist_node.h;h=7e5a0e0e5ad81d5867ef6710e65d2649bb84cab4;hb=2b762697564ca1e12e0e974e93ceeb4c3420505c;hp=dae7475ffa01222cf7c05b8990d30fb1b331a461;hpb=a05764c4fb1ff4fc6013dcfd71fc83fb25cdcd27;p=oota-llvm.git diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index dae7475ffa0..7e5a0e0e5ad 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -18,28 +18,104 @@ namespace llvm { template -struct ilist_nextprev_traits; +struct ilist_traits; +template struct ilist_embedded_sentinel_traits; +template struct ilist_half_embedded_sentinel_traits; +/// ilist_half_node - Base class that provides prev services for sentinels. +/// template -struct ilist_traits; +class ilist_half_node { + friend struct ilist_traits; + friend struct ilist_half_embedded_sentinel_traits; + NodeTy *Prev; +protected: + NodeTy *getPrev() { return Prev; } + const NodeTy *getPrev() const { return Prev; } + void setPrev(NodeTy *P) { Prev = P; } + ilist_half_node() : Prev(nullptr) {} +}; + +template +struct ilist_nextprev_traits; + +template class ilist_iterator; /// ilist_node - Base class that provides next/prev services for nodes /// that use ilist_nextprev_traits or ilist_default_traits. /// template -class ilist_node { -private: +class ilist_node : private ilist_half_node { friend struct ilist_nextprev_traits; friend struct ilist_traits; - NodeTy *Prev, *Next; - NodeTy *getPrev() { return Prev; } + friend struct ilist_half_embedded_sentinel_traits; + friend struct ilist_embedded_sentinel_traits; + NodeTy *Next; NodeTy *getNext() { return Next; } - const NodeTy *getPrev() const { return Prev; } const NodeTy *getNext() const { return Next; } - void setPrev(NodeTy *N) { Prev = N; } void setNext(NodeTy *N) { Next = N; } protected: - ilist_node() : Prev(0), Next(0) {} + ilist_node() : Next(nullptr) {} + +public: + ilist_iterator getIterator() { + // FIXME: Stop downcasting to create the iterator (potential UB). + return ilist_iterator(static_cast(this)); + } + ilist_iterator getIterator() const { + // FIXME: Stop downcasting to create the iterator (potential UB). + return ilist_iterator(static_cast(this)); + } +}; + +/// An ilist node that can access its parent list. +/// +/// Requires \c NodeTy to have \a getParent() to find the parent node, and the +/// \c ParentTy to have \a getSublistAccess() to get a reference to the list. +template +class ilist_node_with_parent : public ilist_node { +protected: + ilist_node_with_parent() = default; + +private: + /// Forward to NodeTy::getParent(). + /// + /// Note: do not use the name "getParent()". We want a compile error + /// (instead of recursion) when the subclass fails to implement \a + /// getParent(). + const ParentTy *getNodeParent() const { + return static_cast(this)->getParent(); + } + +public: + /// @name Adjacent Node Accessors + /// @{ + /// \brief Get the previous node, or \c nullptr for the list head. + NodeTy *getPrevNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getPrevNode(*static_cast(this)); + } + /// \brief Get the previous node, or \c nullptr for the list head. + const NodeTy *getPrevNode() const { + return const_cast(this)->getPrevNode(); + } + + /// \brief Get the next node, or \c nullptr for the list tail. + NodeTy *getNextNode() { + // Should be separated to a reused function, but then we couldn't use auto + // (and would need the type of the list). + const auto &List = + getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); + return List.getNextNode(*static_cast(this)); + } + /// \brief Get the next node, or \c nullptr for the list tail. + const NodeTy *getNextNode() const { + return const_cast(this)->getNextNode(); + } + /// @} }; } // End llvm namespace