summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/__functional_0356
-rw-r--r--libcxx/include/functional15
-rw-r--r--libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/move_reentrant.pass.cpp46
-rw-r--r--libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign_reentrant.pass.cpp46
4 files changed, 134 insertions, 29 deletions
diff --git a/libcxx/include/__functional_03 b/libcxx/include/__functional_03
index 13d8a3d9600..0a3bfbaa3d2 100644
--- a/libcxx/include/__functional_03
+++ b/libcxx/include/__functional_03
@@ -600,7 +600,10 @@ template<class _Rp>
function<_Rp()>&
function<_Rp()>::operator=(const function& __f)
{
- function(__f).swap(*this);
+ if (__f)
+ function(__f).swap(*this);
+ else
+ *this = nullptr;
return *this;
}
@@ -608,11 +611,12 @@ template<class _Rp>
function<_Rp()>&
function<_Rp()>::operator=(nullptr_t)
{
- if (__f_ == (__base*)&__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
+ __base* __t = __f_;
__f_ = 0;
+ if (__t == (__base*)&__buf_)
+ __t->destroy();
+ else if (__t)
+ __t->destroy_deallocate();
return *this;
}
@@ -876,7 +880,10 @@ template<class _Rp, class _A0>
function<_Rp(_A0)>&
function<_Rp(_A0)>::operator=(const function& __f)
{
- function(__f).swap(*this);
+ if (__f)
+ function(__f).swap(*this);
+ else
+ *this = nullptr;
return *this;
}
@@ -884,11 +891,12 @@ template<class _Rp, class _A0>
function<_Rp(_A0)>&
function<_Rp(_A0)>::operator=(nullptr_t)
{
- if (__f_ == (__base*)&__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
+ __base* __t = __f_;
__f_ = 0;
+ if (__t == (__base*)&__buf_)
+ __t->destroy();
+ else if (__t)
+ __t->destroy_deallocate();
return *this;
}
@@ -1152,7 +1160,10 @@ template<class _Rp, class _A0, class _A1>
function<_Rp(_A0, _A1)>&
function<_Rp(_A0, _A1)>::operator=(const function& __f)
{
- function(__f).swap(*this);
+ if (__f)
+ function(__f).swap(*this);
+ else
+ *this = nullptr;
return *this;
}
@@ -1160,11 +1171,12 @@ template<class _Rp, class _A0, class _A1>
function<_Rp(_A0, _A1)>&
function<_Rp(_A0, _A1)>::operator=(nullptr_t)
{
- if (__f_ == (__base*)&__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
+ __base* __t = __f_;
__f_ = 0;
+ if (__t == (__base*)&__buf_)
+ __t->destroy();
+ else if (__t)
+ __t->destroy_deallocate();
return *this;
}
@@ -1428,7 +1440,10 @@ template<class _Rp, class _A0, class _A1, class _A2>
function<_Rp(_A0, _A1, _A2)>&
function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f)
{
- function(__f).swap(*this);
+ if (__f)
+ function(__f).swap(*this);
+ else
+ *this = nullptr;
return *this;
}
@@ -1436,11 +1451,12 @@ template<class _Rp, class _A0, class _A1, class _A2>
function<_Rp(_A0, _A1, _A2)>&
function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t)
{
- if (__f_ == (__base*)&__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
+ __base* __t = __f_;
__f_ = 0;
+ if (__t == (__base*)&__buf_)
+ __t->destroy();
+ else if (__t)
+ __t->destroy_deallocate();
return *this;
}
diff --git a/libcxx/include/functional b/libcxx/include/functional
index e45beb81801..bb0bdf151a0 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -1818,11 +1818,7 @@ template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(function&& __f) _NOEXCEPT
{
- if ((void *)__f_ == &__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
- __f_ = 0;
+ *this = nullptr;
if (__f.__f_ == 0)
__f_ = 0;
else if ((void *)__f.__f_ == &__f.__buf_)
@@ -1842,11 +1838,12 @@ template<class _Rp, class ..._ArgTypes>
function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT
{
- if ((void *)__f_ == &__buf_)
- __f_->destroy();
- else if (__f_)
- __f_->destroy_deallocate();
+ __base* __t = __f_;
__f_ = 0;
+ if ((void *)__t == &__buf_)
+ __t->destroy();
+ else if (__t)
+ __t->destroy_deallocate();
return *this;
}
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/move_reentrant.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/move_reentrant.pass.cpp
new file mode 100644
index 00000000000..0813c48f322
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/move_reentrant.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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(ArgTypes...)>
+
+// function& operator=(function &&);
+
+#include <functional>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A
+{
+ static std::function<void()> global;
+ static bool cancel;
+
+ ~A() {
+ DoNotOptimize(cancel);
+ if (cancel)
+ global = std::function<void()>(nullptr);
+ }
+ void operator()() {}
+};
+
+std::function<void()> A::global;
+bool A::cancel = false;
+
+int main()
+{
+ A::global = A();
+ assert(A::global.target<A>());
+
+ // Check that we don't recurse in A::~A().
+ A::cancel = true;
+ A::global = std::function<void()>(nullptr);
+ assert(!A::global.target<A>());
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign_reentrant.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign_reentrant.pass.cpp
new file mode 100644
index 00000000000..eeb181928ea
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign_reentrant.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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(ArgTypes...)>
+
+// function& operator=(nullptr_t);
+
+#include <functional>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A
+{
+ static std::function<void()> global;
+ static bool cancel;
+
+ ~A() {
+ DoNotOptimize(cancel);
+ if (cancel)
+ global = nullptr;
+ }
+ void operator()() {}
+};
+
+std::function<void()> A::global;
+bool A::cancel = false;
+
+int main()
+{
+ A::global = A();
+ assert(A::global.target<A>());
+
+ // Check that we don't recurse in A::~A().
+ A::cancel = true;
+ A::global = nullptr;
+ assert(!A::global.target<A>());
+}
OpenPOWER on IntegriCloud