Author: ericwf Date: Thu Dec 29 14:03:55 2016 New Revision: 290721 URL: http://llvm.org/viewvc/llvm-project?rev=290721&view=rev Log: Fix PR31489 - std::function self-swap segfaults
Modified: libcxx/trunk/include/__functional_03 libcxx/trunk/include/functional libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp Modified: libcxx/trunk/include/__functional_03 URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_03?rev=290721&r1=290720&r2=290721&view=diff ============================================================================== --- libcxx/trunk/include/__functional_03 (original) +++ libcxx/trunk/include/__functional_03 Thu Dec 29 14:03:55 2016 @@ -642,6 +642,8 @@ template<class _Rp> void function<_Rp()>::swap(function& __f) { + if (_VSTD::addressof(__f) == this) + return; if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; @@ -916,6 +918,8 @@ template<class _Rp, class _A0> void function<_Rp(_A0)>::swap(function& __f) { + if (_VSTD::addressof(__f) == this) + return; if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; @@ -1190,6 +1194,8 @@ template<class _Rp, class _A0, class _A1 void function<_Rp(_A0, _A1)>::swap(function& __f) { + if (_VSTD::addressof(__f) == this) + return; if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; @@ -1464,6 +1470,8 @@ template<class _Rp, class _A0, class _A1 void function<_Rp(_A0, _A1, _A2)>::swap(function& __f) { + if (_VSTD::addressof(__f) == this) + return; if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=290721&r1=290720&r2=290721&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Thu Dec 29 14:03:55 2016 @@ -1870,6 +1870,8 @@ template<class _Rp, class ..._ArgTypes> void function<_Rp(_ArgTypes...)>::swap(function& __f) _NOEXCEPT { + if (_VSTD::addressof(__f) == this) + return; if ((void *)__f_ == &__buf_ && (void *)__f.__f_ == &__f.__buf_) { typename aligned_storage<sizeof(__buf_)>::type __tempbuf; Modified: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp?rev=290721&r1=290720&r2=290721&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp Thu Dec 29 14:03:55 2016 @@ -19,92 +19,120 @@ #include "test_macros.h" #include "count_new.hpp" -class A -{ - int data_[10]; +class A { + int data_[10]; + public: - static int count; + static int count; - A() - { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; - } - - A(const A&) {++count;} - - ~A() {--count;} - - int operator()(int i) const - { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; - } + A() { + ++count; + for (int i = 0; i < 10; ++i) + data_[i] = i; + } + + A(const A &) { ++count; } + + ~A() { --count; } + + int operator()(int i) const { + for (int j = 0; j < 10; ++j) + i += data_[j]; + return i; + } }; int A::count = 0; -int g(int) {return 0;} - -int main() -{ - assert(globalMemCounter.checkOutstandingNewEq(0)); - { +int g0() { return 0; } +int g(int) { return 0; } +int g2(int, int) { return 2; } +int g3(int, int, int) { return 3; } + +int main() { + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = A(); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); std::function<int(int)> f2; f2 = f; assert(A::count == 2); assert(globalMemCounter.checkOutstandingNewEq(2)); assert(f2.target<A>()); - assert(f2.target<int(*)(int)>() == 0); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + assert(f2.target<int (*)(int)>() == 0); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = g; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>()); + assert(f.target<int (*)(int)>()); assert(f.target<A>() == 0); std::function<int(int)> f2; f2 = f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>()); + assert(f2.target<int (*)(int)>()); assert(f2.target<A>() == 0); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); assert(f.target<A>() == 0); std::function<int(int)> f2; f2 = f; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>() == 0); + assert(f2.target<int (*)(int)>() == 0); assert(f2.target<A>() == 0); - } + } + { + typedef std::function<int()> Func; + Func f = g0; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)()>() == g0); + } + { + typedef std::function<int(int)> Func; + Func f = g; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int)>() == g); + } + { + typedef std::function<int(int, int)> Func; + Func f = g2; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int, int)>() == g2); + } + { + typedef std::function<int(int, int, int)> Func; + Func f = g3; + Func& fr = (f = f); + assert(&fr == &f); + assert(*f.target<int(*)(int, int, int)>() == g3); + } #if TEST_STD_VER >= 11 - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f = A(); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); + assert(f.target<int (*)(int)>() == 0); std::function<int(int)> f2; f2 = std::move(f); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f2.target<A>()); - assert(f2.target<int(*)(int)>() == 0); + assert(f2.target<int (*)(int)>() == 0); assert(f.target<A>() == 0); - assert(f.target<int(*)(int)>() == 0); - } + assert(f.target<int (*)(int)>() == 0); + } #endif } Modified: libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp?rev=290721&r1=290720&r2=290721&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp Thu Dec 29 14:03:55 2016 @@ -18,46 +18,49 @@ #include "count_new.hpp" -class A -{ - int data_[10]; -public: - static int count; - - explicit A(int j) - { - ++count; - data_[0] = j; - } - - A(const A& a) - { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = a.data_[i]; - } +class A { + int data_[10]; - ~A() {--count;} +public: + static int count; - int operator()(int i) const - { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; - } + explicit A(int j) { + ++count; + data_[0] = j; + } + + A(const A &a) { + ++count; + for (int i = 0; i < 10; ++i) + data_[i] = a.data_[i]; + } + + ~A() { --count; } + + int operator()(int i) const { + for (int j = 0; j < 10; ++j) + i += data_[j]; + return i; + } + + int operator()() const { return -1; } + int operator()(int, int) const { return -2; } + int operator()(int, int, int) const { return -3; } - int id() const {return data_[0];} + int id() const { return data_[0]; } }; int A::count = 0; -int g(int) {return 0;} -int h(int) {return 1;} - -int main() -{ - assert(globalMemCounter.checkOutstandingNewEq(0)); - { +int g0() { return 0; } +int g(int) { return 0; } +int h(int) { return 1; } +int g2(int, int) { return 2; } +int g3(int, int, int) { return 3; } + +int main() { + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = A(2); assert(A::count == 2); @@ -69,52 +72,122 @@ int main() assert(globalMemCounter.checkOutstandingNewEq(2)); assert(f1.target<A>()->id() == 2); assert(f2.target<A>()->id() == 1); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = A(1); std::function<int(int)> f2 = g; assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f1.target<A>()->id() == 1); - assert(*f2.target<int(*)(int)>() == g); + assert(*f2.target<int (*)(int)>() == g); f1.swap(f2); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(*f1.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == g); assert(f2.target<A>()->id() == 1); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = g; std::function<int(int)> f2 = A(1); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(*f1.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == g); assert(f2.target<A>()->id() == 1); f1.swap(f2); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(f1.target<A>()->id() == 1); - assert(*f2.target<int(*)(int)>() == g); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { + assert(*f2.target<int (*)(int)>() == g); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { std::function<int(int)> f1 = g; std::function<int(int)> f2 = h; assert(A::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(*f1.target<int(*)(int)>() == g); - assert(*f2.target<int(*)(int)>() == h); + assert(*f1.target<int (*)(int)>() == g); + assert(*f2.target<int (*)(int)>() == h); f1.swap(f2); assert(A::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(*f1.target<int(*)(int)>() == h); - assert(*f2.target<int(*)(int)>() == g); + assert(*f1.target<int (*)(int)>() == h); + assert(*f2.target<int (*)(int)>() == g); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int)> f1 = A(1); + assert(A::count == 1); + { + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 1); + assert(f1.target<A>()->id() == 1); + } + assert(A::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int()> f1 = g0; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)()>() == g0); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int, int)> f1 = g2; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)(int, int)>() == g2); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int(int, int, int)> f1 = g3; + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(*f1.target<int (*)(int, int, int)>() == g3); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + std::function<int()> f1 = A(1); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 1); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); + { + std::function<int(int, int)> f1 = A(2); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 2); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); + { + std::function<int(int, int, int)> f1 = A(3); + assert(A::count == 1); + DisableAllocationGuard guard; + ((void)guard); + f1.swap(f1); + assert(A::count == 1); + assert(f1.target<A>()->id() == 3); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(A::count == 0); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits