[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
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: aa208791bb950bd56f85eb200c7ac08df89b5efb
diff --git a/include/functional b/include/functional
index e45beb8..bb0bdf1 100644
--- a/include/functional
+++ b/include/functional
@@ -1818,11 +1818,7 @@
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 @@
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;
}