Commit ad41558d authored by Owen Anderson's avatar Owen Anderson
Browse files

Revert "Remove code only needed to detect a pre-4.0 API break."

This reverts commit 17a3fbf2
due to build failures in llvm/unittests/ADT/IListTest.cpp
parent 17a3fbf2
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
@@ -92,6 +92,63 @@ struct ilist_traits : public ilist_node_traits<NodeTy> {};
/// Const traits should never be instantiated.
template <typename Ty> struct ilist_traits<const Ty> {};

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>
  static Yes &test(U *I, decltype(I->getNext(&make<NodeT>())) * = nullptr);
  template <class> static No &test(...);

public:
  static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes);
};

/// Type trait to check for a traits class that has a createSentinel member (as
/// a canary for any of the ilist_sentinel_traits API).
template <class TraitsT> struct HasCreateSentinel {
  typedef char Yes[1];
  typedef char No[2];

  template <class U>
  static Yes &test(U *I, decltype(I->createSentinel()) * = nullptr);
  template <class> static No &test(...);

public:
  static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes);
};

/// Type trait to check for a traits class that has a createNode member.
/// Allocation should be managed in a wrapper class, instead of in
/// ilist_traits.
template <class TraitsT, class NodeT> struct HasCreateNode {
  typedef char Yes[1];
  typedef char No[2];
  template <size_t N> struct SFINAE {};

  template <class U>
  static Yes &test(U *I, decltype(I->createNode(make<NodeT>())) * = 0);
  template <class> static No &test(...);

public:
  static const bool value = sizeof(test<TraitsT>(nullptr)) == sizeof(Yes);
};

template <class TraitsT, class NodeT> struct HasObsoleteCustomization {
  static const bool value = HasGetNext<TraitsT, NodeT>::value ||
                            HasCreateSentinel<TraitsT>::value ||
                            HasCreateNode<TraitsT, NodeT>::value;
};

} // end namespace ilist_detail

//===----------------------------------------------------------------------===//
//
/// A wrapper around an intrusive list with callbacks and non-intrusive
@@ -125,6 +182,13 @@ public:
      typename base_list_type::const_reverse_iterator const_reverse_iterator;

private:
  // TODO: Drop this assertion and the transitive type traits anytime after
  // v4.0 is branched (i.e,. keep them for one release to help out-of-tree code
  // update).
  static_assert(
      !ilist_detail::HasObsoleteCustomization<TraitsT, value_type>::value,
      "ilist customization points have changed!");

  static bool op_less(const_reference L, const_reference R) { return L < R; }
  static bool op_equal(const_reference L, const_reference R) { return L == R; }