| // { dg-options "-std=gnu++23 -lstdc++_libbacktrace" } |
| // { dg-do run { target c++23 } } |
| // { dg-require-effective-target stacktrace } |
| |
| #include <stacktrace> |
| #include "testsuite_allocator.h" |
| |
| static_assert( std::is_nothrow_default_constructible_v<std::stacktrace> ); |
| static_assert( std::is_copy_constructible_v<std::stacktrace> ); |
| static_assert( std::is_nothrow_move_constructible_v<std::stacktrace> ); |
| static_assert( std::is_copy_assignable_v<std::stacktrace> ); |
| static_assert( std::is_nothrow_move_assignable_v<std::stacktrace> ); |
| static_assert( std::is_nothrow_swappable_v<std::stacktrace> ); |
| |
| void |
| test_cons() |
| { |
| { |
| using Stacktrace = std::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 ); |
| |
| Stacktrace s6(s4, Alloc{}); |
| VERIFY( s6 == s4 ); |
| |
| Stacktrace s7(std::move(s6), Alloc{}); |
| VERIFY( s7 == s4 ); |
| } |
| |
| { |
| using Alloc = __gnu_test::uneq_allocator<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 ); |
| |
| // TODO test allocator-extended copy/move |
| |
| // TODO test allocator propagation |
| } |
| } |
| |
| |
| void |
| test_assign() |
| { |
| { |
| using Stacktrace = std::stacktrace; |
| |
| Stacktrace s0; |
| s0 = s0; |
| VERIFY( s0.empty() ); |
| s0 = std::move(s0); |
| VERIFY( s0.empty() ); |
| |
| Stacktrace s1 = Stacktrace::current(); |
| VERIFY( s1 != s0 ); |
| s0 = s1; |
| VERIFY( s0 == s1 ); |
| VERIFY( s0.at(0).source_line() == (__LINE__ - 4) ); |
| |
| s1 = Stacktrace::current(); |
| VERIFY( s1 != s0 ); |
| Stacktrace s2 = s0; |
| Stacktrace s3 = s1; |
| s0 = std::move(s1); |
| VERIFY( s0 == s3 ); |
| VERIFY( s1 == s2 ); // ISO C++: valid but unspecified; GCC: swapped. |
| } |
| |
| { |
| using Alloc = __gnu_test::uneq_allocator<std::stacktrace_entry>; |
| using Stacktrace = std::basic_stacktrace<Alloc>; |
| |
| Stacktrace s0; |
| s0 = s0; |
| VERIFY( s0.empty() ); |
| s0 = std::move(s0); |
| VERIFY( s0.empty() ); |
| |
| Stacktrace s1 = Stacktrace::current(); |
| VERIFY( s1 != s0 ); |
| s0 = s1; |
| VERIFY( s0 == s1 ); |
| |
| s1 = Stacktrace::current(Alloc(__LINE__)); |
| VERIFY( s1 != s0 ); |
| s0 = std::move(s1); |
| VERIFY( s0.at(0).source_line() == s0.get_allocator().get_personality() ); |
| VERIFY( s1.empty() ); // ISO C++: valid but unspecified; GCC: empty. |
| |
| Stacktrace s2 = Stacktrace::current(s0.get_allocator()); |
| Stacktrace s3 = s2; |
| s2 = std::move(s0); |
| VERIFY( s2.at(0).source_line() == s2.get_allocator().get_personality() ); |
| VERIFY( s0 == s3 ); // ISO C++: valid but unspecified, GCC: swapped. |
| } |
| } |
| |
| void |
| test_swap() |
| { |
| { |
| using Stacktrace = std::stacktrace; |
| |
| Stacktrace s0; |
| Stacktrace s1 = Stacktrace::current(); |
| swap(s0, s1); |
| VERIFY( s1.empty() ); |
| VERIFY( ! s0.empty() ); |
| } |
| |
| { |
| using Alloc = __gnu_test::uneq_allocator<std::stacktrace_entry>; |
| using Stacktrace = std::basic_stacktrace<Alloc>; |
| |
| Stacktrace s0; |
| Stacktrace s1 = Stacktrace::current(); |
| swap(s0, s1); |
| VERIFY( s1.empty() ); |
| VERIFY( ! s0.empty() ); |
| |
| // TODO test allocator propagation |
| } |
| } |
| |
| void |
| test_pr105031() |
| { |
| // PR libstdc++/105031 |
| // wrong constexpr if statement in operator=(basic_stacktrace&&) |
| using Alloc = __gnu_test::uneq_allocator<std::stacktrace_entry>; |
| std::basic_stacktrace<Alloc> s; |
| s = auto(s); |
| } |
| |
| int main() |
| { |
| test_cons(); |
| test_assign(); |
| test_swap(); |
| test_pr105031(); |
| } |