forked from OSchip/llvm-project
ADT: Move ilist_node_access to ilist_detail::NodeAccess...
... and make a few ilist-internal API changes, in preparation for changing how ilist_node is templated. The only effect for ilist users should be changing the friend target from llvm::ilist_node_access to llvm::ilist_detail::NodeAccess (which is only necessary when they inherit privately from ilist_node). - Split out SpecificNodeAccess, which has overloads of getNodePtr and getValuePtr that are untemplated. - Use more typedefs to prevent more changes later. - Force inheritance to use *NodeAccess (to emphasize that ilist *users* shouldn't be doing this). There should be no functionality change here. llvm-svn: 281142
This commit is contained in:
parent
41aceac37f
commit
34c4d2abfd
|
@ -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*(); }
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue