diff options
| -rw-r--r-- | llvm/include/llvm/ADT/ilist.h | 35 | ||||
| -rw-r--r-- | llvm/unittests/ADT/ilistTest.cpp | 17 | 
2 files changed, 33 insertions, 19 deletions
diff --git a/llvm/include/llvm/ADT/ilist.h b/llvm/include/llvm/ADT/ilist.h index 10ff088dcd6..c77730c99a3 100644 --- a/llvm/include/llvm/ADT/ilist.h +++ b/llvm/include/llvm/ADT/ilist.h @@ -83,34 +83,37 @@ 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 { +template <class TraitsT, class NodeT> class HasGetNext {    typedef char Yes[1];    typedef char No[2];    template <size_t N> struct SFINAE {};    template <class U> -  static Yes &hasGetNext( -      SFINAE<sizeof(static_cast<NodeT *>(make<U>().getNext(&make<NodeT>())))> -          * = 0); -  template <class U> static No &hasGetNext(...); +  static Yes &test(U *I, decltype(I->getNext(&make<NodeT>())) * = 0); +  template <class> static No &test(...); -  static const bool value = sizeof(hasGetNext<TraitsT>(nullptr)) == sizeof(Yes); +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 { +template <class TraitsT> class HasCreateSentinel {    typedef char Yes[1];    typedef char No[2];    template <size_t N> struct SFINAE {};    template <class U> -  static Yes & -  hasCreateSentinel(SFINAE<sizeof(make<U>().createSentinel())> * = 0); -  template <class U> static No &hasCreateSentinel(...); +  static Yes &test(U *I, decltype(I->createSentinel()) * = 0); +  template <class U> 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 = -      sizeof(hasCreateSentinel<TraitsT>(nullptr)) == sizeof(Yes); +      HasGetNext<TraitsT, NodeT>::value || HasCreateSentinel<TraitsT>::value;  };  } // end namespace ilist_detail @@ -287,14 +290,8 @@ template <typename NodeTy, typename Traits = ilist_traits<NodeTy>>  class iplist : public Traits, ilist_node_access {    // TODO: Drop these assertions anytime after 4.0 is branched (keep them for    // one release to help out-of-tree code update). -#if !defined(_MSC_VER) -  // FIXME: This fails in MSVC, but it's worth keeping around to help -  // non-Windows users root out bugs in their ilist_traits. -  static_assert(!ilist_detail::HasGetNext<Traits, NodeTy>::value, -                "ilist next and prev links are not customizable!"); -  static_assert(!ilist_detail::HasCreateSentinel<Traits>::value, -                "ilist sentinel is not customizable!"); -#endif +  static_assert(!ilist_detail::HasObsoleteCustomization<Traits, NodeTy>::value, +                "ilist customization points have changed!");    ilist_sentinel<NodeTy> Sentinel; diff --git a/llvm/unittests/ADT/ilistTest.cpp b/llvm/unittests/ADT/ilistTest.cpp index a8ea63ed464..57cdd584ec1 100644 --- a/llvm/unittests/ADT/ilistTest.cpp +++ b/llvm/unittests/ADT/ilistTest.cpp @@ -190,4 +190,21 @@ TEST(ilistTest, privateNode) {    L2.remove(&N);  } +struct GetNext { +  Node *getNext(Node *); +}; +TEST(ilistTest, HasGetNextTrait) { +  EXPECT_TRUE((ilist_detail::HasGetNext<GetNext, Node>::value)); +  EXPECT_TRUE((ilist_detail::HasObsoleteCustomization<GetNext, Node>::value)); +} + +struct CreateSentinel { +  Node *createSentinel(); +}; +TEST(ilistTest, HasCreateSentinel) { +  EXPECT_TRUE((ilist_detail::HasCreateSentinel<CreateSentinel>::value)); +  EXPECT_TRUE( +      (ilist_detail::HasObsoleteCustomization<CreateSentinel, Node>::value)); +} +  } // end namespace  | 

