diff --git a/llvm/include/llvm/ADT/ilist_iterator.h b/llvm/include/llvm/ADT/ilist_iterator.h index d106d0c62215..1a883364421a 100644 --- a/llvm/include/llvm/ADT/ilist_iterator.h +++ b/llvm/include/llvm/ADT/ilist_iterator.h @@ -27,27 +27,28 @@ template <class NodeTy> struct ConstCorrectNodeType<const NodeTy> { typedef const ilist_node<NodeTy> type; }; -template <bool IsReverse = false> struct IteratorHelper { - template <class T> static void increment(T *&I) { - I = ilist_node_access::getNext(*I); - } - template <class T> static void decrement(T *&I) { - I = ilist_node_access::getPrev(*I); - } +template <bool IsReverse> struct IteratorHelper; +template <> struct IteratorHelper<false> : ilist_detail::NodeAccess { + typedef ilist_detail::NodeAccess Access; + template <class T> static void increment(T *&I) { I = Access::getNext(*I); } + template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); } }; -template <> struct IteratorHelper<true> { - template <class T> static void increment(T *&I) { - IteratorHelper<false>::decrement(I); - } - template <class T> static void decrement(T *&I) { - IteratorHelper<false>::increment(I); - } +template <> struct IteratorHelper<true> : ilist_detail::NodeAccess { + typedef ilist_detail::NodeAccess Access; + template <class T> static void increment(T *&I) { I = Access::getPrev(*I); } + template <class T> static void decrement(T *&I) { I = Access::getNext(*I); } }; } // end namespace ilist_detail /// Iterator for intrusive lists based on ilist_node. -template <typename NodeTy, bool IsReverse> class ilist_iterator { +template <typename NodeTy, bool IsReverse> +class ilist_iterator : ilist_detail::SpecificNodeAccess< + typename std::remove_const<NodeTy>::type> { + typedef ilist_detail::SpecificNodeAccess< + typename std::remove_const<NodeTy>::type> + Access; + public: typedef NodeTy value_type; typedef value_type *pointer; @@ -69,10 +70,8 @@ public: /// Create from an ilist_node. explicit ilist_iterator(node_reference N) : NodePtr(&N) {} - explicit ilist_iterator(pointer NP) - : NodePtr(ilist_node_access::getNodePtr(NP)) {} - explicit ilist_iterator(reference NR) - : NodePtr(ilist_node_access::getNodePtr(&NR)) {} + explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {} + explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {} ilist_iterator() : NodePtr(nullptr) {} // This is templated so that we can allow constructing a const iterator from @@ -108,7 +107,7 @@ public: // Accessors... reference operator*() const { assert(!NodePtr->isKnownSentinel()); - return *ilist_node_access::getValuePtr(NodePtr); + return *Access::getValuePtr(NodePtr); } pointer operator->() const { return &operator*(); } diff --git a/llvm/include/llvm/ADT/ilist_node.h b/llvm/include/llvm/ADT/ilist_node.h index a5e2f5ed5b7f..8bcbec2dc8c9 100644 --- a/llvm/include/llvm/ADT/ilist_node.h +++ b/llvm/include/llvm/ADT/ilist_node.h @@ -19,17 +19,20 @@ namespace llvm { +namespace ilist_detail { +struct NodeAccess; +} // end namespace ilist_detail + template<typename NodeTy> struct ilist_traits; -struct ilist_node_access; template <typename NodeTy, bool IsReverse = false> class ilist_iterator; template <typename NodeTy> class ilist_sentinel; /// Templated wrapper class. template <typename NodeTy> class ilist_node : ilist_node_base { friend class ilist_base; - friend struct ilist_node_access; + friend struct ilist_detail::NodeAccess; friend struct ilist_traits<NodeTy>; friend class ilist_iterator<NodeTy, false>; friend class ilist_iterator<NodeTy, true>; @@ -65,13 +68,15 @@ public: using ilist_node_base::isKnownSentinel; }; +namespace ilist_detail { /// An access class for ilist_node private API. /// /// This gives access to the private parts of ilist nodes. Nodes for an ilist /// should friend this class if they inherit privately from ilist_node. /// /// Using this class outside of the ilist implementation is unsupported. -struct ilist_node_access { +struct NodeAccess { +protected: template <typename T> static ilist_node<T> *getNodePtr(T *N) { return N; } template <typename T> static const ilist_node<T> *getNodePtr(const T *N) { return N; @@ -99,6 +104,27 @@ struct ilist_node_access { } }; +template <class T> struct SpecificNodeAccess : NodeAccess { +protected: + typedef T *pointer; + typedef const T *const_pointer; + typedef ilist_node<T> node_type; + + static node_type *getNodePtr(pointer N) { + return NodeAccess::getNodePtr<T>(N); + } + static const ilist_node<T> *getNodePtr(const_pointer N) { + return NodeAccess::getNodePtr<T>(N); + } + static pointer getValuePtr(node_type *N) { + return NodeAccess::getValuePtr<T>(N); + } + static const_pointer getValuePtr(const node_type *N) { + return NodeAccess::getValuePtr<T>(N); + } +}; +} // end namespace ilist_detail + template <typename NodeTy> class ilist_sentinel : public ilist_node<NodeTy> { public: ilist_sentinel() { diff --git a/llvm/include/llvm/ADT/simple_ilist.h b/llvm/include/llvm/ADT/simple_ilist.h index 6db10fb7320b..698cad052631 100644 --- a/llvm/include/llvm/ADT/simple_ilist.h +++ b/llvm/include/llvm/ADT/simple_ilist.h @@ -46,7 +46,8 @@ namespace llvm { /// eraseAndDispose(), and \a clearAndDispose(). These have different names /// because the extra semantic is otherwise non-obvious. They are equivalent /// to calling \a std::for_each() on the range to be discarded. -template <typename T> class simple_ilist : ilist_base, ilist_node_access { +template <typename T> +class simple_ilist : ilist_base, ilist_detail::SpecificNodeAccess<T> { typedef ilist_base list_base_type; ilist_sentinel<T> Sentinel; diff --git a/llvm/unittests/ADT/IListSentinelTest.cpp b/llvm/unittests/ADT/IListSentinelTest.cpp index 533421e85040..55571efc9c25 100644 --- a/llvm/unittests/ADT/IListSentinelTest.cpp +++ b/llvm/unittests/ADT/IListSentinelTest.cpp @@ -16,10 +16,15 @@ namespace { class Node : public ilist_node<Node> {}; +struct LocalAccess : ilist_detail::NodeAccess { + using NodeAccess::getPrev; + using NodeAccess::getNext; +}; + TEST(IListSentinelTest, DefaultConstructor) { ilist_sentinel<Node> S; - EXPECT_EQ(&S, ilist_node_access::getPrev(S)); - EXPECT_EQ(&S, ilist_node_access::getNext(S)); + EXPECT_EQ(&S, LocalAccess::getPrev(S)); + EXPECT_EQ(&S, LocalAccess::getNext(S)); #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS EXPECT_TRUE(S.isKnownSentinel()); #else @@ -29,8 +34,8 @@ TEST(IListSentinelTest, DefaultConstructor) { TEST(IListSentinelTest, NormalNodeIsNotKnownSentinel) { Node N; - EXPECT_EQ(nullptr, ilist_node_access::getPrev(N)); - EXPECT_EQ(nullptr, ilist_node_access::getNext(N)); + EXPECT_EQ(nullptr, LocalAccess::getPrev(N)); + EXPECT_EQ(nullptr, LocalAccess::getNext(N)); EXPECT_FALSE(N.isKnownSentinel()); } diff --git a/llvm/unittests/ADT/IListTest.cpp b/llvm/unittests/ADT/IListTest.cpp index 5fe225b8874b..472d97c365c6 100644 --- a/llvm/unittests/ADT/IListTest.cpp +++ b/llvm/unittests/ADT/IListTest.cpp @@ -218,7 +218,7 @@ TEST(IListTest, addNodeToList) { } struct PrivateNode : private ilist_node<PrivateNode> { - friend struct llvm::ilist_node_access; + friend struct llvm::ilist_detail::NodeAccess; int Value = 0;