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_03 | |
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_03')
-rw-r--r-- | libcxx/include/__functional_03 | 56 |
1 files changed, 36 insertions, 20 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; } |