[libcxx] r212070 - 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.

Marshall Clow mclow.lists at gmail.com
Mon Jun 30 14:27:51 PDT 2014


Author: marshall
Date: Mon Jun 30 16:27:51 2014
New Revision: 212070

URL: http://llvm.org/viewvc/llvm-project?rev=212070&view=rev
Log:
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.

Added:
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp
Modified:
    libcxx/trunk/include/__functional_03
    libcxx/trunk/include/functional
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp

Modified: libcxx/trunk/include/__functional_03
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_03?rev=212070&r1=212069&r2=212070&view=diff
==============================================================================
--- libcxx/trunk/include/__functional_03 (original)
+++ libcxx/trunk/include/__functional_03 Mon Jun 30 16:27:51 2014
@@ -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
         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
         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
         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;
 

Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=212070&r1=212069&r2=212070&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Mon Jun 30 16:27:51 2014
@@ -1421,7 +1421,7 @@ class _LIBCPP_TYPE_VIS_ONLY function<_Rp
         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>

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp?rev=212070&r1=212069&r2=212070&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy.pass.cpp Mon Jun 30 16:27:51 2014
@@ -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);
     {

Added: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp?rev=212070&view=auto
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp (added)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/no-variadics.pass.cpp Mon Jun 30 16:27:51 2014
@@ -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);
+}





More information about the cfe-commits mailing list