From 762c7604e5515a429002431bc4b29dbe0405c7b3 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Wed, 17 Aug 2016 23:47:56 +0000 Subject: [PATCH] ADT: Tidy up ilist_traits static asserts, NFC Change the ilist traits to use decltype instead of sizeof, and add HasObsoleteCustomization so that additions to this list don't need to be added in two places. I suspect this will now work with MSVC, since the trait tested in r278991 seems to work. If for some reason it continues to fail on Windows I'll follow up by adding back the #ifndef _MSC_VER. llvm-svn: 279012 --- include/llvm/ADT/ilist.h | 35 ++++++++++++++++------------------- unittests/ADT/ilistTest.cpp | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 19 deletions(-) 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