ADT: Explode include/llvm/ADT/{ilist,ilist_node}.h, NFC

I'm working on a lower-level intrusive list that can be used
stand-alone, and splitting the files up a bit will make the code easier
to organize.  Explode the ilist headers in advance to improve blame
lists in the future.
- Move ilist_node_base from ilist_node.h to ilist_node_base.h.
- Move ilist_base from ilist.h to ilist_base.h.
- Move ilist_iterator from ilist.h to ilist_iterator.h.
- Move ilist_node_access from ilist.h to ilist_node.h to support
  ilist_iterator.
- Update unit tests to #include smaller headers.
- Clang-format the moved things.

I noticed in transit that there is a simplify_type specialization for
ilist_iterator.  Since there is no longer an implicit conversion from
ilist<T>::iterator to T*, this doesn't make sense (effectively it's a
form of implicit conversion).  For now I've added a FIXME.

llvm-svn: 280047
This commit is contained in:
Duncan P. N. Exon Smith 2016-08-30 01:37:58 +00:00
parent 4d22e4fcb9
commit 79185d80dc
7 changed files with 330 additions and 269 deletions

View File

@ -24,6 +24,8 @@
#ifndef LLVM_ADT_ILIST_H
#define LLVM_ADT_ILIST_H
#include "llvm/ADT/ilist_base.h"
#include "llvm/ADT/ilist_iterator.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
@ -35,36 +37,6 @@
namespace llvm {
template<typename NodeTy, typename Traits> class iplist;
template <typename NodeTy, bool IsReverse> class ilist_iterator;
/// 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.
///
/// It's strongly discouraged to *use* this class outside of the ilist
/// implementation.
struct ilist_node_access {
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;
}
template <typename T> static ilist_node<T> *getPrev(ilist_node<T> &N) {
return N.getPrev();
}
template <typename T> static ilist_node<T> *getNext(ilist_node<T> &N) {
return N.getNext();
}
template <typename T>
static const ilist_node<T> *getPrev(const ilist_node<T> &N) {
return N.getPrev();
}
template <typename T>
static const ilist_node<T> *getNext(const ilist_node<T> &N) {
return N.getNext();
}
};
namespace ilist_detail {
@ -139,214 +111,6 @@ struct ilist_traits : public ilist_default_traits<NodeTy> {};
template<typename Ty>
struct ilist_traits<const Ty> : public ilist_traits<Ty> {};
namespace ilist_detail {
template <class NodeTy> struct ConstCorrectNodeType {
typedef ilist_node<NodeTy> type;
};
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 <> 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);
}
};
} // end namespace ilist_detail
//===----------------------------------------------------------------------===//
// Iterator for intrusive list.
//
template <typename NodeTy, bool IsReverse>
class ilist_iterator
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
super;
typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
typedef typename std::add_const<value_type>::type *const_pointer;
typedef typename std::add_const<value_type>::type &const_reference;
typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type;
typedef node_type *node_pointer;
typedef node_type &node_reference;
private:
node_pointer NodePtr;
public:
/// Create from an ilist_node.
explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
explicit ilist_iterator(pointer NP) : NodePtr(NP) {}
explicit ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(nullptr) {}
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
template <class node_ty>
ilist_iterator(
const ilist_iterator<node_ty, IsReverse> &RHS,
typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,
void *>::type = nullptr)
: NodePtr(RHS.getNodePtr()) {}
// This is templated so that we can allow assigning to a const iterator from
// a nonconst iterator...
template <class node_ty>
const ilist_iterator &
operator=(const ilist_iterator<node_ty, IsReverse> &RHS) {
NodePtr = RHS.getNodePtr();
return *this;
}
/// Convert from an iterator to its reverse.
///
/// TODO: Roll this into the implicit constructor once we're sure that no one
/// is relying on the std::reverse_iterator off-by-one semantics.
ilist_iterator<NodeTy, !IsReverse> getReverse() const {
if (NodePtr)
return ilist_iterator<NodeTy, !IsReverse>(*NodePtr);
return ilist_iterator<NodeTy, !IsReverse>();
}
void reset(pointer NP) { NodePtr = NP; }
// Accessors...
reference operator*() const {
assert(!NodePtr->isKnownSentinel());
return static_cast<NodeTy &>(*getNodePtr());
}
pointer operator->() const { return &operator*(); }
// Comparison operators
friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr == RHS.NodePtr;
}
friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr != RHS.NodePtr;
}
// Increment and decrement operators...
ilist_iterator &operator--() {
ilist_detail::IteratorHelper<IsReverse>::decrement(NodePtr);
return *this;
}
ilist_iterator &operator++() {
ilist_detail::IteratorHelper<IsReverse>::increment(NodePtr);
return *this;
}
ilist_iterator operator--(int) {
ilist_iterator tmp = *this;
--*this;
return tmp;
}
ilist_iterator operator++(int) {
ilist_iterator tmp = *this;
++*this;
return tmp;
}
/// Get the underlying ilist_node.
node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
};
// Allow ilist_iterators to convert into pointers to a node automatically when
// used by the dyn_cast, cast, isa mechanisms...
template<typename From> struct simplify_type;
template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > {
typedef NodeTy* SimpleType;
static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};
template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > {
typedef /*const*/ NodeTy* SimpleType;
static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};
/// Implementations of list algorithms using ilist_node_base.
class ilist_base {
public:
static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) {
ilist_node_base &Prev = *Next.getPrev();
N.setNext(&Next);
N.setPrev(&Prev);
Prev.setNext(&N);
Next.setPrev(&N);
}
static void removeImpl(ilist_node_base &N) {
ilist_node_base *Prev = N.getPrev();
ilist_node_base *Next = N.getNext();
Next->setPrev(Prev);
Prev->setNext(Next);
// Not strictly necessary, but helps catch a class of bugs.
N.setPrev(nullptr);
N.setNext(nullptr);
}
static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First,
ilist_node_base &Last) {
assert(&Next != &Last && "Should be checked by callers");
assert(&First != &Last && "Should be checked by callers");
// Position cannot be contained in the range to be transferred.
assert(&Next != &First &&
// Check for the most common mistake.
"Insertion point can't be one of the transferred nodes");
ilist_node_base &Final = *Last.getPrev();
// Detach from old list/position.
First.getPrev()->setNext(&Last);
Last.setPrev(First.getPrev());
// Splice [First, Final] into its new list/position.
ilist_node_base &Prev = *Next.getPrev();
Final.setNext(&Next);
First.setPrev(&Prev);
Prev.setNext(&First);
Next.setPrev(&Final);
}
template <class T>
static void insertBefore(ilist_node<T> &Next, ilist_node<T> &N) {
insertBeforeImpl(Next, N);
}
template <class T> static void remove(ilist_node<T> &N) { removeImpl(N); }
template <class T>
static void transferBefore(ilist_node<T> &Next, ilist_node<T> &First,
ilist_node<T> &Last) {
transferBeforeImpl(Next, First, Last);
}
};
//===----------------------------------------------------------------------===//
//
/// The subset of list functionality that can safely be used on nodes of

View File

@ -0,0 +1,78 @@
//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ILIST_BASE_H
#define LLVM_ADT_ILIST_BASE_H
#include "llvm/ADT/ilist_node_base.h"
#include <cassert>
#include <cstddef>
#include <type_traits>
namespace llvm {
/// Implementations of list algorithms using ilist_node_base.
class ilist_base {
public:
static void insertBeforeImpl(ilist_node_base &Next, ilist_node_base &N) {
ilist_node_base &Prev = *Next.getPrev();
N.setNext(&Next);
N.setPrev(&Prev);
Prev.setNext(&N);
Next.setPrev(&N);
}
static void removeImpl(ilist_node_base &N) {
ilist_node_base *Prev = N.getPrev();
ilist_node_base *Next = N.getNext();
Next->setPrev(Prev);
Prev->setNext(Next);
// Not strictly necessary, but helps catch a class of bugs.
N.setPrev(nullptr);
N.setNext(nullptr);
}
static void transferBeforeImpl(ilist_node_base &Next, ilist_node_base &First,
ilist_node_base &Last) {
assert(&Next != &Last && "Should be checked by callers");
assert(&First != &Last && "Should be checked by callers");
// Position cannot be contained in the range to be transferred.
assert(&Next != &First &&
// Check for the most common mistake.
"Insertion point can't be one of the transferred nodes");
ilist_node_base &Final = *Last.getPrev();
// Detach from old list/position.
First.getPrev()->setNext(&Last);
Last.setPrev(First.getPrev());
// Splice [First, Final] into its new list/position.
ilist_node_base &Prev = *Next.getPrev();
Final.setNext(&Next);
First.setPrev(&Prev);
Prev.setNext(&First);
Next.setPrev(&Final);
}
template <class T> static void insertBefore(T &Next, T &N) {
insertBeforeImpl(Next, N);
}
template <class T> static void remove(T &N) { removeImpl(N); }
template <class T> static void transferBefore(T &Next, T &First, T &Last) {
transferBeforeImpl(Next, First, Last);
}
};
} // end namespace llvm
#endif // LLVM_ADT_ILIST_BASE_H

View File

@ -0,0 +1,172 @@
//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ILIST_ITERATOR_H
#define LLVM_ADT_ILIST_ITERATOR_H
#include "llvm/ADT/ilist_node.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace llvm {
namespace ilist_detail {
template <class NodeTy> struct ConstCorrectNodeType {
typedef ilist_node<NodeTy> type;
};
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 <> 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);
}
};
} // end namespace ilist_detail
/// Iterator for intrusive lists based on ilist_node.
template <typename NodeTy, bool IsReverse>
class ilist_iterator
: public std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
public:
typedef std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t>
super;
typedef typename super::value_type value_type;
typedef typename super::difference_type difference_type;
typedef typename super::pointer pointer;
typedef typename super::reference reference;
typedef typename std::add_const<value_type>::type *const_pointer;
typedef typename std::add_const<value_type>::type &const_reference;
typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type;
typedef node_type *node_pointer;
typedef node_type &node_reference;
private:
node_pointer NodePtr;
public:
/// Create from an ilist_node.
explicit ilist_iterator(node_reference N) : NodePtr(&N) {}
explicit ilist_iterator(pointer NP) : NodePtr(NP) {}
explicit ilist_iterator(reference NR) : NodePtr(&NR) {}
ilist_iterator() : NodePtr(nullptr) {}
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
template <class node_ty>
ilist_iterator(
const ilist_iterator<node_ty, IsReverse> &RHS,
typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,
void *>::type = nullptr)
: NodePtr(RHS.getNodePtr()) {}
// This is templated so that we can allow assigning to a const iterator from
// a nonconst iterator...
template <class node_ty>
const ilist_iterator &
operator=(const ilist_iterator<node_ty, IsReverse> &RHS) {
NodePtr = RHS.getNodePtr();
return *this;
}
/// Convert from an iterator to its reverse.
///
/// TODO: Roll this into the implicit constructor once we're sure that no one
/// is relying on the std::reverse_iterator off-by-one semantics.
ilist_iterator<NodeTy, !IsReverse> getReverse() const {
if (NodePtr)
return ilist_iterator<NodeTy, !IsReverse>(*NodePtr);
return ilist_iterator<NodeTy, !IsReverse>();
}
void reset(pointer NP) { NodePtr = NP; }
// Accessors...
reference operator*() const {
assert(!NodePtr->isKnownSentinel());
return static_cast<NodeTy &>(*getNodePtr());
}
pointer operator->() const { return &operator*(); }
// Comparison operators
friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr == RHS.NodePtr;
}
friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
return LHS.NodePtr != RHS.NodePtr;
}
// Increment and decrement operators...
ilist_iterator &operator--() {
ilist_detail::IteratorHelper<IsReverse>::decrement(NodePtr);
return *this;
}
ilist_iterator &operator++() {
ilist_detail::IteratorHelper<IsReverse>::increment(NodePtr);
return *this;
}
ilist_iterator operator--(int) {
ilist_iterator tmp = *this;
--*this;
return tmp;
}
ilist_iterator operator++(int) {
ilist_iterator tmp = *this;
++*this;
return tmp;
}
/// Get the underlying ilist_node.
node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
};
template <typename From> struct simplify_type;
/// Allow ilist_iterators to convert into pointers to a node automatically when
/// used by the dyn_cast, cast, isa mechanisms...
///
/// FIXME: remove this, since there is no implicit conversion to NodeTy.
template <typename NodeTy> struct simplify_type<ilist_iterator<NodeTy>> {
typedef NodeTy *SimpleType;
static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};
template <typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy>> {
typedef /*const*/ NodeTy *SimpleType;
static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) {
return &*Node;
}
};
} // end namespace llvm
#endif // LLVM_ADT_ILIST_ITERATOR_H

View File

@ -15,41 +15,13 @@
#ifndef LLVM_ADT_ILIST_NODE_H
#define LLVM_ADT_ILIST_NODE_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/ilist_node_base.h"
namespace llvm {
template<typename NodeTy>
struct ilist_traits;
/// Base class for ilist nodes.
class ilist_node_base {
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
#else
ilist_node_base *Prev = nullptr;
#endif
ilist_node_base *Next = nullptr;
public:
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }
ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
bool isKnownSentinel() const { return PrevAndSentinel.getInt(); }
void initializeSentinel() { PrevAndSentinel.setInt(true); }
#else
void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }
ilist_node_base *getPrev() const { return Prev; }
bool isKnownSentinel() const { return false; }
void initializeSentinel() {}
#endif
void setNext(ilist_node_base *Next) { this->Next = Next; }
ilist_node_base *getNext() const { return Next; }
};
struct ilist_node_access;
template <typename NodeTy, bool IsReverse = false> class ilist_iterator;
template <typename NodeTy> class ilist_sentinel;
@ -93,6 +65,34 @@ public:
using ilist_node_base::isKnownSentinel;
};
/// 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 {
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;
}
template <typename T> static ilist_node<T> *getPrev(ilist_node<T> &N) {
return N.getPrev();
}
template <typename T> static ilist_node<T> *getNext(ilist_node<T> &N) {
return N.getNext();
}
template <typename T>
static const ilist_node<T> *getPrev(const ilist_node<T> &N) {
return N.getPrev();
}
template <typename T>
static const ilist_node<T> *getNext(const ilist_node<T> &N) {
return N.getNext();
}
};
template <typename NodeTy> class ilist_sentinel : public ilist_node<NodeTy> {
public:
ilist_sentinel() {

View File

@ -0,0 +1,47 @@
//===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ILIST_NODE_BASE_H
#define LLVM_ADT_ILIST_NODE_BASE_H
#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
/// Base class for ilist nodes.
class ilist_node_base {
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
#else
ilist_node_base *Prev = nullptr;
#endif
ilist_node_base *Next = nullptr;
public:
#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }
ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
bool isKnownSentinel() const { return PrevAndSentinel.getInt(); }
void initializeSentinel() { PrevAndSentinel.setInt(true); }
#else
void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }
ilist_node_base *getPrev() const { return Prev; }
bool isKnownSentinel() const { return false; }
void initializeSentinel() {}
#endif
void setNext(ilist_node_base *Next) { this->Next = Next; }
ilist_node_base *getNext() const { return Next; }
};
} // end namespace llvm
#endif // LLVM_ADT_ILIST_NODE_BASE_H

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_base.h"
#include "gtest/gtest.h"
using namespace llvm;

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/ilist_node_base.h"
#include "gtest/gtest.h"
using namespace llvm;