diff options
| author | Volodymyr Sapsai <vsapsai@apple.com> | 2018-04-25 23:38:41 +0000 |
|---|---|---|
| committer | Volodymyr Sapsai <vsapsai@apple.com> | 2018-04-25 23:38:41 +0000 |
| commit | aa208791bb950bd56f85eb200c7ac08df89b5efb (patch) | |
| tree | 4aaa51fba1398c820d0c4d788a2bae4d390254db /libcxx/include/functional | |
| parent | 2c6430fe3c2005a60680b72a52bfb4e81ca841ee (diff) | |
| download | bcm5719-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/include/functional')
| -rw-r--r-- | libcxx/include/functional | 15 |
1 files changed, 6 insertions, 9 deletions
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; } |

