diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 10ff088dcd6..c77730c99a3 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -83,34 +83,37 @@ template 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 struct HasGetNext { +template class HasGetNext { typedef char Yes[1]; typedef char No[2]; template struct SFINAE {}; template - static Yes &hasGetNext( - SFINAE(make().getNext(&make())))> - * = 0); - template static No &hasGetNext(...); + static Yes &test(U *I, decltype(I->getNext(&make())) * = 0); + template static No &test(...); - static const bool value = sizeof(hasGetNext(nullptr)) == sizeof(Yes); +public: + static const bool value = sizeof(test(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 struct HasCreateSentinel { +template class HasCreateSentinel { typedef char Yes[1]; typedef char No[2]; template struct SFINAE {}; template - static Yes & - hasCreateSentinel(SFINAE().createSentinel())> * = 0); - template static No &hasCreateSentinel(...); + static Yes &test(U *I, decltype(I->createSentinel()) * = 0); + template static No &test(...); +public: + static const bool value = sizeof(test(nullptr)) == sizeof(Yes); +}; + +template struct HasObsoleteCustomization { static const bool value = - sizeof(hasCreateSentinel(nullptr)) == sizeof(Yes); + HasGetNext::value || HasCreateSentinel::value; }; } // end namespace ilist_detail @@ -287,14 +290,8 @@ template > 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::value, - "ilist next and prev links are not customizable!"); - static_assert(!ilist_detail::HasCreateSentinel::value, - "ilist sentinel is not customizable!"); -#endif + static_assert(!ilist_detail::HasObsoleteCustomization::value, + "ilist customization points have changed!"); ilist_sentinel Sentinel; diff --git a/unittests/ADT/ilistTest.cpp b/unittests/ADT/ilistTest.cpp index a8ea63ed464..57cdd584ec1 100644 --- a/unittests/ADT/ilistTest.cpp +++ b/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::value)); + EXPECT_TRUE((ilist_detail::HasObsoleteCustomization::value)); +} + +struct CreateSentinel { + Node *createSentinel(); +}; +TEST(ilistTest, HasCreateSentinel) { + EXPECT_TRUE((ilist_detail::HasCreateSentinel::value)); + EXPECT_TRUE( + (ilist_detail::HasObsoleteCustomization::value)); +} + } // end namespace