summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/function.objects
diff options
context:
space:
mode:
authorVolodymyr Sapsai <vsapsai@apple.com>2018-04-25 23:38:41 +0000
committerVolodymyr Sapsai <vsapsai@apple.com>2018-04-25 23:38:41 +0000
commitaa208791bb950bd56f85eb200c7ac08df89b5efb (patch)
tree4aaa51fba1398c820d0c4d788a2bae4d390254db /libcxx/test/std/utilities/function.objects
parent2c6430fe3c2005a60680b72a52bfb4e81ca841ee (diff)
downloadbcm5719-llvm-aa208791bb950bd56f85eb200c7ac08df89b5efb.tar.gz
bcm5719-llvm-aa208791bb950bd56f85eb200c7ac08df89b5efb.zip
[libcxx] func.wrap.func.con: Unset function before destroying anything
Be defensive against a reentrant std::function::operator=(nullptr_t), in case the held function object has a non-trivial destructor. Destroying the function object in-place can lead to the destructor being called twice. Patch by Duncan P. N. Exon Smith. C++03 support by Volodymyr Sapsai. rdar://problem/32836603 Reviewers: EricWF, mclow.lists Reviewed By: mclow.lists Subscribers: cfe-commits, arphaman Differential Revision: https://reviews.llvm.org/D34331 llvm-svn: 330885
Diffstat (limited to 'libcxx/test/std/utilities/function.objects')
-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
2 files changed, 92 insertions, 0 deletions
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