Skip to content

Commit

Permalink
ADT: Remove the ilist_nextprev_traits customization point
Browse files Browse the repository at this point in the history
No one is using the capability to implement next and prev another way
(since lld stopped doing it in r278468).  Remove the customization point
by moving the API from ilist_nextprev_traits<T> to ilist_node_access.

The old traits class is still useful/necessary API as a target for
friends of node types that inherit privately from ilist_node.
Eventually I plan to either remove it entirely or move the template
parameters to the methods.

(Note: if there's desire to bring back customization of next/prev
pointers in the future (e.g., to pack some bits in there), I think a
traits class like this is an awkward way to accomplish it.  Instead, we
should change ilist<T> to be ilist<ilist_node<T>>, and give an extra
template parameter to ilist_node.)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278532 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
dexonsmith committed Aug 12, 2016
1 parent 69f0407 commit 6394023
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 33 deletions.
92 changes: 68 additions & 24 deletions include/llvm/ADT/ilist.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,64 @@ namespace llvm {
template<typename NodeTy, typename Traits> class iplist;
template<typename NodeTy> class ilist_iterator;

/// ilist_nextprev_traits - A fragment for template traits for intrusive list
/// that provides default next/prev implementations for common operations.
/// An access class for next/prev on ilist_nodes.
///
template<typename NodeTy>
struct ilist_nextprev_traits {
static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); }
static NodeTy *getNext(NodeTy *N) { return N->getNext(); }
static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); }
static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); }

static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); }
static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); }
/// 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.
///
/// It's strongly discouraged to *use* this class outside of ilist
/// implementation.
struct ilist_node_access {
template <typename NodeTy> static NodeTy *getPrev(NodeTy *N) {
return N->getPrev();
}
template <typename NodeTy> static NodeTy *getNext(NodeTy *N) {
return N->getNext();
}
template <typename NodeTy> static const NodeTy *getPrev(const NodeTy *N) {
return N->getPrev();
}
template <typename NodeTy> static const NodeTy *getNext(const NodeTy *N) {
return N->getNext();
}

template <typename NodeTy> static void setPrev(NodeTy *N, NodeTy *Prev) {
N->setPrev(Prev);
}
template <typename NodeTy> static void setNext(NodeTy *N, NodeTy *Next) {
N->setNext(Next);
}
template <typename NodeTy> static void setPrev(NodeTy *N, std::nullptr_t) {
N->setPrev(nullptr);
}
template <typename NodeTy> static void setNext(NodeTy *N, std::nullptr_t) {
N->setNext(nullptr);
}
};

namespace ilist_detail {

template <class T> T &make();

/// Type trait to check for a traits class that has a getNext member (as a
/// canary for any of the ilist_nextprev_traits API).
template <class TraitsT, class NodeT> struct HasGetNext {
typedef char Yes[1];
typedef char No[2];
template <size_t N> struct SFINAE {};

template <class U, class V>
static Yes &hasGetNext(
SFINAE<sizeof(static_cast<NodeT *>(make<U>().getNext(&make<NodeT>())))>
* = 0);
template <class U, class V> static No &hasGetNext(...);

static const bool value =
sizeof(hasGetNext<TraitsT, NodeT>(nullptr)) == sizeof(Yes);
};

} // end namespace ilist_detail

template<typename NodeTy>
struct ilist_traits;

Expand Down Expand Up @@ -93,15 +137,15 @@ struct ilist_sentinel_traits {
if (!Head) {
Head = ilist_traits<NodeTy>::createSentinel();
ilist_traits<NodeTy>::noteHead(Head, Head);
ilist_traits<NodeTy>::setNext(Head, nullptr);
ilist_node_access::setNext(Head, nullptr);
return Head;
}
return ilist_traits<NodeTy>::getPrev(Head);
return ilist_node_access::getPrev(Head);
}

/// noteHead - stash the sentinel into its default location
static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) {
ilist_traits<NodeTy>::setPrev(NewHead, Sentinel);
ilist_node_access::setPrev(NewHead, Sentinel);
}
};

Expand Down Expand Up @@ -187,11 +231,9 @@ struct ilist_node_traits {
/// By inheriting from this, you can easily use default implementations
/// for all common operations.
///
template<typename NodeTy>
struct ilist_default_traits : public ilist_nextprev_traits<NodeTy>,
public ilist_sentinel_traits<NodeTy>,
public ilist_node_traits<NodeTy> {
};
template <typename NodeTy>
struct ilist_default_traits : public ilist_sentinel_traits<NodeTy>,
public ilist_node_traits<NodeTy> {};

// Template traits for intrusive list. By specializing this template class, you
// can change what next/prev fields are used to store the links...
Expand All @@ -218,7 +260,6 @@ template <typename NodeTy>
class ilist_iterator
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef ilist_traits<NodeTy> Traits;
typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
super;

Expand Down Expand Up @@ -279,12 +320,12 @@ class ilist_iterator

// Increment and decrement operators...
ilist_iterator &operator--() {
NodePtr = Traits::getPrev(NodePtr);
NodePtr = ilist_node_access::getPrev(NodePtr);
assert(NodePtr && "--'d off the beginning of an ilist!");
return *this;
}
ilist_iterator &operator++() {
NodePtr = Traits::getNext(NodePtr);
NodePtr = ilist_node_access::getNext(NodePtr);
return *this;
}
ilist_iterator operator--(int) {
Expand Down Expand Up @@ -348,8 +389,11 @@ template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > {
/// and the successor pointer for the sentinel (which always stays at the
/// end of the list) is always null.
///
template<typename NodeTy, typename Traits=ilist_traits<NodeTy> >
class iplist : public Traits {
template <typename NodeTy, typename Traits = ilist_traits<NodeTy>>
class iplist : public Traits, ilist_node_access {
static_assert(!ilist_detail::HasGetNext<Traits, NodeTy>::value,
"ilist next and prev links are not customizable!");

mutable NodeTy *Head;

// Use the prev node pointer of 'head' as the tail pointer. This is really a
Expand Down
10 changes: 3 additions & 7 deletions include/llvm/ADT/ilist_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,13 @@ class ilist_half_node {
ilist_half_node() : Prev(nullptr) {}
};

template<typename NodeTy>
struct ilist_nextprev_traits;

struct ilist_node_access;
template <typename NodeTy> class ilist_iterator;

/// ilist_node - Base class that provides next/prev services for nodes
/// that use ilist_nextprev_traits or ilist_default_traits.
///
/// Base class that provides next/prev services for ilist nodes.
template<typename NodeTy>
class ilist_node : private ilist_half_node<NodeTy> {
friend struct ilist_nextprev_traits<NodeTy>;
friend struct ilist_node_access;
friend struct ilist_traits<NodeTy>;
friend struct ilist_half_embedded_sentinel_traits<NodeTy>;
friend struct ilist_embedded_sentinel_traits<NodeTy>;
Expand Down
3 changes: 1 addition & 2 deletions include/llvm/IR/SymbolTableListTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ template <typename NodeTy> class SymbolTableList;
//
template <typename ValueSubClass>
class SymbolTableListTraits
: public ilist_nextprev_traits<ValueSubClass>,
public SymbolTableListSentinelTraits<ValueSubClass>,
: public SymbolTableListSentinelTraits<ValueSubClass>,
public ilist_node_traits<ValueSubClass> {
typedef SymbolTableList<ValueSubClass> ListTy;
typedef
Expand Down

0 comments on commit 6394023

Please sign in to comment.