Index: include/__functional_03 =================================================================== --- include/__functional_03 +++ include/__functional_03 @@ -662,6 +662,9 @@ static bool __not_null(_R2 (*__p)()) {return __p;} template _LIBCPP_INLINE_VISIBILITY + static bool __not_null(_R2 (*__p)(...)) {return __p;} + template + _LIBCPP_INLINE_VISIBILITY static bool __not_null(const function<_R2()>& __p) {return __p;} public: typedef _Rp result_type; @@ -944,18 +947,12 @@ template _LIBCPP_INLINE_VISIBILITY static bool __not_null(_R2 (*__p)(_B0)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)()) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)() const) {return __p;} - template + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)() volatile) {return __p;} - template + static bool __not_null(_R2 (*__p)(_B0, ...)) {return __p;} + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)() const volatile) {return __p;} + static bool __not_null(_Ret _Class::*__p) { return __p; } template _LIBCPP_INLINE_VISIBILITY static bool __not_null(const function<_R2(_B0)>& __p) {return __p;} @@ -1240,18 +1237,12 @@ template _LIBCPP_INLINE_VISIBILITY static bool __not_null(_R2 (*__p)(_B0, _B1)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1) const) {return __p;} - template + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1) volatile) {return __p;} - template + static bool __not_null(_R2 (*__p)(_B0, _B1, ...)) {return __p;} + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1) const volatile) {return __p;} + static bool __not_null(_Ret _Class::*__p) { return __p; } template _LIBCPP_INLINE_VISIBILITY static bool __not_null(const function<_R2(_B0, _B1)>& __p) {return __p;} @@ -1535,18 +1526,12 @@ template _LIBCPP_INLINE_VISIBILITY static bool __not_null(_R2 (*__p)(_B0, _B1, _B2)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1, _B2)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1, _B2) const) {return __p;} - template + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1, _B2) volatile) {return __p;} - template + static bool __not_null(_R2 (*__p)(_B0, _B1, _B2, ...)) {return __p;} + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_B1, _B2) const volatile) {return __p;} + static bool __not_null(_Ret _Class::*__p) { return __p; } template _LIBCPP_INLINE_VISIBILITY static bool __not_null(const function<_R2(_B0, _B1, _B2)>& __p) {return __p;} Index: include/__functional_base_03 =================================================================== --- include/__functional_base_03 +++ include/__functional_base_03 @@ -425,6 +425,19 @@ return (__t1.*__f)(); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(...), _T1& __t1) +{ + return (__t1.*__f)(); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -437,6 +450,19 @@ return (__t1.*__f)(__a0); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, ...), _T1& __t1, _A0& __a0) +{ + return (__t1.*__f)(__a0); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -449,6 +475,19 @@ return (__t1.*__f)(__a0, __a1); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, ...), _T1& __t1, _A0& __a0, _A1& __a1) +{ + return (__t1.*__f)(__a0, __a1); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -461,6 +500,20 @@ return (__t1.*__f)(__a0, __a1, __a2); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2, ...), _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) +{ + return (__t1.*__f)(__a0, __a1, __a2); +} + + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -473,6 +526,19 @@ return (__t1.*__f)(); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(...) const, _T1& __t1) +{ + return (__t1.*__f)(); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -485,6 +551,19 @@ return (__t1.*__f)(__a0); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, ...) const, _T1& __t1, _A0& __a0) +{ + return (__t1.*__f)(__a0); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -497,6 +576,19 @@ return (__t1.*__f)(__a0, __a1); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, ...) const, _T1& __t1, _A0& __a0, _A1& __a1) +{ + return (__t1.*__f)(__a0, __a1); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -509,6 +601,19 @@ return (__t1.*__f)(__a0, __a1, __a2); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2, ...) const, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) +{ + return (__t1.*__f)(__a0, __a1, __a2); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -521,6 +626,19 @@ return (__t1.*__f)(); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(...) volatile, _T1& __t1) +{ + return (__t1.*__f)(); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -533,6 +651,19 @@ return (__t1.*__f)(__a0); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, ...) volatile, _T1& __t1, _A0& __a0) +{ + return (__t1.*__f)(__a0); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -545,6 +676,19 @@ return (__t1.*__f)(__a0, __a1); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, ...) volatile, _T1& __t1, _A0& __a0, _A1& __a1) +{ + return (__t1.*__f)(__a0, __a1); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -557,6 +701,19 @@ return (__t1.*__f)(__a0, __a1, __a2); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2, ...) volatile, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) +{ + return (__t1.*__f)(__a0, __a1, __a2); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -569,6 +726,19 @@ return (__t1.*__f)(); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(...) const volatile, _T1& __t1) +{ + return (__t1.*__f)(); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -581,6 +751,19 @@ return (__t1.*__f)(__a0); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, ...) const volatile, _T1& __t1, _A0& __a0) +{ + return (__t1.*__f)(__a0); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -593,6 +776,19 @@ return (__t1.*__f)(__a0, __a1); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, ...) const volatile, _T1& __t1, _A0& __a0, _A1& __a1) +{ + return (__t1.*__f)(__a0, __a1); +} + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -605,6 +801,20 @@ return (__t1.*__f)(__a0, __a1, __a2); } + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + is_base_of<_Tp, typename remove_reference<_T1>::type>::value, + _Rp +>::type +__invoke(_Rp (_Tp::*__f)(_A0, _A1, _A2, ...) const volatile, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) +{ + return (__t1.*__f)(__a0, __a1, __a2); +} + + // second bullet template Index: include/functional =================================================================== --- include/functional +++ include/functional @@ -1446,18 +1446,12 @@ template _LIBCPP_INLINE_VISIBILITY static bool __not_null(_R2 (*__p)(_Ap...)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_Ap...)) {return __p;} - template - _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_Ap...) const) {return __p;} - template + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_Ap...) volatile) {return __p;} - template + static bool __not_null(_R2 (*__p)(_Ap..., ...)) { return __p; } + template _LIBCPP_INLINE_VISIBILITY - static bool __not_null(_R2 (_Cp::*__p)(_Ap...) const volatile) {return __p;} + static bool __not_null(_Ret _Class::*__p) { return __p; } template _LIBCPP_INLINE_VISIBILITY static bool __not_null(const function<_R2(_Ap...)>& __p) {return !!__p;} Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp =================================================================== --- test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp @@ -11,7 +11,7 @@ // class function -// function(nullptr_t); +// function(Fp); #include #include Index: test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_nullptr.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_nullptr.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// class function + +// function(Fp); + +// Ensure that __not_null works for all function types. +// See https://llvm.org/bugs/show_bug.cgi?id=23589 + +#include +#include + +struct A {}; + +#define NULL_CV_TYPE + +#if __cplusplus >= 201103L +#define TEST_CV_MEM_TYPE_RET(Ret, CV) \ + test_mf(); \ + test_mf(); \ + test_mf(); \ + test_mf(); \ + test_mf(); \ + test_mf() +#else +#define TEST_CV_MEM_TYPE_RET(Ret, CV) \ + test_mf(); \ + test_mf() +#endif + +#define TEST_CV_MEM_TYPE(CV) \ + TEST_CV_MEM_TYPE_RET(void, CV); \ + TEST_CV_MEM_TYPE_RET(int, CV) + +#define TEST_CV_TYPE(CV) \ + test0(); \ + test0(); \ + test1(); \ + test1();\ + test2(); \ + test2();\ + test3(); \ + test3();\ + test0(); \ + test0(); \ + test1(); \ + test1();\ + test2(); \ + test2();\ + test3(); \ + test3() + + +template +void test_mf() { + MemFn mf = nullptr; + std::function f = mf; + A a; + try { f(static_cast(a)); assert(false); } + catch (std::bad_function_call&) {} +} + +template +void test0() { + RawFn fn = nullptr; + std::function f = fn; + try { f(); assert(false); } + catch (std::bad_function_call&) {} +} + +template +void test1() { + RawFn fn = nullptr; + std::function f = fn; + int x = 42; + try { f(x); assert(false); } + catch (std::bad_function_call&) {} +} + +template +void test2() { + RawFn fn = nullptr; + std::function f = fn; + int x = 42; + try { f(x, x); assert(false); } + catch (std::bad_function_call&) {} +} + +template +void test3() { + RawFn fn = nullptr; + std::function f = fn; + int x = 42; + try { f(x, x, x); assert(false); } + catch (std::bad_function_call&) {} +} + +int main() { + { + TEST_CV_MEM_TYPE( NULL_CV_TYPE ); + TEST_CV_MEM_TYPE( const ); + TEST_CV_MEM_TYPE( volatile ); + TEST_CV_MEM_TYPE( const volatile ); + } + { + TEST_CV_TYPE( NULL_CV_TYPE ); + TEST_CV_TYPE( const ); + TEST_CV_TYPE( volatile ); + TEST_CV_TYPE( const volatile ); + + TEST_CV_TYPE( & ); + TEST_CV_TYPE( const & ); + TEST_CV_TYPE( volatile & ); + TEST_CV_TYPE( const volatile & ); + } +} \ No newline at end of file