Index: llvm/include/llvm/ADT/IntrusiveRefCntPtr.h =================================================================== --- llvm/include/llvm/ADT/IntrusiveRefCntPtr.h +++ llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -171,17 +171,20 @@ IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } - template + template ::value, bool> = true> IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.get()) { S.Obj = nullptr; } - template + template ::value, bool> = true> IntrusiveRefCntPtr(std::unique_ptr S) : Obj(S.release()) { retain(); } - template + template ::value, bool> = true> IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.get()) { retain(); } Index: llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp =================================================================== --- llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp +++ llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp @@ -96,4 +96,46 @@ EXPECT_TRUE(Retained); } +TEST(IntrusiveRefCntPtr, ConstructorSFINAE) { + struct X {}; + struct Y : X {}; + struct Z {}; + static_assert(std::is_convertible &&, + IntrusiveRefCntPtr>::value, + "X -> X is okay"); + static_assert(std::is_convertible &, + IntrusiveRefCntPtr>::value, + "X -> X is okay"); + static_assert( + std::is_convertible, IntrusiveRefCntPtr>::value, + "X -> X is okay"); + static_assert(std::is_convertible &&, + IntrusiveRefCntPtr>::value, + "Y -> X is okay"); + static_assert(std::is_convertible &, + IntrusiveRefCntPtr>::value, + "Y -> X is okay"); + static_assert( + std::is_convertible, IntrusiveRefCntPtr>::value, + "Y -> X is okay"); + static_assert(!std::is_convertible &&, + IntrusiveRefCntPtr>::value, + "X -> Y should be rejected with SFINAE"); + static_assert(!std::is_convertible &, + IntrusiveRefCntPtr>::value, + "X -> Y should be rejected with SFINAE"); + static_assert( + !std::is_convertible, IntrusiveRefCntPtr>::value, + "X -> Y should be rejected with SFINAE"); + static_assert(!std::is_convertible &&, + IntrusiveRefCntPtr>::value, + "X -> Z should be rejected with SFINAE"); + static_assert(!std::is_convertible &, + IntrusiveRefCntPtr>::value, + "X -> Z should be rejected with SFINAE"); + static_assert( + !std::is_convertible, IntrusiveRefCntPtr>::value, + "X -> Z should be rejected with SFINAE"); +} + } // end namespace llvm