diff options
author | Marshall Clow <mclow.lists@gmail.com> | 2014-06-30 21:27:51 +0000 |
---|---|---|
committer | Marshall Clow <mclow.lists@gmail.com> | 2014-06-30 21:27:51 +0000 |
commit | 38cae6330b3e41fb4c81f6fbdb98b4c8c5b159a8 (patch) | |
tree | 0ab63ce833c8f17b8036adea441fb78f80345208 | |
parent | af245d115bfab4eb0ca1b969b2aae6f84eb90706 (diff) | |
download | bcm5719-llvm-38cae6330b3e41fb4c81f6fbdb98b4c8c5b159a8.tar.gz bcm5719-llvm-38cae6330b3e41fb4c81f6fbdb98b4c8c5b159a8.zip |
Fix libc++ bug #20039: 'Constructing std::function from empty compatible std::function results in half-empty state' Thanks to Agustin Berge for the report, and for his and Eric Fiselier's work on a fix.
llvm-svn: 212070
4 files changed, 46 insertions, 5 deletions
diff --git a/libcxx/include/__functional_03 b/libcxx/include/__functional_03 index 540268760a6..d8a9f05fa12 100644 --- a/libcxx/include/__functional_03 +++ b/libcxx/include/__functional_03 @@ -651,9 +651,14 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp()> __base* __f_; template <class _Fp> + _LIBCPP_INLINE_VISIBILITY static bool __not_null(const _Fp&) {return true;} template <class _R2> - static bool __not_null(const function<_Rp()>& __p) {return __p;} + _LIBCPP_INLINE_VISIBILITY + static bool __not_null(_R2 (*__p)()) {return __p;} + template <class _R2> + _LIBCPP_INLINE_VISIBILITY + static bool __not_null(const function<_R2()>& __p) {return __p;} public: typedef _Rp result_type; @@ -955,7 +960,7 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0)> static bool __not_null(_R2 (_Cp::*__p)() const volatile) {return __p;} template <class _R2, class _B0> _LIBCPP_INLINE_VISIBILITY - static bool __not_null(const function<_Rp(_B0)>& __p) {return __p;} + static bool __not_null(const function<_R2(_B0)>& __p) {return __p;} public: typedef _Rp result_type; @@ -1257,7 +1262,7 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0, _A1)> static bool __not_null(_R2 (_Cp::*__p)(_B1) const volatile) {return __p;} template <class _R2, class _B0, class _B1> _LIBCPP_INLINE_VISIBILITY - static bool __not_null(const function<_Rp(_B0, _B1)>& __p) {return __p;} + static bool __not_null(const function<_R2(_B0, _B1)>& __p) {return __p;} public: typedef _Rp result_type; @@ -1558,7 +1563,7 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0, _A1, _A2)> static bool __not_null(_R2 (_Cp::*__p)(_B1, _B2) const volatile) {return __p;} template <class _R2, class _B0, class _B1, class _B2> _LIBCPP_INLINE_VISIBILITY - static bool __not_null(const function<_Rp(_B0, _B1, _B2)>& __p) {return __p;} + static bool __not_null(const function<_R2(_B0, _B1, _B2)>& __p) {return __p;} public: typedef _Rp result_type; diff --git a/libcxx/include/functional b/libcxx/include/functional index 38c22f7a7e0..416a9a97f71 100644 --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -1421,7 +1421,7 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_ArgTypes...)> 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<_Rp(_Ap...)>& __p) {return __p;} + static bool __not_null(const function<_R2(_Ap...)>& __p) {return !!__p;} template <class _Fp, bool = !is_same<_Fp, function>::value && __invokable<_Fp&, _ArgTypes...>::value> diff --git a/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp b/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp index 0efb4d9ac25..cf7b96314f7 100644 --- a/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp +++ b/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp @@ -99,6 +99,18 @@ int main() assert(f2.target<int(*)(int)>() == 0); assert(f2.target<A>() == 0); } + { + std::function<int(int)> f; + assert(new_called == 0); + assert(f.target<int(*)(int)>() == 0); + assert(f.target<A>() == 0); + assert(!f); + std::function<long(int)> g = f; + assert(new_called == 0); + assert(g.target<long(*)(int)>() == 0); + assert(g.target<A>() == 0); + assert(!g); + } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES assert(new_called == 0); { diff --git a/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp b/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp new file mode 100644 index 00000000000..7099c45fab8 --- /dev/null +++ b/libcxx/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <functional> + +// class function<R()> + +// template<class F> function(F); + +#define _LIBCPP_HAS_NO_VARIADICS +#include <functional> +#include <cassert> + +int main() +{ + std::function<void()> f(static_cast<void(*)()>(0)); + assert(!f); +} |