https://gcc.gnu.org/g:fe04901737112abb6b1a71fe645f727384dc986a
commit r15-5761-gfe04901737112abb6b1a71fe645f727384dc986a Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Nov 28 10:24:00 2024 +0000 libstdc++: Fix allocator-extended move ctor for std::basic_stacktrace [PR117822] libstdc++-v3/ChangeLog: PR libstdc++/117822 * include/std/stacktrace (stacktrace(stacktrace&&, const A&)): Fix typo in qualified-id for is_always_equal trait. * testsuite/19_diagnostics/stacktrace/stacktrace.cc: Test allocator-extended constructors and allocator propagation. Diff: --- libstdc++-v3/include/std/stacktrace | 2 +- .../19_diagnostics/stacktrace/stacktrace.cc | 207 ++++++++++++++++++++- 2 files changed, 204 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/include/std/stacktrace b/libstdc++-v3/include/std/stacktrace index 58d0c2a0fc22..2c0f6ba10a91 100644 --- a/libstdc++-v3/include/std/stacktrace +++ b/libstdc++-v3/include/std/stacktrace @@ -295,7 +295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const allocator_type& __alloc) noexcept : _M_alloc(__alloc) { - if constexpr (_Allocator::is_always_equal::value) + if constexpr (_AllocTraits::is_always_equal::value) _M_impl = std::__exchange(__other._M_impl, {}); else if (_M_alloc == __other._M_alloc) _M_impl = std::__exchange(__other._M_impl, {}); diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc index 6bb22eacd92c..ee1a6d221e3a 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/stacktrace.cc @@ -106,12 +106,164 @@ test_cons() VERIFY( s5 != s0 ); VERIFY( s3 == s0 ); - // TODO test allocator-extended copy/move + Stacktrace s6(s5, Alloc{6}); + VERIFY( ! s6.empty() ); + VERIFY( s6.size() != 0 ); + VERIFY( s6.begin() != s6.end() ); + VERIFY( s6 == s5 ); + VERIFY( s5 != s0 ); + VERIFY( s6.get_allocator().get_personality() == 6 ); - // TODO test allocator propagation + Stacktrace s7(std::move(s6), Alloc{7}); + VERIFY( ! s7.empty() ); + VERIFY( s7.size() != 0 ); + VERIFY( s7.begin() != s7.end() ); + VERIFY( s7 == s5 ); + VERIFY( s5 != s0 ); + VERIFY( s7.get_allocator().get_personality() == 7 ); } -} + { + using Alloc = __gnu_test::SimpleAllocator<std::stacktrace_entry>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s0; + VERIFY( s0.empty() ); + VERIFY( s0.size() == 0 ); + VERIFY( s0.begin() == s0.end() ); + + Stacktrace s1(Alloc{}); + VERIFY( s1.empty() ); + VERIFY( s1.size() == 0 ); + VERIFY( s1.begin() == s1.end() ); + + VERIFY( s0 == s1 ); + + Stacktrace s2(s0); + VERIFY( s2 == s0 ); + + const Stacktrace curr = Stacktrace::current(); + + Stacktrace s3(curr); + VERIFY( ! s3.empty() ); + VERIFY( s3.size() != 0 ); + VERIFY( s3.begin() != s3.end() ); + VERIFY( s3 != s0 ); + + Stacktrace s4(s3); + VERIFY( ! s4.empty() ); + VERIFY( s4.size() != 0 ); + VERIFY( s4.begin() != s4.end() ); + VERIFY( s4 == s3 ); + VERIFY( s4 != s0 ); + + Stacktrace s5(std::move(s3)); + VERIFY( ! s5.empty() ); + VERIFY( s5.size() != 0 ); + VERIFY( s5.begin() != s5.end() ); + VERIFY( s5 == s4 ); + VERIFY( s5 != s0 ); + VERIFY( s3 == s0 ); + + Stacktrace s6(s5, Alloc{}); + VERIFY( ! s6.empty() ); + VERIFY( s6.size() != 0 ); + VERIFY( s6.begin() != s6.end() ); + VERIFY( s6 == s5 ); + VERIFY( s5 != s0 ); + + Stacktrace s7(std::move(s6), Alloc{}); + VERIFY( ! s7.empty() ); + VERIFY( s7.size() != 0 ); + VERIFY( s7.begin() != s7.end() ); + VERIFY( s7 == s5 ); + VERIFY( s5 != s0 ); + } + +{ + using Stacktrace = std::pmr::stacktrace; + using Alloc = Stacktrace::allocator_type; + + Stacktrace s0; + VERIFY( s0.empty() ); + VERIFY( s0.size() == 0 ); + VERIFY( s0.begin() == s0.end() ); + + Stacktrace s1(Alloc{}); + VERIFY( s1.empty() ); + VERIFY( s1.size() == 0 ); + VERIFY( s1.begin() == s1.end() ); + + VERIFY( s0 == s1 ); + + Stacktrace s2(s0); + VERIFY( s2 == s0 ); + + const Stacktrace curr = Stacktrace::current(); + + Stacktrace s3(curr); + VERIFY( ! s3.empty() ); + VERIFY( s3.size() != 0 ); + VERIFY( s3.begin() != s3.end() ); + VERIFY( s3 != s0 ); + + Stacktrace s4(s3); + VERIFY( ! s4.empty() ); + VERIFY( s4.size() != 0 ); + VERIFY( s4.begin() != s4.end() ); + VERIFY( s4 == s3 ); + VERIFY( s4 != s0 ); + + Stacktrace s5(std::move(s3)); + VERIFY( ! s5.empty() ); + VERIFY( s5.size() != 0 ); + VERIFY( s5.begin() != s5.end() ); + VERIFY( s5 == s4 ); + VERIFY( s5 != s0 ); + VERIFY( s3 == s0 ); + + __gnu_test::memory_resource mr; + Stacktrace s6(s5, &mr); + VERIFY( ! s6.empty() ); + VERIFY( s6.size() != 0 ); + VERIFY( s6.begin() != s6.end() ); + VERIFY( s6 == s5 ); + VERIFY( s5 != s0 ); + VERIFY( s6.get_allocator() != s5.get_allocator() ); + + Stacktrace s7(std::move(s6), Alloc{}); + VERIFY( ! s7.empty() ); + VERIFY( s7.size() != 0 ); + VERIFY( s7.begin() != s7.end() ); + VERIFY( s7 == s5 ); + VERIFY( s5 != s0 ); + VERIFY( s7.get_allocator() != s6.get_allocator() ); + } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, false>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(s1); + VERIFY( s2.get_allocator() != s1.get_allocator() ); + Stacktrace s3(std::move(s1)); + VERIFY( s3.get_allocator() == s1.get_allocator() ); + } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, true>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(s1); + VERIFY( s2.get_allocator() == s1.get_allocator() ); + Stacktrace s3(std::move(s1)); + VERIFY( s3.get_allocator() == s1.get_allocator() ); + } +} void test_assign() @@ -167,6 +319,32 @@ test_assign() VERIFY( s2.at(0).source_line() == s2.get_allocator().get_personality() ); VERIFY( s0 == s3 ); // ISO C++: valid but unspecified, GCC: swapped. } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, false>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(Alloc{2}); + s2 = s1; + VERIFY( s2.get_allocator() != s1.get_allocator() ); + s1 = std::move(s2); + VERIFY( s1.get_allocator() != s2.get_allocator() ); + } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, true>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(Alloc{2}); + s2 = s1; + VERIFY( s2.get_allocator() == s1.get_allocator() ); + s1 = Stacktrace::current(Alloc{3}); + VERIFY( s1.get_allocator().get_personality() == 3 ); + } } void @@ -191,8 +369,29 @@ test_swap() swap(s0, s1); VERIFY( s1.empty() ); VERIFY( ! s0.empty() ); + } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, false>; + using Stacktrace = std::basic_stacktrace<Alloc>; + + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(Alloc{1}); // Must use equal allocators when not propagating. + swap(s1, s2); + VERIFY( s1.get_allocator() == s2.get_allocator() ); + } + + { + using Alloc + = __gnu_test::propagating_allocator<std::stacktrace_entry, true>; + using Stacktrace = std::basic_stacktrace<Alloc>; - // TODO test allocator propagation + Stacktrace s1 = Stacktrace::current(Alloc{1}); + Stacktrace s2(Alloc{2}); + swap(s1, s2); + VERIFY( s1.get_allocator().get_personality() == 2 ); + VERIFY( s2.get_allocator().get_personality() == 1 ); } }