[libcxx] Fix PR23589: std::function doesn't recognize null pointer to varargs function.
Summary:
This patch fixes __not_null's detection of nullptr by breaking it down into 4 cases.
1. `__not_null(Tp const&)`: Default case. Tp is not null.
2. `__not_null(Tp* __ptr);` Case for pointers to functions.
3. `__not_null(_Ret _Class::* __ptr);` Case for pointers to members.
4. `__not_null(function<Tp> const&);`: Cases for other std::functions.
Reviewers: mclow.lists
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D11111
llvm-svn: 245335
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 0d28f784010b548946fdfa042de4a78e834c8772
diff --git a/include/functional b/include/functional
index 6c57de0..3c9f5a7 100644
--- a/include/functional
+++ b/include/functional
@@ -1327,6 +1327,22 @@
{
};
+template <class _Fp>
+_LIBCPP_INLINE_VISIBILITY
+bool __not_null(_Fp const&) { return true; }
+
+template <class _Fp>
+_LIBCPP_INLINE_VISIBILITY
+bool __not_null(_Fp* __ptr) { return __ptr; }
+
+template <class _Ret, class _Class>
+_LIBCPP_INLINE_VISIBILITY
+bool __not_null(_Ret _Class::*__ptr) { return __ptr; }
+
+template <class _Fp>
+_LIBCPP_INLINE_VISIBILITY
+bool __not_null(function<_Fp> const& __f) { return !!__f; }
+
} // namespace __function
#ifndef _LIBCPP_HAS_NO_VARIADICS
@@ -1468,28 +1484,6 @@
typename aligned_storage<3*sizeof(void*)>::type __buf_;
__base* __f_;
- template <class _Fp>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(const _Fp&) {return true;}
- template <class _R2, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(_R2 (*__p)(_Ap...)) {return __p;}
- template <class _R2, class _Cp, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(_R2 (_Cp::*__p)(_Ap...)) {return __p;}
- template <class _R2, class _Cp, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(_R2 (_Cp::*__p)(_Ap...) const) {return __p;}
- template <class _R2, class _Cp, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(_R2 (_Cp::*__p)(_Ap...) volatile) {return __p;}
- template <class _R2, class _Cp, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(_R2 (_Cp::*__p)(_Ap...) const volatile) {return __p;}
- template <class _R2, class ..._Ap>
- _LIBCPP_INLINE_VISIBILITY
- static bool __not_null(const function<_R2(_Ap...)>& __p) {return !!__p;}
-
template <class _Fp, bool = !is_same<_Fp, function>::value &&
__invokable<_Fp&, _ArgTypes...>::value>
struct __callable;
@@ -1654,7 +1648,7 @@
>::type*)
: __f_(0)
{
- if (__not_null(__f))
+ if (__function::__not_null(__f))
{
typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_ArgTypes...)> _FF;
if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value)
@@ -1681,7 +1675,7 @@
: __f_(0)
{
typedef allocator_traits<_Alloc> __alloc_traits;
- if (__not_null(__f))
+ if (__function::__not_null(__f))
{
typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _FF;
typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;