From 0b8acd772fe9480a854d46974f269e60aa40c88b Mon Sep 17 00:00:00 2001 From: morzhovets Date: Fri, 1 Nov 2024 22:54:25 +0400 Subject: [PATCH] Update libcxx tests --- test/sources/libcxx/MapTests.h | 14 +- test/sources/libcxx/MultiMapTests.h | 14 +- test/sources/libcxx/MultiSetTests.h | 12 + test/sources/libcxx/SetTests.h | 12 + test/sources/libcxx/Support.h | 14 + test/sources/libcxx/UnorderedMapTests.h | 24 + test/sources/libcxx/UnorderedMultiMapTests.h | 24 + test/sources/libcxx/UnorderedSetTests.h | 30 + test/sources/libcxx/VectorTests.h | 32 + .../libcxx/map/map.cons/copy_assign.pass.cpp | 14 +- .../libcxx/map/map.cons/deduct.pass.cpp | 39 + ...cpp => default_recursive.compile.pass.cpp} | 15 +- .../libcxx/map/map.cons/from_range.pass.cpp | 49 ++ .../sources/libcxx/map/map.cons/move.pass.cpp | 6 +- .../map.modifiers/insert_node_type.pass.cpp | 24 + .../map/map.modifiers/insert_range.pass.cpp | 39 + .../sources/libcxx/map/map.ops/count.pass.cpp | 208 ++--- .../multimap/multimap.cons/deduct.pass.cpp | 39 + ...cpp => default_recursive.compile.pass.cpp} | 15 +- .../multimap.cons/from_range.pass.cpp | 45 + .../multimap/multimap.cons/move.pass.cpp | 6 +- .../multimap.modifiers/insert_range.pass.cpp | 40 + .../libcxx/multiset/insert_range.pass.cpp | 35 + .../multiset/multiset.cons/deduct.pass.cpp | 43 +- .../multiset.cons/from_range.pass.cpp | 41 + .../multiset/multiset.cons/move.pass.cpp | 6 +- .../libcxx/set/insert_node_type.pass.cpp | 24 + test/sources/libcxx/set/insert_range.pass.cpp | 35 + .../libcxx/set/set.cons/deduct.pass.cpp | 39 + .../libcxx/set/set.cons/from_range.pass.cpp | 48 ++ .../sources/libcxx/set/set.cons/move.pass.cpp | 6 +- test/sources/libcxx/support/Counter.h | 12 +- test/sources/libcxx/support/Emplaceable.h | 13 +- test/sources/libcxx/support/MoveOnly.h | 66 +- .../sources/libcxx/support/NotConstructible.h | 14 +- test/sources/libcxx/support/allocators.h | 2 +- .../libcxx/support/almost_satisfies_types.h | 445 ++++++++++ .../libcxx/support/container_test_types.h | 41 +- test/sources/libcxx/support/count_new.h | 640 ++++++++++++++ .../support/deduction_guides_sfinae_checks.h | 136 ++- .../libcxx/support/double_move_tracker.h | 47 + .../libcxx/support/exception_safety_helpers.h | 110 +++ .../from_range_associative_containers.h | 314 +++++++ .../libcxx/support/from_range_helpers.h | 121 +++ .../support/from_range_sequence_containers.h | 163 ++++ .../support/from_range_unordered_containers.h | 456 ++++++++++ .../libcxx/support/insert_range_helpers.h | 122 +++ .../libcxx/support/insert_range_maps_sets.h | 422 +++++++++ .../insert_range_sequence_containers.h | 808 ++++++++++++++++++ ...map_allocator_requirement_test_templates.h | 1 + ...set_allocator_requirement_test_templates.h | 1 + test/sources/libcxx/support/test_allocator.h | 38 +- .../sources/libcxx/support/test_comparisons.h | 8 +- test/sources/libcxx/support/test_iterators.h | 503 ++++++++--- .../unord.map/eq.different_hash.pass.cpp | 150 ++++ .../libcxx/unord.map/hash_function.pass.cpp | 32 + test/sources/libcxx/unord.map/key_eq.pass.cpp | 40 + .../unord.map/unord.map.cnstr/deduct.pass.cpp | 75 ++ .../unord.map.cnstr/from_range.pass.cpp | 55 ++ .../insert_iter_iter.pass.cpp | 69 ++ .../insert_node_type.pass.cpp | 24 + .../unord.map.modifiers/insert_range.pass.cpp | 70 +- .../unord.multimap/eq.different_hash.pass.cpp | 148 ++++ .../sources/libcxx/unord.multimap/eq.pass.cpp | 27 +- .../unord.multimap/hash_function.pass.cpp | 37 + .../libcxx/unord.multimap/key_eq.pass.cpp | 50 ++ .../unord.multimap.cnstr/deduct.pass.cpp | 75 ++ .../unord.multimap.cnstr/from_range.pass.cpp | 51 ++ .../insert_iter_iter.pass.cpp | 109 +++ .../insert_range.pass.cpp | 111 +-- .../unord.set/eq.different_hash.pass.cpp | 137 +++ .../unord.set/extra/insert_range_ext.pass.cpp | 28 + .../libcxx/unord.set/hash_function.pass.cpp | 32 + .../unord.set/insert_iter_iter.pass.cpp | 69 ++ .../unord.set/insert_node_type.pass.cpp | 24 + .../libcxx/unord.set/insert_range.pass.cpp | 68 +- test/sources/libcxx/unord.set/key_eq.pass.cpp | 42 + .../unord.set/unord.set.cnstr/deduct.pass.cpp | 79 +- .../unord.set.cnstr/from_range.pass.cpp | 54 ++ test/sources/libcxx/vector/iterators.pass.cpp | 49 +- test/sources/libcxx/vector/types.pass.cpp | 25 +- .../vector.capacity/shrink_to_fit.pass.cpp | 47 +- .../vector.cons/construct_from_range.pass.cpp | 40 + .../vector.cons/construct_iter_iter.pass.cpp | 6 + .../construct_iter_iter_alloc.pass.cpp | 7 + .../libcxx/vector/vector.cons/deduct.pass.cpp | 1 + .../vector/vector.cons/exceptions.pass.cpp | 12 +- .../libcxx/vector/vector.cons/move.pass.cpp | 17 +- .../vector.modifiers/append_range.pass.cpp | 71 ++ .../assert.push_back.invalidation.pass.cpp | 56 ++ .../vector.modifiers/assign_range.pass.cpp | 80 ++ .../destroy_elements.pass.cpp | 68 ++ .../vector.modifiers/erase_iter.pass.cpp | 121 ++- .../vector.modifiers/erase_iter_iter.pass.cpp | 19 + .../insert_iter_iter_iter.pass.cpp | 2 +- .../vector.modifiers/insert_range.pass.cpp | 72 ++ 96 files changed, 7141 insertions(+), 683 deletions(-) rename test/sources/libcxx/map/map.cons/{default_recursive.pass.cpp => default_recursive.compile.pass.cpp} (69%) create mode 100644 test/sources/libcxx/map/map.cons/from_range.pass.cpp create mode 100644 test/sources/libcxx/map/map.modifiers/insert_range.pass.cpp rename test/sources/libcxx/multimap/multimap.cons/{default_recursive.pass.cpp => default_recursive.compile.pass.cpp} (67%) create mode 100644 test/sources/libcxx/multimap/multimap.cons/from_range.pass.cpp create mode 100644 test/sources/libcxx/multimap/multimap.modifiers/insert_range.pass.cpp create mode 100644 test/sources/libcxx/multiset/insert_range.pass.cpp create mode 100644 test/sources/libcxx/multiset/multiset.cons/from_range.pass.cpp create mode 100644 test/sources/libcxx/set/insert_range.pass.cpp create mode 100644 test/sources/libcxx/set/set.cons/from_range.pass.cpp create mode 100644 test/sources/libcxx/support/almost_satisfies_types.h create mode 100644 test/sources/libcxx/support/count_new.h create mode 100644 test/sources/libcxx/support/double_move_tracker.h create mode 100644 test/sources/libcxx/support/exception_safety_helpers.h create mode 100644 test/sources/libcxx/support/from_range_associative_containers.h create mode 100644 test/sources/libcxx/support/from_range_helpers.h create mode 100644 test/sources/libcxx/support/from_range_sequence_containers.h create mode 100644 test/sources/libcxx/support/from_range_unordered_containers.h create mode 100644 test/sources/libcxx/support/insert_range_helpers.h create mode 100644 test/sources/libcxx/support/insert_range_maps_sets.h create mode 100644 test/sources/libcxx/support/insert_range_sequence_containers.h create mode 100644 test/sources/libcxx/unord.map/eq.different_hash.pass.cpp create mode 100644 test/sources/libcxx/unord.map/hash_function.pass.cpp create mode 100644 test/sources/libcxx/unord.map/key_eq.pass.cpp create mode 100644 test/sources/libcxx/unord.map/unord.map.cnstr/from_range.pass.cpp create mode 100644 test/sources/libcxx/unord.map/unord.map.modifiers/insert_iter_iter.pass.cpp create mode 100644 test/sources/libcxx/unord.multimap/eq.different_hash.pass.cpp create mode 100644 test/sources/libcxx/unord.multimap/hash_function.pass.cpp create mode 100644 test/sources/libcxx/unord.multimap/key_eq.pass.cpp create mode 100644 test/sources/libcxx/unord.multimap/unord.multimap.cnstr/from_range.pass.cpp create mode 100644 test/sources/libcxx/unord.multimap/unord.multimap.modifiers/insert_iter_iter.pass.cpp create mode 100644 test/sources/libcxx/unord.set/eq.different_hash.pass.cpp create mode 100644 test/sources/libcxx/unord.set/extra/insert_range_ext.pass.cpp create mode 100644 test/sources/libcxx/unord.set/hash_function.pass.cpp create mode 100644 test/sources/libcxx/unord.set/insert_iter_iter.pass.cpp create mode 100644 test/sources/libcxx/unord.set/key_eq.pass.cpp create mode 100644 test/sources/libcxx/unord.set/unord.set.cnstr/from_range.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.cons/construct_from_range.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.modifiers/append_range.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.modifiers/assert.push_back.invalidation.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.modifiers/assign_range.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.modifiers/destroy_elements.pass.cpp create mode 100644 test/sources/libcxx/vector/vector.modifiers/insert_range.pass.cpp diff --git a/test/sources/libcxx/MapTests.h b/test/sources/libcxx/MapTests.h index 19f386a33..8c99a0107 100644 --- a/test/sources/libcxx/MapTests.h +++ b/test/sources/libcxx/MapTests.h @@ -118,7 +118,7 @@ LIBCXX_TEST_END #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO LIBCXX_TEST_BEGIN(cons_default_recursive) -#include "map/map.cons/default_recursive.pass.cpp" +#include "map/map.cons/default_recursive.compile.pass.cpp" LIBCXX_TEST_END #endif @@ -126,6 +126,12 @@ LIBCXX_TEST_BEGIN(cons_dtor_noexcept) #include "map/map.cons/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cons_from_range) +#include "map/map.cons/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cons_initializer_list) #include "map/map.cons/initializer_list.pass.cpp" LIBCXX_TEST_END @@ -242,6 +248,12 @@ LIBCXX_TEST_BEGIN(modifiers_insert_or_assign) #include "map/map.modifiers/insert_or_assign.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(modifiers_insert_range) +#include "map/map.modifiers/insert_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(modifiers_insert_rv) #include "map/map.modifiers/insert_rv.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/MultiMapTests.h b/test/sources/libcxx/MultiMapTests.h index cebe12c43..b1dad03b8 100644 --- a/test/sources/libcxx/MultiMapTests.h +++ b/test/sources/libcxx/MultiMapTests.h @@ -114,7 +114,7 @@ LIBCXX_TEST_END #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO LIBCXX_TEST_BEGIN(cons_default_recursive) -#include "multimap/multimap.cons/default_recursive.pass.cpp" +#include "multimap/multimap.cons/default_recursive.compile.pass.cpp" LIBCXX_TEST_END #endif @@ -122,6 +122,12 @@ LIBCXX_TEST_BEGIN(cons_dtor_noexcept) #include "multimap/multimap.cons/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cons_from_range) +#include "multimap/multimap.cons/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cons_initializer_list) #include "multimap/multimap.cons/initializer_list.pass.cpp" LIBCXX_TEST_END @@ -234,6 +240,12 @@ LIBCXX_TEST_BEGIN(modifiers_insert_node_type_hint) #include "multimap/multimap.modifiers/insert_node_type_hint.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(modifiers_insert_range) +#include "multimap/multimap.modifiers/insert_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(modifiers_insert_rv) #include "multimap/multimap.modifiers/insert_rv.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/MultiSetTests.h b/test/sources/libcxx/MultiSetTests.h index 00b58799e..1aae02517 100644 --- a/test/sources/libcxx/MultiSetTests.h +++ b/test/sources/libcxx/MultiSetTests.h @@ -108,6 +108,12 @@ LIBCXX_TEST_BEGIN(insert_node_type_hint) #include "multiset/insert_node_type_hint.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(insert_range) +#include "multiset/insert_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(insert_rv) #include "multiset/insert_rv.pass.cpp" LIBCXX_TEST_END @@ -208,6 +214,12 @@ LIBCXX_TEST_BEGIN(cons_dtor_noexcept) #include "multiset/multiset.cons/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cons_from_range) +#include "multiset/multiset.cons/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cons_initializer_list) #include "multiset/multiset.cons/initializer_list.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/SetTests.h b/test/sources/libcxx/SetTests.h index 781d3b5ce..fecb75a3a 100644 --- a/test/sources/libcxx/SetTests.h +++ b/test/sources/libcxx/SetTests.h @@ -116,6 +116,12 @@ LIBCXX_TEST_BEGIN(insert_node_type_hint) #include "set/insert_node_type_hint.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(insert_range) +#include "set/insert_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(insert_rv) #include "set/insert_rv.pass.cpp" LIBCXX_TEST_END @@ -204,6 +210,12 @@ LIBCXX_TEST_BEGIN(cons_dtor_noexcept) #include "set/set.cons/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cons_from_range) +#include "set/set.cons/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cons_initializer_list) #include "set/set.cons/initializer_list.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/Support.h b/test/sources/libcxx/Support.h index 69a49555c..0450a8b0c 100644 --- a/test/sources/libcxx/Support.h +++ b/test/sources/libcxx/Support.h @@ -48,4 +48,18 @@ #include "support/asan_testing.h" #include "support/min_allocator.h" +#if TEST_STD_VER >= 23 +# include "support/insert_range_sequence_containers.h" +# include "support/from_range_sequence_containers.h" +# include "support/insert_range_maps_sets.h" +# include "support/from_range_associative_containers.h" +# include "support/from_range_unordered_containers.h" +#else +namespace libcxx_insert_range_seq {} +namespace libcxx_from_range_seq {} +namespace libcxx_insert_range_maps_sets {} +namespace libcxx_from_range_assoc {} +namespace libcxx_from_range_unord {} +#endif + #define TEST_LIBCPP_ASSERT_FAILURE(expr, mess) try { (void)(expr); assert(false); } catch (...) {} diff --git a/test/sources/libcxx/UnorderedMapTests.h b/test/sources/libcxx/UnorderedMapTests.h index 0a60d75c6..c9ddb4c26 100644 --- a/test/sources/libcxx/UnorderedMapTests.h +++ b/test/sources/libcxx/UnorderedMapTests.h @@ -46,6 +46,10 @@ LIBCXX_TEST_BEGIN(empty) #include "unord.map/empty.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(eq_different_hash) +#include "unord.map/eq.different_hash.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(eq) #include "unord.map/eq.pass.cpp" LIBCXX_TEST_END @@ -82,6 +86,10 @@ LIBCXX_TEST_BEGIN(get_allocator) #include "unord.map/get_allocator.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(hash_function) +#include "unord.map/hash_function.pass.cpp" +LIBCXX_TEST_END + #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO LIBCXX_TEST_BEGIN(incomplete_type) #include "unord.map/incomplete_type.pass.cpp" @@ -96,6 +104,10 @@ LIBCXX_TEST_BEGIN(iterators) #include "unord.map/iterators.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(key_eq) +#include "unord.map/key_eq.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(load_factor) #include "unord.map/load_factor.pass.cpp" LIBCXX_TEST_END @@ -262,6 +274,12 @@ LIBCXX_TEST_BEGIN(cnstr_init) #include "unord.map/unord.map.cnstr/init.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cnstr_from_range) +#include "unord.map/unord.map.cnstr/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cnstr_init_size) #include "unord.map/unord.map.cnstr/init_size.pass.cpp" LIBCXX_TEST_END @@ -414,6 +432,10 @@ LIBCXX_TEST_BEGIN(modifiers_insert_init) #include "unord.map/unord.map.modifiers/insert_init.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(modifiers_insert_iter_iter) +#include "unord.map/unord.map.modifiers/insert_iter_iter.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(modifiers_insert_node_type) #include "unord.map/unord.map.modifiers/insert_node_type.pass.cpp" LIBCXX_TEST_END @@ -426,9 +448,11 @@ LIBCXX_TEST_BEGIN(modifiers_insert_or_assign) #include "unord.map/unord.map.modifiers/insert_or_assign.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 LIBCXX_TEST_BEGIN(modifiers_insert_range) #include "unord.map/unord.map.modifiers/insert_range.pass.cpp" LIBCXX_TEST_END +#endif LIBCXX_TEST_BEGIN(modifiers_insert_rvalue) #include "unord.map/unord.map.modifiers/insert_rvalue.pass.cpp" diff --git a/test/sources/libcxx/UnorderedMultiMapTests.h b/test/sources/libcxx/UnorderedMultiMapTests.h index 39b09f837..c269b9bd7 100644 --- a/test/sources/libcxx/UnorderedMultiMapTests.h +++ b/test/sources/libcxx/UnorderedMultiMapTests.h @@ -26,6 +26,10 @@ LIBCXX_TEST_BEGIN(empty) #include "unord.multimap/empty.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(eq_different_hash) +#include "unord.multimap/eq.different_hash.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(eq) #include "unord.multimap/eq.pass.cpp" LIBCXX_TEST_END @@ -62,6 +66,10 @@ LIBCXX_TEST_BEGIN(get_allocator) #include "unord.multimap/get_allocator.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(hash_function) +#include "unord.multimap/hash_function.pass.cpp" +LIBCXX_TEST_END + #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO LIBCXX_TEST_BEGIN(incomplete) #include "unord.multimap/incomplete.pass.cpp" @@ -76,6 +84,10 @@ LIBCXX_TEST_BEGIN(iterators) #include "unord.multimap/iterators.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(key_eq) +#include "unord.multimap/key_eq.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(max_size) #include "unord.multimap/max_size.pass.cpp" LIBCXX_TEST_END @@ -193,6 +205,12 @@ LIBCXX_TEST_BEGIN(cnstr_dtor_noexcept) #include "unord.multimap/unord.multimap.cnstr/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cnstr_from_range) +#include "unord.multimap/unord.multimap.cnstr/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cnstr_init) #include "unord.multimap/unord.multimap.cnstr/init.pass.cpp" LIBCXX_TEST_END @@ -333,9 +351,15 @@ LIBCXX_TEST_BEGIN(modifiers_insert_init) #include "unord.multimap/unord.multimap.modifiers/insert_init.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(modifiers_insert_iter_iter) +#include "unord.multimap/unord.multimap.modifiers/insert_iter_iter.pass.cpp" +LIBCXX_TEST_END + +#if TEST_STD_VER >= 23 LIBCXX_TEST_BEGIN(modifiers_insert_range) #include "unord.multimap/unord.multimap.modifiers/insert_range.pass.cpp" LIBCXX_TEST_END +#endif LIBCXX_TEST_BEGIN(modifiers_insert_rvalue) #include "unord.multimap/unord.multimap.modifiers/insert_rvalue.pass.cpp" diff --git a/test/sources/libcxx/UnorderedSetTests.h b/test/sources/libcxx/UnorderedSetTests.h index af59cf48d..c6a4a6427 100644 --- a/test/sources/libcxx/UnorderedSetTests.h +++ b/test/sources/libcxx/UnorderedSetTests.h @@ -54,6 +54,10 @@ LIBCXX_TEST_BEGIN(empty) #include "unord.set/empty.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(eq_different_hash) +#include "unord.set/eq.different_hash.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(eq) #include "unord.set/eq.pass.cpp" LIBCXX_TEST_END @@ -110,6 +114,10 @@ LIBCXX_TEST_BEGIN(get_allocator) #include "unord.set/get_allocator.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(hash_function) +#include "unord.set/hash_function.pass.cpp" +LIBCXX_TEST_END + #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO LIBCXX_TEST_BEGIN(incomplete) #include "unord.set/incomplete.pass.cpp" @@ -136,6 +144,10 @@ LIBCXX_TEST_BEGIN(insert_init) #include "unord.set/insert_init.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(insert_iter_iter) +#include "unord.set/insert_iter_iter.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(insert_node_type) #include "unord.set/insert_node_type.pass.cpp" LIBCXX_TEST_END @@ -144,9 +156,11 @@ LIBCXX_TEST_BEGIN(insert_node_type_hint) #include "unord.set/insert_node_type_hint.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 LIBCXX_TEST_BEGIN(insert_range) #include "unord.set/insert_range.pass.cpp" LIBCXX_TEST_END +#endif LIBCXX_TEST_BEGIN(insert_rvalue) #include "unord.set/insert_rvalue.pass.cpp" @@ -160,6 +174,10 @@ LIBCXX_TEST_BEGIN(iterators) #include "unord.set/iterators.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(key_eq) +#include "unord.set/key_eq.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(load_factor) #include "unord.set/load_factor.pass.cpp" LIBCXX_TEST_END @@ -212,6 +230,12 @@ LIBCXX_TEST_BEGIN(common_iterator_difference_type) #include "unord.set/common/iterator_difference_type.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(extra_insert_range_ext) +#include "unord.set/extra/insert_range_ext.pass.cpp" +LIBCXX_TEST_END +#endif + #ifdef LIBCXX_TEST_FAILURE LIBCXX_TEST_BEGIN(spec_assert_bucket) @@ -304,6 +328,12 @@ LIBCXX_TEST_BEGIN(cnstr_dtor_noexcept) #include "unord.set/unord.set.cnstr/dtor_noexcept.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cnstr_from_range) +#include "unord.set/unord.set.cnstr/from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cnstr_init) #include "unord.set/unord.set.cnstr/init.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/VectorTests.h b/test/sources/libcxx/VectorTests.h index 40ba6ec75..18ca5f9ab 100644 --- a/test/sources/libcxx/VectorTests.h +++ b/test/sources/libcxx/VectorTests.h @@ -180,6 +180,12 @@ LIBCXX_TEST_BEGIN(cons_construct_default) #include "vector/vector.cons/construct_default.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(cons_construct_from_range) +#include "vector/vector.cons/construct_from_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(cons_construct_iter_iter) #include "vector/vector.cons/construct_iter_iter.pass.cpp" LIBCXX_TEST_END @@ -280,10 +286,30 @@ LIBCXX_TEST_BEGIN(erasure_erase_if) #include "vector/vector.erasure/erase_if.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(modifiers_append_range) +#include "vector/vector.modifiers/append_range.pass.cpp" +LIBCXX_TEST_END +#endif + +LIBCXX_TEST_BEGIN(modifiers_assert_push_back_invalidation) +#include "vector/vector.modifiers/assert.push_back.invalidation.pass.cpp" +LIBCXX_TEST_END + +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(modifiers_assign_range) +#include "vector/vector.modifiers/assign_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(modifiers_clear) #include "vector/vector.modifiers/clear.pass.cpp" LIBCXX_TEST_END +LIBCXX_TEST_BEGIN(modifiers_destroy_elements) +#include "vector/vector.modifiers/destroy_elements.pass.cpp" +LIBCXX_TEST_END + LIBCXX_TEST_BEGIN(modifiers_emplace) #include "vector/vector.modifiers/emplace.pass.cpp" LIBCXX_TEST_END @@ -324,6 +350,12 @@ LIBCXX_TEST_BEGIN(modifiers_insert_iter_size_value) #include "vector/vector.modifiers/insert_iter_size_value.pass.cpp" LIBCXX_TEST_END +#if TEST_STD_VER >= 23 +LIBCXX_TEST_BEGIN(modifiers_insert_range) +#include "vector/vector.modifiers/insert_range.pass.cpp" +LIBCXX_TEST_END +#endif + LIBCXX_TEST_BEGIN(modifiers_pop_back) #include "vector/vector.modifiers/pop_back.pass.cpp" LIBCXX_TEST_END diff --git a/test/sources/libcxx/map/map.cons/copy_assign.pass.cpp b/test/sources/libcxx/map/map.cons/copy_assign.pass.cpp index 84f7c29f3..48bd389f4 100644 --- a/test/sources/libcxx/map/map.cons/copy_assign.pass.cpp +++ b/test/sources/libcxx/map/map.cons/copy_assign.pass.cpp @@ -17,8 +17,8 @@ // map& operator=(const map& m); #if TEST_STD_VER >= 11 -momo::stdish::vector ca_allocs; -momo::stdish::vector ca_deallocs; +std::vector ca_allocs; +std::vector ca_deallocs; template class counting_allocatorT { @@ -67,7 +67,7 @@ class counting_allocatorF { }; bool balanced_allocs() { - momo::stdish::vector temp1, temp2; + std::vector temp1, temp2; //std::printf("Allocations = %zu, deallocations = %zu\n", ca_allocs.size(), // ca_deallocs.size()); @@ -77,10 +77,10 @@ bool balanced_allocs() { temp1 = ca_allocs; std::sort(temp1.begin(), temp1.end()); temp2.clear(); - std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter>(temp2)); + std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter>(temp2)); //std::printf("There were %zu different allocators\n", temp2.size()); - for (momo::stdish::vector::const_iterator it = temp2.begin(); it != temp2.end(); ++it ) { + for (std::vector::const_iterator it = temp2.begin(); it != temp2.end(); ++it ) { std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it); std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it); //std::printf("%d: %td vs %td\n", *it, allocs, deallocs); @@ -91,10 +91,10 @@ bool balanced_allocs() { temp1 = ca_allocs; std::sort(temp1.begin(), temp1.end()); temp2.clear(); - std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter>(temp2)); + std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter>(temp2)); //std::printf("There were %zu different (de)allocators\n", temp2.size()); - for (momo::stdish::vector::const_iterator it = ca_deallocs.begin(); it != ca_deallocs.end(); ++it ) { + for (std::vector::const_iterator it = ca_deallocs.begin(); it != ca_deallocs.end(); ++it ) { std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it); std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it); //std::printf("%d: %td vs %td\n", *it, allocs, deallocs); diff --git a/test/sources/libcxx/map/map.cons/deduct.pass.cpp b/test/sources/libcxx/map/map.cons/deduct.pass.cpp index 5fea49f2d..0348fcd5c 100644 --- a/test/sources/libcxx/map/map.cons/deduct.pass.cpp +++ b/test/sources/libcxx/map/map.cons/deduct.pass.cpp @@ -28,6 +28,15 @@ // template // map(initializer_list, Allocator) // -> map, Allocator>; +// +// template, +// class Allocator = allocator>> +// map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) +// -> map, range-mapped-type, Compare, Allocator>; // C++23 +// +// template +// map(from_range_t, R&&, Allocator) +// -> map, range-mapped-type, less>, Allocator>; // C++23 using P = std::pair; using PC = std::pair; @@ -158,7 +167,37 @@ int main(int, char**) #endif } +#if TEST_STD_VER >= 23 + { + using Range = std::array; + using Comp = std::greater; + using DefaultComp = std::less; + using Alloc = test_allocator; + + { // (from_range, range) + momo::stdish::map c(std::from_range, Range()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp) + momo::stdish::map c(std::from_range, Range(), Comp()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp, alloc) + momo::stdish::map c(std::from_range, Range(), Comp(), Alloc()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, alloc) + momo::stdish::map c(std::from_range, Range(), Alloc()); + static_assert(std::is_same_v>); + } + } +#endif + #if MOMO_VERSION_MAJOR > 3 + //AssociativeContainerDeductionGuidesSfinaeAway>(); AssociativeContainerDeductionGuidesSfinaeAway>(); #endif diff --git a/test/sources/libcxx/map/map.cons/default_recursive.pass.cpp b/test/sources/libcxx/map/map.cons/default_recursive.compile.pass.cpp similarity index 69% rename from test/sources/libcxx/map/map.cons/default_recursive.pass.cpp rename to test/sources/libcxx/map/map.cons/default_recursive.compile.pass.cpp index af2b90502..e0118bd39 100644 --- a/test/sources/libcxx/map/map.cons/default_recursive.pass.cpp +++ b/test/sources/libcxx/map/map.cons/default_recursive.compile.pass.cpp @@ -16,15 +16,14 @@ // map(); -struct X -{ - std::map m; - std::map::iterator i; - std::map::const_iterator ci; +struct X { + std::map m; + std::map::iterator i; + std::map::const_iterator ci; #if TEST_STD_VER <= 17 - // These reverse_iterator specializations require X to be complete in C++20. - std::map::reverse_iterator ri; - std::map::const_reverse_iterator cri; + // These reverse_iterator specializations require X to be complete in C++20. + std::map::reverse_iterator ri; + std::map::const_reverse_iterator cri; #endif // TEST_STD_VER <= 17 }; diff --git a/test/sources/libcxx/map/map.cons/from_range.pass.cpp b/test/sources/libcxx/map/map.cons/from_range.pass.cpp new file mode 100644 index 000000000..42141b4a3 --- /dev/null +++ b/test/sources/libcxx/map/map.cons/from_range.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template R> +// map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 +// +// template R> +// map(from_range_t, R&& rg, const Allocator& a)) +// : map(from_range, std::forward(rg), Compare(), a) { } // C++23 + +void test_duplicates() { + using T = std::pair; + + std::array input = { + T{1, 'a'}, T{2, 'a'}, T{3, 'a'}, T{3, 'b'}, T{3, 'c'}, T{2, 'b'}, T{4, 'a'} + }; + std::array expected = { + T{1, 'a'}, T{2, 'a'}, T{3, 'a'}, T{4, 'a'} + }; + auto c = std::map(std::from_range, input); + assert(std::ranges::is_permutation(expected, c)); +} + +int main(int, char**) { + using T = std::pair; + for_all_iterators_and_allocators([]() { + test_associative_map, Alloc>(); + }); + test_associative_map_move_only(); + test_duplicates(); + + static_assert(test_map_constraints()); + + test_map_exception_safety_throwing_copy(); + test_map_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/map/map.cons/move.pass.cpp b/test/sources/libcxx/map/map.cons/move.pass.cpp index 2b282a1ac..305046262 100644 --- a/test/sources/libcxx/map/map.cons/move.pass.cpp +++ b/test/sources/libcxx/map/map.cons/move.pass.cpp @@ -32,7 +32,8 @@ int main(int, char**) assert(std::distance(m.begin(), m.end()) == 0); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); @@ -64,7 +65,8 @@ int main(int, char**) assert(*std::next(m.begin(), 2) == V(3, 1)); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); diff --git a/test/sources/libcxx/map/map.modifiers/insert_node_type.pass.cpp b/test/sources/libcxx/map/map.modifiers/insert_node_type.pass.cpp index 1303eef57..a60d6453a 100644 --- a/test/sources/libcxx/map/map.modifiers/insert_node_type.pass.cpp +++ b/test/sources/libcxx/map/map.modifiers/insert_node_type.pass.cpp @@ -18,6 +18,27 @@ // insert_return_type insert(node_type&&); +template +void verify_insert_return_type(T&& t) { + using verified_type = std::remove_cv_t>; + static_assert(std::is_aggregate_v); + static_assert(std::is_same_v); + + auto& [pos, ins, nod] = t; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(std::addressof(pos) == std::addressof(t.position)); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(&ins == &t.inserted); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(std::addressof(nod) == std::addressof(t.node)); +} + template typename Container::node_type node_factory(typename Container::key_type const& key, @@ -43,6 +64,7 @@ void test(Container& c) assert(irt.inserted); assert(irt.node.empty()); assert(irt.position->first == i && irt.position->second == i + 1); + verify_insert_return_type(irt); } assert(c.size() == 10); @@ -54,6 +76,7 @@ void test(Container& c) assert(!irt.inserted); assert(irt.node.empty()); assert(irt.position == c.end()); + verify_insert_return_type(irt); } { // Insert duplicate node. @@ -64,6 +87,7 @@ void test(Container& c) assert(!irt.node.empty()); assert(irt.position == c.find(0)); assert(irt.node.key() == 0 && irt.node.mapped() == 42); + verify_insert_return_type(irt); } assert(c.size() == 10); diff --git a/test/sources/libcxx/map/map.modifiers/insert_range.pass.cpp b/test/sources/libcxx/map/map.modifiers/insert_range.pass.cpp new file mode 100644 index 000000000..c9ceb7335 --- /dev/null +++ b/test/sources/libcxx/map/map.modifiers/insert_range.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// Some fields in the test case variables are deliberately not explicitly initialized, this silences a warning on GCC. +// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-missing-field-initializers + +// + +// template R> +// void insert_range(R&& rg); // C++23 + +int main(int, char**) { + // Note: we want to use a pair with non-const elements for input (an assignable type is a lot more convenient) but + // have to use the exact `value_type` of the map (that is, `pair`) for the allocator. + using Pair = std::pair; + using ConstPair = std::pair; + for_all_iterators_and_allocators([]() { + test_map_set_insert_range, Alloc>, Pair, Iter, Sent>(); + }); + + static_assert(test_map_constraints_insert_range()); + + test_map_insert_range_move_only(); + + test_map_insert_range_exception_safety_throwing_copy(); + test_assoc_map_insert_range_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/map/map.ops/count.pass.cpp b/test/sources/libcxx/map/map.ops/count.pass.cpp index 73727ae9a..4fe4b9169 100644 --- a/test/sources/libcxx/map/map.ops/count.pass.cpp +++ b/test/sources/libcxx/map/map.ops/count.pass.cpp @@ -16,176 +16,70 @@ // size_type count(const key_type& k) const; -int main(int, char**) -{ - { - typedef std::pair V; - typedef std::map M; - { - typedef M::size_type R; - V ar[] = - { - V(5, 5), - V(6, 6), - V(7, 7), - V(8, 8), - V(9, 9), - V(10, 10), - V(11, 11), - V(12, 12) - }; - const M m(ar, ar+sizeof(ar)/sizeof(ar[0])); - R r = m.count(5); - assert(r == 1); - r = m.count(6); - assert(r == 1); - r = m.count(7); - assert(r == 1); - r = m.count(8); - assert(r == 1); - r = m.count(9); - assert(r == 1); - r = m.count(10); - assert(r == 1); - r = m.count(11); - assert(r == 1); - r = m.count(12); - assert(r == 1); - r = m.count(4); - assert(r == 0); - } - } #if TEST_STD_VER >= 11 - { - typedef std::pair V; - typedef std::map, min_allocator> M; - { - typedef M::size_type R; - V ar[] = - { - V(5, 5), - V(6, 6), - V(7, 7), - V(8, 8), - V(9, 9), - V(10, 10), - V(11, 11), - V(12, 12) - }; - const M m(ar, ar+sizeof(ar)/sizeof(ar[0])); - R r = m.count(5); - assert(r == 1); - r = m.count(6); - assert(r == 1); - r = m.count(7); - assert(r == 1); - r = m.count(8); - assert(r == 1); - r = m.count(9); - assert(r == 1); - r = m.count(10); - assert(r == 1); - r = m.count(11); - assert(r == 1); - r = m.count(12); - assert(r == 1); - r = m.count(4); - assert(r == 0); - } - } +template +struct FinalCompare final { + bool operator()(const T& x, const T& y) const { return x < y; } +}; #endif -#if TEST_STD_VER > 11 - { - typedef std::pair V; - typedef std::map> M; - typedef M::size_type R; - V ar[] = - { - V(5, 5), - V(6, 6), - V(7, 7), - V(8, 8), - V(9, 9), - V(10, 10), - V(11, 11), - V(12, 12) - }; - const M m(ar, ar+sizeof(ar)/sizeof(ar[0])); - R r = m.count(5); - assert(r == 1); - r = m.count(6); - assert(r == 1); - r = m.count(7); - assert(r == 1); - r = m.count(8); - assert(r == 1); - r = m.count(9); - assert(r == 1); - r = m.count(10); - assert(r == 1); - r = m.count(11); - assert(r == 1); - r = m.count(12); - assert(r == 1); - r = m.count(4); +template +void test() { + typedef typename Map::value_type V; + typedef typename Map::size_type R; + + V ar[] = {V(5, 5), V(6, 6), V(7, 7), V(8, 8), V(9, 9), V(10, 10), V(11, 11), V(12, 12)}; + + const Map m(ar, ar + sizeof(ar) / sizeof(ar[0])); + + for (int i = 0; i < 5; ++i) { + R r = m.count(ArgType(i)); assert(r == 0); + } - r = m.count(C2Int(5)); - assert(r == 1); - r = m.count(C2Int(6)); - assert(r == 1); - r = m.count(C2Int(7)); - assert(r == 1); - r = m.count(C2Int(8)); - assert(r == 1); - r = m.count(C2Int(9)); + for (int i = 5; i < 13; ++i) { + R r = m.count(ArgType(i)); assert(r == 1); - r = m.count(C2Int(10)); - assert(r == 1); - r = m.count(C2Int(11)); - assert(r == 1); - r = m.count(C2Int(12)); - assert(r == 1); - r = m.count(C2Int(4)); - assert(r == 0); - } + } +} - { +int main(int, char**) { + test >(); +#if TEST_STD_VER >= 11 + typedef std::pair V; + test, min_allocator>>(); + test>>(); +#endif +#if TEST_STD_VER >= 14 + typedef std::map> TM; + test(); + test(); + + { typedef PrivateConstructor PC; - typedef std::map> M; + typedef std::map > M; typedef M::size_type R; M m; - m [ PC::make(5) ] = 5; - m [ PC::make(6) ] = 6; - m [ PC::make(7) ] = 7; - m [ PC::make(8) ] = 8; - m [ PC::make(9) ] = 9; - m [ PC::make(10) ] = 10; - m [ PC::make(11) ] = 11; - m [ PC::make(12) ] = 12; + m[PC::make(5)] = 5; + m[PC::make(6)] = 6; + m[PC::make(7)] = 7; + m[PC::make(8)] = 8; + m[PC::make(9)] = 9; + m[PC::make(10)] = 10; + m[PC::make(11)] = 11; + m[PC::make(12)] = 12; - R r = m.count(5); - assert(r == 1); - r = m.count(6); - assert(r == 1); - r = m.count(7); - assert(r == 1); - r = m.count(8); - assert(r == 1); - r = m.count(9); - assert(r == 1); - r = m.count(10); - assert(r == 1); - r = m.count(11); - assert(r == 1); - r = m.count(12); - assert(r == 1); - r = m.count(4); - assert(r == 0); + for (int i = 0; i < 5; ++i) { + R r = m.count(i); + assert(r == 0); } -#endif + for (int i = 5; i < 13; ++i) { + R r = m.count(i); + assert(r == 1); + } + } +#endif // TEST_STD_VER >= 14 return 0; } diff --git a/test/sources/libcxx/multimap/multimap.cons/deduct.pass.cpp b/test/sources/libcxx/multimap/multimap.cons/deduct.pass.cpp index 1b5f3c1e0..155b981fa 100644 --- a/test/sources/libcxx/multimap/multimap.cons/deduct.pass.cpp +++ b/test/sources/libcxx/multimap/multimap.cons/deduct.pass.cpp @@ -28,6 +28,15 @@ // template // multimap(initializer_list, Allocator) // -> multimap, Allocator>; +// +// template>, +// class Allocator = allocator>> +// multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) +// -> multimap, range-mapped-type, Compare, Allocator>; // C++23 +// +// template +// multimap(from_range_t, R&&, Allocator) +// -> multimap, range-mapped-type, less>, Allocator>; // C++23 using P = std::pair; using PC = std::pair; @@ -158,7 +167,37 @@ int main(int, char**) #endif } +#if TEST_STD_VER >= 23 + { + using Range = std::array; + using Comp = std::greater; + using DefaultComp = std::less; + using Alloc = test_allocator; + + { // (from_range, range) + momo::stdish::multimap c(std::from_range, Range()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp) + momo::stdish::multimap c(std::from_range, Range(), Comp()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp, alloc) + momo::stdish::multimap c(std::from_range, Range(), Comp(), Alloc()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, alloc) + momo::stdish::multimap c(std::from_range, Range(), Alloc()); + static_assert(std::is_same_v>); + } + } +#endif + #if MOMO_VERSION_MAJOR > 3 + //AssociativeContainerDeductionGuidesSfinaeAway>(); AssociativeContainerDeductionGuidesSfinaeAway>(); #endif diff --git a/test/sources/libcxx/multimap/multimap.cons/default_recursive.pass.cpp b/test/sources/libcxx/multimap/multimap.cons/default_recursive.compile.pass.cpp similarity index 67% rename from test/sources/libcxx/multimap/multimap.cons/default_recursive.pass.cpp rename to test/sources/libcxx/multimap/multimap.cons/default_recursive.compile.pass.cpp index 33ec6ce30..6d44c28ad 100644 --- a/test/sources/libcxx/multimap/multimap.cons/default_recursive.pass.cpp +++ b/test/sources/libcxx/multimap/multimap.cons/default_recursive.compile.pass.cpp @@ -16,15 +16,14 @@ // multimap(); -struct X -{ - std::multimap m; - std::multimap::iterator i; - std::multimap::const_iterator ci; +struct X { + std::multimap m; + std::multimap::iterator i; + std::multimap::const_iterator ci; #if TEST_STD_VER <= 17 - // These reverse_iterator specializations require X to be complete in C++20. - std::multimap::reverse_iterator ri; - std::multimap::const_reverse_iterator cri; + // These reverse_iterator specializations require X to be complete in C++20. + std::multimap::reverse_iterator ri; + std::multimap::const_reverse_iterator cri; #endif // TEST_STD_VER <= 17 }; diff --git a/test/sources/libcxx/multimap/multimap.cons/from_range.pass.cpp b/test/sources/libcxx/multimap/multimap.cons/from_range.pass.cpp new file mode 100644 index 000000000..37da8bb8d --- /dev/null +++ b/test/sources/libcxx/multimap/multimap.cons/from_range.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template R> +// multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 +// +// template R> +// multimap(from_range_t, R&& rg, const Allocator& a)) +// : multimap(from_range, std::forward(rg), Compare(), a) { } // C++23 + +void test_duplicates() { + using T = std::pair; + std::array input = { + T{1, 'a'}, T{2, 'a'}, T{3, 'a'}, T{3, 'b'}, T{3, 'c'}, T{2, 'b'}, T{4, 'a'} + }; + auto c = std::multimap(std::from_range, input); + assert(std::ranges::is_permutation(input, c)); +} + +int main(int, char**) { + using T = std::pair; + for_all_iterators_and_allocators([]() { + test_associative_map, Alloc>(); + }); + test_associative_map_move_only(); + test_duplicates(); + + static_assert(test_map_constraints()); + + test_map_exception_safety_throwing_copy(); + test_map_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/multimap/multimap.cons/move.pass.cpp b/test/sources/libcxx/multimap/multimap.cons/move.pass.cpp index bf64a5605..be41b901c 100644 --- a/test/sources/libcxx/multimap/multimap.cons/move.pass.cpp +++ b/test/sources/libcxx/multimap/multimap.cons/move.pass.cpp @@ -32,7 +32,8 @@ int main(int, char**) assert(std::distance(m.begin(), m.end()) == 0); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); @@ -70,7 +71,8 @@ int main(int, char**) assert(*std::next(m.begin(), 8) == V(3, 2)); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); diff --git a/test/sources/libcxx/multimap/multimap.modifiers/insert_range.pass.cpp b/test/sources/libcxx/multimap/multimap.modifiers/insert_range.pass.cpp new file mode 100644 index 000000000..6ffc08620 --- /dev/null +++ b/test/sources/libcxx/multimap/multimap.modifiers/insert_range.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// Some fields in the test case variables are deliberately not explicitly initialized, this silences a warning on GCC. +// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-missing-field-initializers + +// + +// template R> +// void insert_range(R&& rg); // C++23 + +int main(int, char**) { + // Note: we want to use a pair with non-const elements for input (an assignable type is a lot more convenient) but + // have to use the exact `value_type` of the map (that is, `pair`) for the allocator. + using Pair = std::pair; + using ConstPair = std::pair; + for_all_iterators_and_allocators([]() { + test_map_set_insert_range, Alloc>, Pair, Iter, Sent>(/*allow_duplicates=*/true); + }); + + static_assert(test_map_constraints_insert_range()); + + test_map_insert_range_move_only(); + + test_map_insert_range_exception_safety_throwing_copy(); + test_assoc_map_insert_range_exception_safety_throwing_allocator(); + + return 0; +} + diff --git a/test/sources/libcxx/multiset/insert_range.pass.cpp b/test/sources/libcxx/multiset/insert_range.pass.cpp new file mode 100644 index 000000000..ed88bcd63 --- /dev/null +++ b/test/sources/libcxx/multiset/insert_range.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// Some fields in the test case variables are deliberately not explicitly initialized, this silences a warning on GCC. +// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-missing-field-initializers + +// + +// template R> +// void insert_range(R&& rg); // C++23 + +int main(int, char**) { + for_all_iterators_and_allocators([]() { + test_map_set_insert_range, Alloc>, int, Iter, Sent>(/*allow_duplicates=*/true); + }); + + static_assert(test_set_constraints_insert_range()); + + test_set_insert_range_move_only(); + + test_set_insert_range_exception_safety_throwing_copy(); + test_assoc_set_insert_range_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/multiset/multiset.cons/deduct.pass.cpp b/test/sources/libcxx/multiset/multiset.cons/deduct.pass.cpp index b21cafd70..4043db7ca 100644 --- a/test/sources/libcxx/multiset/multiset.cons/deduct.pass.cpp +++ b/test/sources/libcxx/multiset/multiset.cons/deduct.pass.cpp @@ -31,6 +31,15 @@ // template // multiset(initializer_list, Allocator) // -> multiset, Allocator>; +// +// template>, +// class Allocator = allocator>> +// multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) +// -> multiset, Compare, Allocator>; +// +// template +// multiset(from_range_t, R&&, Allocator) +// -> multiset, less>, Allocator>; struct NotAnAllocator { friend bool operator<(NotAnAllocator, NotAnAllocator) { return false; } @@ -189,8 +198,38 @@ int main(int, char **) { } #endif -#if !(defined(TEST_MSVC) && _MSC_VER < 1930) - AssociativeContainerDeductionGuidesSfinaeAway>(); +#if TEST_STD_VER >= 23 + { + using Range = std::array; + using Comp = std::greater; + using DefaultComp = std::less; + using Alloc = test_allocator; + + { // (from_range, range) + momo::stdish::multiset c(std::from_range, Range()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp) + momo::stdish::multiset c(std::from_range, Range(), Comp()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp, alloc) + momo::stdish::multiset c(std::from_range, Range(), Comp(), Alloc()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, alloc) + momo::stdish::multiset c(std::from_range, Range(), Alloc()); + static_assert(std::is_same_v>); + } + } +#endif + +#if MOMO_VERSION_MAJOR > 3 + //AssociativeContainerDeductionGuidesSfinaeAway>(); + AssociativeContainerDeductionGuidesSfinaeAway>(); #endif return 0; diff --git a/test/sources/libcxx/multiset/multiset.cons/from_range.pass.cpp b/test/sources/libcxx/multiset/multiset.cons/from_range.pass.cpp new file mode 100644 index 000000000..f96fe35cc --- /dev/null +++ b/test/sources/libcxx/multiset/multiset.cons/from_range.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template R> +// multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 +// +// template R> +// multiset(from_range_t, R&& rg, const Allocator& a)) +// : multiset(from_range, std::forward(rg), Compare(), a) { } // C++23 + +void test_duplicates() { + std::array input = {1, 2, 3, 3, 3, 4, 2, 1, 2}; + auto c = std::multiset(std::from_range, input); + assert(std::ranges::is_permutation(input, c)); +} + +int main(int, char**) { + for_all_iterators_and_allocators([]() { + test_associative_set, Alloc>(); + }); + test_associative_set_move_only(); + test_duplicates(); + + static_assert(test_set_constraints()); + + test_set_exception_safety_throwing_copy(); + test_set_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/multiset/multiset.cons/move.pass.cpp b/test/sources/libcxx/multiset/multiset.cons/move.pass.cpp index b59b2e5f5..fc2815ad7 100644 --- a/test/sources/libcxx/multiset/multiset.cons/move.pass.cpp +++ b/test/sources/libcxx/multiset/multiset.cons/move.pass.cpp @@ -32,7 +32,8 @@ int main(int, char**) assert(std::distance(m.begin(), m.end()) == 0); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); @@ -71,7 +72,8 @@ int main(int, char**) assert(*std::next(m.begin(), 8) == 3); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); diff --git a/test/sources/libcxx/set/insert_node_type.pass.cpp b/test/sources/libcxx/set/insert_node_type.pass.cpp index 3aeb8ca68..714f87c46 100644 --- a/test/sources/libcxx/set/insert_node_type.pass.cpp +++ b/test/sources/libcxx/set/insert_node_type.pass.cpp @@ -18,6 +18,27 @@ // insert_return_type insert(node_type&&); +template +void verify_insert_return_type(T&& t) { + using verified_type = std::remove_cv_t>; + static_assert(std::is_aggregate_v); + static_assert(std::is_same_v); + + auto& [pos, ins, nod] = t; + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(std::addressof(pos) == std::addressof(t.position)); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(&ins == &t.inserted); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + assert(std::addressof(nod) == std::addressof(t.node)); +} + template typename Container::node_type node_factory(typename Container::key_type const& key) @@ -42,6 +63,7 @@ void test(Container& c) assert(irt.inserted); assert(irt.node.empty()); assert(*irt.position == i); + verify_insert_return_type(irt); } assert(c.size() == 10); @@ -53,6 +75,7 @@ void test(Container& c) assert(!irt.inserted); assert(irt.node.empty()); assert(irt.position == c.end()); + verify_insert_return_type(irt); } { // Insert duplicate node. @@ -63,6 +86,7 @@ void test(Container& c) assert(!irt.node.empty()); assert(irt.position == c.find(0)); assert(irt.node.value() == 0); + verify_insert_return_type(irt); } assert(c.size() == 10); diff --git a/test/sources/libcxx/set/insert_range.pass.cpp b/test/sources/libcxx/set/insert_range.pass.cpp new file mode 100644 index 000000000..43e61b5ed --- /dev/null +++ b/test/sources/libcxx/set/insert_range.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// Some fields in the test case variables are deliberately not explicitly initialized, this silences a warning on GCC. +// ADDITIONAL_COMPILE_FLAGS(gcc-style-warnings): -Wno-missing-field-initializers + +// + +// template R> +// void insert_range(R&& rg); // C++23 + +int main(int, char**) { + for_all_iterators_and_allocators([]() { + test_map_set_insert_range, Alloc>, int, Iter, Sent>(); + }); + + static_assert(test_set_constraints_insert_range()); + + test_set_insert_range_move_only(); + + test_set_insert_range_exception_safety_throwing_copy(); + test_assoc_set_insert_range_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/set/set.cons/deduct.pass.cpp b/test/sources/libcxx/set/set.cons/deduct.pass.cpp index 9fceffe54..2d02da7bd 100644 --- a/test/sources/libcxx/set/set.cons/deduct.pass.cpp +++ b/test/sources/libcxx/set/set.cons/deduct.pass.cpp @@ -31,6 +31,15 @@ // template // set(initializer_list, Allocator) // -> set, Allocator>; +// +// template>, +// class Allocator = allocator>> +// set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) +// -> set, Compare, Allocator>; // C++23 +// +// template +// set(from_range_t, R&&, Allocator) +// -> set, less>, Allocator>; // C++23 struct NotAnAllocator { friend bool operator<(NotAnAllocator, NotAnAllocator) { return false; } @@ -179,7 +188,37 @@ int main(int, char **) { assert(s.size() == 2); } +#if TEST_STD_VER >= 23 + { + using Range = std::array; + using Comp = std::greater; + using DefaultComp = std::less; + using Alloc = test_allocator; + + { // (from_range, range) + momo::stdish::set c(std::from_range, Range()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp) + momo::stdish::set c(std::from_range, Range(), Comp()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, comp, alloc) + momo::stdish::set c(std::from_range, Range(), Comp(), Alloc()); + static_assert(std::is_same_v>); + } + + { // (from_range, range, alloc) + momo::stdish::set c(std::from_range, Range(), Alloc()); + static_assert(std::is_same_v>); + } + } +#endif + #if MOMO_VERSION_MAJOR > 3 + //AssociativeContainerDeductionGuidesSfinaeAway>(); AssociativeContainerDeductionGuidesSfinaeAway>(); #endif diff --git a/test/sources/libcxx/set/set.cons/from_range.pass.cpp b/test/sources/libcxx/set/set.cons/from_range.pass.cpp new file mode 100644 index 000000000..3c434e5d0 --- /dev/null +++ b/test/sources/libcxx/set/set.cons/from_range.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// template R> +// set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); // C++23 +// +// template R> +// set(from_range_t, R&& rg, const Allocator& a)) +// : set(from_range, std::forward(rg), Compare(), a) { } // C++23 + +void test_duplicates() { + using T = KeyValue; + + std::array input = { + T{1, 'a'}, T{2, 'a'}, T{3, 'a'}, T{3, 'b'}, T{3, 'c'}, T{2, 'b'}, T{4, 'a'} + }; + std::array expected = { + T{1, 'a'}, T{2, 'b'}, T{3, 'c'}, T{4, 'a'} + }; + auto c = std::set(std::from_range, input); + assert(std::ranges::is_permutation(expected, c)); +} + +int main(int, char**) { + for_all_iterators_and_allocators([]() { + test_associative_set, Alloc>(); + }); + test_associative_set_move_only(); + test_duplicates(); + + static_assert(test_set_constraints()); + + test_set_exception_safety_throwing_copy(); + test_set_exception_safety_throwing_allocator(); + + return 0; +} diff --git a/test/sources/libcxx/set/set.cons/move.pass.cpp b/test/sources/libcxx/set/set.cons/move.pass.cpp index 6a9549702..0ec527ba6 100644 --- a/test/sources/libcxx/set/set.cons/move.pass.cpp +++ b/test/sources/libcxx/set/set.cons/move.pass.cpp @@ -32,7 +32,8 @@ int main(int, char**) assert(std::distance(m.begin(), m.end()) == 0); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); @@ -65,7 +66,8 @@ int main(int, char**) assert(*std::next(m.begin(), 2) == 3); #ifdef LIBCPP_HAS_BAD_NEWS_FOR_MOMO - assert(mo.get_allocator() == A(test_alloc_base::moved_value)); + assert(mo.get_allocator() == A(7)); + assert(mo.get_allocator().get_id() == test_alloc_base::moved_value); assert(mo.key_comp() == C(5)); #endif assert(mo.size() == 0); diff --git a/test/sources/libcxx/support/Counter.h b/test/sources/libcxx/support/Counter.h index 0d1c645a0..49f375ea9 100644 --- a/test/sources/libcxx/support/Counter.h +++ b/test/sources/libcxx/support/Counter.h @@ -44,16 +44,12 @@ class Counter : public Counter_base inline int Counter_base::gConstructed = 0; -namespace std { - template -struct hash > -{ - typedef Counter argument_type; - typedef std::size_t result_type; +struct std::hash > { + typedef Counter argument_type; + typedef std::size_t result_type; - std::size_t operator()(const Counter& x) const {return std::hash()(x.get());} + std::size_t operator()(const Counter& x) const { return std::hash()(x.get()); } }; -} #endif diff --git a/test/sources/libcxx/support/Emplaceable.h b/test/sources/libcxx/support/Emplaceable.h index 41d929aa2..8452c10fc 100644 --- a/test/sources/libcxx/support/Emplaceable.h +++ b/test/sources/libcxx/support/Emplaceable.h @@ -44,18 +44,13 @@ class Emplaceable int get() const {return int_;} }; -namespace std { - template <> -struct hash -{ - typedef Emplaceable argument_type; - typedef std::size_t result_type; +struct std::hash { + typedef Emplaceable argument_type; + typedef std::size_t result_type; - std::size_t operator()(const Emplaceable& x) const {return static_cast(x.get());} + std::size_t operator()(const Emplaceable& x) const { return static_cast(x.get()); } }; -} - #endif // TEST_STD_VER >= 11 #endif // EMPLACEABLE_H diff --git a/test/sources/libcxx/support/MoveOnly.h b/test/sources/libcxx/support/MoveOnly.h index 88c107596..785fc62db 100644 --- a/test/sources/libcxx/support/MoveOnly.h +++ b/test/sources/libcxx/support/MoveOnly.h @@ -56,10 +56,12 @@ class MoveOnly TEST_CONSTEXPR_CXX14 MoveOnly operator*(const MoveOnly& x) const { return MoveOnly(data_ * x.data_); } - template - friend void operator,(T t, U u) = delete; -}; + template + friend void operator,(MoveOnly const&, T) = delete; + template + friend void operator,(T, MoveOnly const&) = delete; +}; template <> struct std::hash @@ -69,4 +71,62 @@ struct std::hash TEST_CONSTEXPR std::size_t operator()(const MoveOnly& x) const {return static_cast(x.get());} }; +class TrivialMoveOnly { + int data_; + + public: + TEST_CONSTEXPR TrivialMoveOnly(int data = 1) : data_(data) {} + + TrivialMoveOnly(const TrivialMoveOnly&) = delete; + TrivialMoveOnly& operator=(const TrivialMoveOnly&) = delete; + + TrivialMoveOnly(TrivialMoveOnly&&) = default; + TrivialMoveOnly& operator=(TrivialMoveOnly&&) = default; + + TEST_CONSTEXPR int get() const { return data_; } + + friend TEST_CONSTEXPR bool operator==(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ == y.data_; + } + friend TEST_CONSTEXPR bool operator!=(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ != y.data_; + } + friend TEST_CONSTEXPR bool operator<(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ < y.data_; + } + friend TEST_CONSTEXPR bool operator<=(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ <= y.data_; + } + friend TEST_CONSTEXPR bool operator>(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ > y.data_; + } + friend TEST_CONSTEXPR bool operator>=(const TrivialMoveOnly& x, const TrivialMoveOnly& y) { + return x.data_ >= y.data_; + } + +#if TEST_STD_VER > 17 + friend constexpr auto operator<=>(const TrivialMoveOnly&, const TrivialMoveOnly&) = default; +#endif // TEST_STD_VER > 17 + + TEST_CONSTEXPR_CXX14 TrivialMoveOnly operator+(const TrivialMoveOnly& x) const { + return TrivialMoveOnly(data_ + x.data_); + } + TEST_CONSTEXPR_CXX14 TrivialMoveOnly operator*(const TrivialMoveOnly& x) const { + return TrivialMoveOnly(data_ * x.data_); + } + + template + friend void operator,(TrivialMoveOnly const&, T) = delete; + + template + friend void operator,(T, TrivialMoveOnly const&) = delete; +}; + +template <> +struct std::hash { + typedef TrivialMoveOnly argument_type; + typedef std::size_t result_type; + TEST_CONSTEXPR std::size_t operator()(const TrivialMoveOnly& x) const { return static_cast(x.get()); } +}; + #endif // MOVEONLY_H diff --git a/test/sources/libcxx/support/NotConstructible.h b/test/sources/libcxx/support/NotConstructible.h index 1ad4f9c63..eafdba6c4 100644 --- a/test/sources/libcxx/support/NotConstructible.h +++ b/test/sources/libcxx/support/NotConstructible.h @@ -27,18 +27,12 @@ bool operator==(const NotConstructible&, const NotConstructible&) {return true;} -namespace std -{ - template <> -struct hash -{ - typedef NotConstructible argument_type; - typedef std::size_t result_type; +struct std::hash { + typedef NotConstructible argument_type; + typedef std::size_t result_type; - std::size_t operator()(const NotConstructible&) const {return 0;} + std::size_t operator()(const NotConstructible&) const { return 0; } }; -} - #endif // NOTCONSTRUCTIBLE_H diff --git a/test/sources/libcxx/support/allocators.h b/test/sources/libcxx/support/allocators.h index 4cb9c84ed..5dc0c91e8 100644 --- a/test/sources/libcxx/support/allocators.h +++ b/test/sources/libcxx/support/allocators.h @@ -213,7 +213,7 @@ class MaybePOCCAAllocator { : id_(id), copy_assigned_into_(copy_assigned_into) {} template - MaybePOCCAAllocator(const MaybePOCCAAllocator& that) + TEST_CONSTEXPR MaybePOCCAAllocator(const MaybePOCCAAllocator& that) : id_(that.id_), copy_assigned_into_(that.copy_assigned_into_) {} MaybePOCCAAllocator(const MaybePOCCAAllocator&) = default; diff --git a/test/sources/libcxx/support/almost_satisfies_types.h b/test/sources/libcxx/support/almost_satisfies_types.h new file mode 100644 index 000000000..5f57727f3 --- /dev/null +++ b/test/sources/libcxx/support/almost_satisfies_types.h @@ -0,0 +1,445 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +#ifndef ALMOST_SATISFIES_TYPES_H +#define ALMOST_SATISFIES_TYPES_H + +#include +#include +#include + +#include "test_iterators.h" + +template > +class UncheckedRange { +public: + T begin(); + U end(); +}; + +static_assert(std::ranges::contiguous_range>); + +// almost an input_iterator +template +class InputIteratorNotDerivedFromGeneric { +public: + using difference_type = long; + using value_type = T; + using iterator_category = void; + + InputIteratorNotDerivedFromGeneric& operator++(); + void operator++(int); + const T& operator*() const; +}; + +using InputIteratorNotDerivedFrom = InputIteratorNotDerivedFromGeneric; + +template +using InputRangeNotDerivedFromGeneric = UncheckedRange>; +using InputRangeNotDerivedFrom = UncheckedRange; + +static_assert(std::input_or_output_iterator); +static_assert(std::indirectly_readable); +static_assert(!std::input_iterator); +static_assert(!std::ranges::input_range); + +class InputIteratorNotIndirectlyReadable { +public: + using difference_type = long; + using iterator_category = std::input_iterator_tag; + + InputIteratorNotIndirectlyReadable& operator++(); + void operator++(int); + const int& operator*() const; +}; + +using InputRangeNotIndirectlyReadable = UncheckedRange; + +static_assert(std::input_or_output_iterator); +static_assert(!std::indirectly_readable); +static_assert(!std::input_iterator); +static_assert(!std::ranges::input_range); + +class InputIteratorNotInputOrOutputIterator { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::input_iterator_tag; + + int& operator++(); + void operator++(int); + const int& operator*() const; +}; + +using InputRangeNotInputOrOutputIterator = UncheckedRange; + +static_assert(!std::input_or_output_iterator); +static_assert(std::indirectly_readable); +static_assert(!std::input_iterator); +static_assert(!std::ranges::input_range); + +// almost an indirect_unary_predicate +class IndirectUnaryPredicateNotCopyConstructible { +public: + IndirectUnaryPredicateNotCopyConstructible(const IndirectUnaryPredicateNotCopyConstructible&) = delete; + bool operator()(int) const; +}; + +static_assert(std::predicate); +static_assert(!std::indirect_unary_predicate); + +class IndirectUnaryPredicateNotPredicate { +public: + bool operator()(int&&) const; +}; + +static_assert(!std::predicate); +static_assert(!std::indirect_unary_predicate); + +// almost a sentinel_for cpp20_input_iterator +class SentinelForNotSemiregular { +public: + SentinelForNotSemiregular() = delete; + using difference_type = long; + SentinelForNotSemiregular& operator++(); + void operator++(int); + const int& operator*() const; + friend bool operator==(const SentinelForNotSemiregular&, const cpp20_input_iterator&); +}; + +using InputRangeNotSentinelSemiregular = UncheckedRange, SentinelForNotSemiregular>; +using OutputRangeNotSentinelSemiregular = UncheckedRange, SentinelForNotSemiregular>; + +static_assert(std::input_or_output_iterator); +static_assert(!std::semiregular); +static_assert(!std::sentinel_for>); + +// almost a sentinel_for cpp20_input_iterator +class SentinelForNotWeaklyEqualityComparableWith { +public: + using difference_type = long; + SentinelForNotWeaklyEqualityComparableWith& operator++(); + void operator++(int); + const int& operator*() const; +}; + +using InputRangeNotSentinelEqualityComparableWith = + UncheckedRange, SentinelForNotWeaklyEqualityComparableWith>; +using OutputRangeNotSentinelEqualityComparableWith = + UncheckedRange, SentinelForNotWeaklyEqualityComparableWith>; + +static_assert(std::input_or_output_iterator); +static_assert(std::semiregular); +static_assert(!std::sentinel_for>); + +class WeaklyIncrementableNotMovable { +public: + using difference_type = long; + WeaklyIncrementableNotMovable& operator++(); + void operator++(int); + WeaklyIncrementableNotMovable(const WeaklyIncrementableNotMovable&) = delete; +}; + +static_assert(!std::movable); +static_assert(!std::weakly_incrementable); + +// almost a forward_iterator +class ForwardIteratorNotDerivedFrom { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::input_iterator_tag; + + ForwardIteratorNotDerivedFrom& operator++(); + ForwardIteratorNotDerivedFrom operator++(int); + const int& operator*() const; + bool operator==(const ForwardIteratorNotDerivedFrom&) const = default; +}; + +using ForwardRangeNotDerivedFrom = UncheckedRange; + +static_assert(std::input_iterator); +static_assert(std::incrementable); +static_assert(std::sentinel_for); +static_assert(!std::forward_iterator); + +class ForwardIteratorNotIncrementable { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::forward_iterator_tag; + + ForwardIteratorNotIncrementable& operator++(); + int operator++(int); + const int& operator*() const; + bool operator==(const ForwardIteratorNotIncrementable&) const = default; +}; + +using ForwardRangeNotIncrementable = UncheckedRange; + +static_assert(std::input_iterator); +static_assert(!std::incrementable); +static_assert(std::sentinel_for); +static_assert(!std::forward_iterator); + +using ForwardRangeNotSentinelSemiregular = UncheckedRange, SentinelForNotSemiregular>; +using ForwardRangeNotSentinelEqualityComparableWith = + UncheckedRange, SentinelForNotWeaklyEqualityComparableWith>; + +class BidirectionalIteratorNotDerivedFrom { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::forward_iterator_tag; + + BidirectionalIteratorNotDerivedFrom& operator++(); + BidirectionalIteratorNotDerivedFrom operator++(int); + BidirectionalIteratorNotDerivedFrom& operator--(); + BidirectionalIteratorNotDerivedFrom operator--(int); + int& operator*() const; + + bool operator==(const BidirectionalIteratorNotDerivedFrom&) const = default; +}; + +using BidirectionalRangeNotDerivedFrom = UncheckedRange; +using BidirectionalRangeNotSentinelSemiregular = + UncheckedRange, SentinelForNotSemiregular>; +using BidirectionalRangeNotSentinelWeaklyEqualityComparableWith = + UncheckedRange, SentinelForNotWeaklyEqualityComparableWith>; + +static_assert(std::forward_iterator); +static_assert(!std::bidirectional_iterator); +static_assert(!std::ranges::bidirectional_range); + +class BidirectionalIteratorNotDecrementable { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::bidirectional_iterator_tag; + + BidirectionalIteratorNotDecrementable& operator++(); + BidirectionalIteratorNotDecrementable operator++(int); + int& operator*() const; + + bool operator==(const BidirectionalIteratorNotDecrementable&) const = default; +}; + +using BidirectionalRangeNotDecrementable = UncheckedRange; + +static_assert(std::forward_iterator); +static_assert(!std::bidirectional_iterator); +static_assert(!std::ranges::bidirectional_range); + +class PermutableNotForwardIterator { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::input_iterator_tag; + + PermutableNotForwardIterator& operator++(); + void operator++(int); + int& operator*() const; +}; + +using PermutableRangeNotForwardIterator = UncheckedRange; + +static_assert(std::input_iterator); +static_assert(!std::forward_iterator); +static_assert(!std::permutable); + +class PermutableNotSwappable { +public: + class NotSwappable { + NotSwappable(NotSwappable&&) = delete; + }; + + using difference_type = long; + using value_type = NotSwappable; + using iterator_category = std::contiguous_iterator_tag; + + PermutableNotSwappable& operator++(); + PermutableNotSwappable operator++(int); + NotSwappable& operator*() const; + + bool operator==(const PermutableNotSwappable&) const = default; +}; + +using PermutableRangeNotSwappable = UncheckedRange; + +static_assert(std::input_iterator); +static_assert(std::forward_iterator); +static_assert(!std::permutable); +static_assert(!std::indirectly_swappable); + +class OutputIteratorNotInputOrOutputIterator { +public: + using difference_type = long; + using value_type = int; + using iterator_category = std::input_iterator_tag; + + int& operator++(); + void operator++(int); + int& operator*(); +}; + +using OutputRangeNotInputOrOutputIterator = UncheckedRange; + +static_assert(!std::input_or_output_iterator); +static_assert(std::indirectly_writable); +static_assert(!std::output_iterator); +static_assert(!std::ranges::output_range); + +class OutputIteratorNotIndirectlyWritable { +public: + using difference_type = long; + using iterator_category = std::input_iterator_tag; + + OutputIteratorNotIndirectlyWritable& operator++(); + void operator++(int); + const int& operator*() const; +}; + +using OutputRangeNotIndirectlyWritable = UncheckedRange; + +static_assert(std::input_or_output_iterator); +static_assert(!std::indirectly_writable); +static_assert(!std::output_iterator); +static_assert(!std::ranges::output_range); + +class IndirectBinaryPredicateNotIndirectlyReadable { +public: + using difference_type = long; + using iterator_category = std::input_iterator_tag; + + int& operator++(); + void operator++(int); + const int& operator*() const; +}; + +using InputRangeIndirectBinaryPredicateNotIndirectlyReadable + = UncheckedRange, IndirectBinaryPredicateNotIndirectlyReadable>; + +static_assert(!std::indirect_binary_predicate); + +class RandomAccessIteratorNotDerivedFrom { + using Self = RandomAccessIteratorNotDerivedFrom; + +public: + using value_type = int; + using difference_type = long; + using pointer = int*; + using reference = int&; + // Deliberately not using the `std::random_access_iterator_tag` category. + using iterator_category = std::bidirectional_iterator_tag; + + reference operator*() const; + reference operator[](difference_type) const; + + Self& operator++(); + Self& operator--(); + Self operator++(int); + Self operator--(int); + + Self& operator+=(difference_type); + Self& operator-=(difference_type); + friend Self operator+(Self, difference_type); + friend Self operator+(difference_type, Self); + friend Self operator-(Self, difference_type); + friend difference_type operator-(Self, Self); + + auto operator<=>(const Self&) const = default; +}; + +static_assert(std::bidirectional_iterator); +static_assert(!std::random_access_iterator); + +using RandomAccessRangeNotDerivedFrom = UncheckedRange; + +class RandomAccessIteratorBadIndex { + using Self = RandomAccessIteratorBadIndex; + +public: + using value_type = int; + using difference_type = long; + using pointer = int*; + using reference = int&; + using iterator_category = std::random_access_iterator_tag; + + reference operator*() const; + // Deliberately returning a type different from `reference`. + const int& operator[](difference_type) const; + + Self& operator++(); + Self& operator--(); + Self operator++(int); + Self operator--(int); + + Self& operator+=(difference_type); + Self& operator-=(difference_type); + friend Self operator+(Self, difference_type); + friend Self operator+(difference_type, Self); + friend Self operator-(Self, difference_type); + friend difference_type operator-(Self, Self); + + auto operator<=>(const Self&) const = default; +}; + +static_assert(std::bidirectional_iterator); +static_assert(!std::random_access_iterator); + +using RandomAccessRangeBadIndex = UncheckedRange; + +class RandomAccessIteratorBadDifferenceType { + using Self = RandomAccessIteratorBadDifferenceType; + +public: + using value_type = int; + // Deliberately use a non-integer `difference_type` + using difference_type = double; + using pointer = double*; + using reference = double&; + using iterator_category = std::random_access_iterator_tag; + + reference operator*() const; + reference operator[](difference_type) const; + + Self& operator++(); + Self& operator--(); + Self operator++(int); + Self operator--(int); + + Self& operator+=(difference_type); + Self& operator-=(difference_type); + friend Self operator+(Self, difference_type); + friend Self operator+(difference_type, Self); + friend Self operator-(Self, difference_type); + friend difference_type operator-(Self, Self); + + auto operator<=>(const Self&) const = default; +}; + +static_assert(std::regular); +static_assert(!std::weakly_incrementable); +static_assert(!std::random_access_iterator); + +template +class ComparatorNotCopyable { +public: + ComparatorNotCopyable(ComparatorNotCopyable&&) = default; + ComparatorNotCopyable& operator=(ComparatorNotCopyable&&) = default; + ComparatorNotCopyable(const ComparatorNotCopyable&) = delete; + ComparatorNotCopyable& operator=(const ComparatorNotCopyable&) = delete; + + bool operator()(Iter&, Iter&) const; +}; + +#endif // ALMOST_SATISFIES_TYPES_H diff --git a/test/sources/libcxx/support/container_test_types.h b/test/sources/libcxx/support/container_test_types.h index d8772cd56..9ea8ccd31 100644 --- a/test/sources/libcxx/support/container_test_types.h +++ b/test/sources/libcxx/support/container_test_types.h @@ -96,6 +96,7 @@ #include #include "test_macros.h" +#include "count_new.h" #if TEST_STD_VER < 11 #error This header requires C++11 or greater @@ -257,38 +258,6 @@ struct ExpectConstructGuard { } }; -//===----------------------------------------------------------------------===// -// DisableAllocationGuard -//===----------------------------------------------------------------------===// - -struct DisableAllocationGuard { - static bool g_disable_allocations; - - explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable) - { - // Don't re-disable if already disabled. - if (g_disable_allocations) m_disabled = false; - if (m_disabled) g_disable_allocations = true; - } - - void release() { - if (m_disabled) g_disable_allocations = false; - m_disabled = false; - } - - ~DisableAllocationGuard() { - release(); - } - -private: - bool m_disabled; - - DisableAllocationGuard(DisableAllocationGuard const&); - DisableAllocationGuard& operator=(DisableAllocationGuard const&); -}; - -inline bool DisableAllocationGuard::g_disable_allocations = false; - //===----------------------------------------------------------------------===// // ContainerTestAllocator //===----------------------------------------------------------------------===// @@ -335,13 +304,13 @@ class ContainerTestAllocator T* allocate(std::size_t n) { - assert(!DisableAllocationGuard::g_disable_allocations); + assert(!globalMemCounter.disable_allocations); return static_cast(::operator new(n*sizeof(T))); } void deallocate(T* p, std::size_t) { - assert(!DisableAllocationGuard::g_disable_allocations); + assert(!globalMemCounter.disable_allocations); return ::operator delete(static_cast(p)); } @@ -411,13 +380,13 @@ class ContainerTestAllocatorForMap T* allocate(std::size_t n) { - assert(!DisableAllocationGuard::g_disable_allocations); + assert(!globalMemCounter.disable_allocations); return static_cast(::operator new(n*sizeof(T))); } void deallocate(T* p, std::size_t) { - assert(!DisableAllocationGuard::g_disable_allocations); + assert(!globalMemCounter.disable_allocations); return ::operator delete(static_cast(p)); } diff --git a/test/sources/libcxx/support/count_new.h b/test/sources/libcxx/support/count_new.h new file mode 100644 index 000000000..d384df192 --- /dev/null +++ b/test/sources/libcxx/support/count_new.h @@ -0,0 +1,640 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +#ifndef COUNT_NEW_H +#define COUNT_NEW_H + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#define DISABLE_NEW_COUNT + +namespace detail +{ +[[noreturn]] inline void throw_bad_alloc_helper() { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + std::abort(); +#endif +} +} + +class MemCounter +{ +public: + // Make MemCounter super hard to accidentally construct or copy. + class MemCounterCtorArg_ {}; + explicit MemCounter(MemCounterCtorArg_) { reset(); } + +private: + MemCounter(MemCounter const &); + MemCounter & operator=(MemCounter const &); + +public: + // All checks return true when disable_checking is enabled. + static const bool disable_checking = true; + + // Disallow any allocations from occurring. Useful for testing that + // code doesn't perform any allocations. + bool disable_allocations; + + // number of allocations to throw after. Default (unsigned)-1. If + // throw_after has the default value it will never be decremented. + static const unsigned never_throw_value = static_cast(-1); + unsigned throw_after; + + int outstanding_new; + int new_called; + int delete_called; + int aligned_new_called; + int aligned_delete_called; + std::size_t last_new_size; + std::size_t last_new_align; + std::size_t last_delete_align; + + int outstanding_array_new; + int new_array_called; + int delete_array_called; + int aligned_new_array_called; + int aligned_delete_array_called; + std::size_t last_new_array_size; + std::size_t last_new_array_align; + std::size_t last_delete_array_align; + +public: + void newCalled(std::size_t s) + { + assert(disable_allocations == false); + if (throw_after == 0) { + throw_after = never_throw_value; + detail::throw_bad_alloc_helper(); + } else if (throw_after != never_throw_value) { + --throw_after; + } + ++new_called; + ++outstanding_new; + last_new_size = s; + } + + void alignedNewCalled(std::size_t s, std::size_t a) { + newCalled(s); + ++aligned_new_called; + last_new_align = a; + } + + void deleteCalled(void * p) + { + if (p) { + --outstanding_new; + ++delete_called; + } + } + + void alignedDeleteCalled(void *p, std::size_t a) { + if (p) { + deleteCalled(p); + ++aligned_delete_called; + last_delete_align = a; + } + } + + void newArrayCalled(std::size_t s) + { + assert(disable_allocations == false); + if (throw_after == 0) { + throw_after = never_throw_value; + detail::throw_bad_alloc_helper(); + } else { + // don't decrement throw_after here. newCalled will end up doing that. + } + ++outstanding_array_new; + ++new_array_called; + last_new_array_size = s; + } + + void alignedNewArrayCalled(std::size_t s, std::size_t a) { + newArrayCalled(s); + ++aligned_new_array_called; + last_new_array_align = a; + } + + void deleteArrayCalled(void * p) + { + assert(p); + --outstanding_array_new; + ++delete_array_called; + } + + void alignedDeleteArrayCalled(void * p, std::size_t a) { + deleteArrayCalled(p); + ++aligned_delete_array_called; + last_delete_array_align = a; + } + + void disableAllocations() + { + disable_allocations = true; + } + + void enableAllocations() + { + disable_allocations = false; + } + + void reset() + { + disable_allocations = false; + throw_after = never_throw_value; + + outstanding_new = 0; + new_called = 0; + delete_called = 0; + aligned_new_called = 0; + aligned_delete_called = 0; + last_new_size = 0; + last_new_align = 0; + + outstanding_array_new = 0; + new_array_called = 0; + delete_array_called = 0; + aligned_new_array_called = 0; + aligned_delete_array_called = 0; + last_new_array_size = 0; + last_new_array_align = 0; + } + +public: + bool checkOutstandingNewEq(int n) const + { + return disable_checking || n == outstanding_new; + } + + bool checkOutstandingNewLessThanOrEqual(int n) const + { + return disable_checking || outstanding_new <= n; + } + + bool checkOutstandingNewNotEq(int n) const + { + return disable_checking || n != outstanding_new; + } + + bool checkNewCalledEq(int n) const + { + return disable_checking || n == new_called; + } + + bool checkNewCalledNotEq(int n) const + { + return disable_checking || n != new_called; + } + + bool checkNewCalledGreaterThan(int n) const + { + return disable_checking || new_called > n; + } + + bool checkDeleteCalledEq(int n) const + { + return disable_checking || n == delete_called; + } + + bool checkDeleteCalledNotEq(int n) const + { + return disable_checking || n != delete_called; + } + + bool checkDeleteCalledGreaterThan(int n) const + { + return disable_checking || delete_called > n; + } + + bool checkAlignedNewCalledEq(int n) const + { + return disable_checking || n == aligned_new_called; + } + + bool checkAlignedNewCalledNotEq(int n) const + { + return disable_checking || n != aligned_new_called; + } + + bool checkAlignedNewCalledGreaterThan(int n) const + { + return disable_checking || aligned_new_called > n; + } + + bool checkAlignedDeleteCalledEq(int n) const + { + return disable_checking || n == aligned_delete_called; + } + + bool checkAlignedDeleteCalledNotEq(int n) const + { + return disable_checking || n != aligned_delete_called; + } + + bool checkLastNewSizeEq(std::size_t n) const + { + return disable_checking || n == last_new_size; + } + + bool checkLastNewSizeNotEq(std::size_t n) const + { + return disable_checking || n != last_new_size; + } + + bool checkLastNewSizeGe(std::size_t n) const + { + return disable_checking || last_new_size >= n; + } + + bool checkLastNewAlignEq(std::size_t n) const + { + return disable_checking || n == last_new_align; + } + + bool checkLastNewAlignNotEq(std::size_t n) const + { + return disable_checking || n != last_new_align; + } + + bool checkLastNewAlignGe(std::size_t n) const + { + return disable_checking || last_new_align >= n; + } + + bool checkLastDeleteAlignEq(std::size_t n) const + { + return disable_checking || n == last_delete_align; + } + + bool checkLastDeleteAlignNotEq(std::size_t n) const + { + return disable_checking || n != last_delete_align; + } + + bool checkOutstandingArrayNewEq(int n) const + { + return disable_checking || n == outstanding_array_new; + } + + bool checkOutstandingArrayNewNotEq(int n) const + { + return disable_checking || n != outstanding_array_new; + } + + bool checkNewArrayCalledEq(int n) const + { + return disable_checking || n == new_array_called; + } + + bool checkNewArrayCalledNotEq(int n) const + { + return disable_checking || n != new_array_called; + } + + bool checkDeleteArrayCalledEq(int n) const + { + return disable_checking || n == delete_array_called; + } + + bool checkDeleteArrayCalledNotEq(int n) const + { + return disable_checking || n != delete_array_called; + } + + bool checkAlignedNewArrayCalledEq(int n) const + { + return disable_checking || n == aligned_new_array_called; + } + + bool checkAlignedNewArrayCalledNotEq(int n) const + { + return disable_checking || n != aligned_new_array_called; + } + + bool checkAlignedNewArrayCalledGreaterThan(int n) const + { + return disable_checking || aligned_new_array_called > n; + } + + bool checkAlignedDeleteArrayCalledEq(int n) const + { + return disable_checking || n == aligned_delete_array_called; + } + + bool checkAlignedDeleteArrayCalledNotEq(int n) const + { + return disable_checking || n != aligned_delete_array_called; + } + + bool checkLastNewArraySizeEq(std::size_t n) const + { + return disable_checking || n == last_new_array_size; + } + + bool checkLastNewArraySizeNotEq(std::size_t n) const + { + return disable_checking || n != last_new_array_size; + } + + bool checkLastNewArrayAlignEq(std::size_t n) const + { + return disable_checking || n == last_new_array_align; + } + + bool checkLastNewArrayAlignNotEq(std::size_t n) const + { + return disable_checking || n != last_new_array_align; + } +}; + +TEST_DIAGNOSTIC_PUSH +TEST_MSVC_DIAGNOSTIC_IGNORED(4640) // '%s' construction of local static object is not thread safe (/Zc:threadSafeInit-) +inline MemCounter* getGlobalMemCounter() { + static MemCounter counter((MemCounter::MemCounterCtorArg_())); + return &counter; +} +TEST_DIAGNOSTIC_POP + +inline MemCounter &globalMemCounter = *getGlobalMemCounter(); + +#ifndef DISABLE_NEW_COUNT +// operator new(size_t[, nothrow_t]) and operator delete(size_t[, nothrow_t]) +void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { + getGlobalMemCounter()->newCalled(s); + if (s == 0) + ++s; + void* p = std::malloc(s); + if (p == nullptr) + detail::throw_bad_alloc_helper(); + return p; +} + +void* operator new(std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT { +# ifdef TEST_HAS_NO_EXCEPTIONS + getGlobalMemCounter()->newCalled(s); +# else + try { + getGlobalMemCounter()->newCalled(s); + } catch (std::bad_alloc const&) { + return nullptr; + } +# endif + return std::malloc(s); +} + +void operator delete(void* p) TEST_NOEXCEPT { + getGlobalMemCounter()->deleteCalled(p); + std::free(p); +} + +void operator delete(void* p, std::nothrow_t const&) TEST_NOEXCEPT { + getGlobalMemCounter()->deleteCalled(p); + std::free(p); +} + +// operator new[](size_t[, nothrow_t]) and operator delete[](size_t[, nothrow_t]) +void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) { + getGlobalMemCounter()->newArrayCalled(s); + if (s == 0) + s++; + void* p = std::malloc(s); + if (p == nullptr) + detail::throw_bad_alloc_helper(); + return p; +} + +void* operator new[](std::size_t s, std::nothrow_t const&) TEST_NOEXCEPT { +# ifdef TEST_HAS_NO_EXCEPTIONS + getGlobalMemCounter()->newArrayCalled(s); +# else + try { + getGlobalMemCounter()->newArrayCalled(s); + } catch (std::bad_alloc const&) { + return nullptr; + } +# endif + return std::malloc(s); +} + +void operator delete[](void* p) TEST_NOEXCEPT { + getGlobalMemCounter()->deleteArrayCalled(p); + std::free(p); +} + +void operator delete[](void* p, std::nothrow_t const&) TEST_NOEXCEPT { + getGlobalMemCounter()->deleteArrayCalled(p); + std::free(p); +} + +# ifndef TEST_HAS_NO_ALIGNED_ALLOCATION +# if defined(_LIBCPP_MSVCRT_LIKE) || (!defined(_LIBCPP_VERSION) && defined(_WIN32)) +# define USE_ALIGNED_ALLOC +# endif + +# if defined(__APPLE__) +# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) +# define TEST_HAS_NO_C11_ALIGNED_ALLOC +# endif +# elif defined(__ANDROID__) && __ANDROID_API__ < 28 +# define TEST_HAS_NO_C11_ALIGNED_ALLOC +# endif + +inline void* allocate_aligned_impl(std::size_t size, std::align_val_t align) { + const std::size_t alignment = static_cast(align); + void* ret = nullptr; +# ifdef USE_ALIGNED_ALLOC + ret = _aligned_malloc(size, alignment); +# elif TEST_STD_VER >= 17 && !defined(TEST_HAS_NO_C11_ALIGNED_ALLOC) + size_t rounded_size = (size + alignment - 1) & ~(alignment - 1); + ret = aligned_alloc(alignment, size > rounded_size ? size : rounded_size); +# else + assert(posix_memalign(&ret, std::max(alignment, sizeof(void*)), size) != EINVAL); +# endif + return ret; +} + +inline void free_aligned_impl(void* ptr, std::align_val_t) { + if (ptr) { +# ifdef USE_ALIGNED_ALLOC + ::_aligned_free(ptr); +# else + ::free(ptr); +# endif + } +} + +// operator new(size_t, align_val_t[, nothrow_t]) and operator delete(size_t, align_val_t[, nothrow_t]) +void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) { + getGlobalMemCounter()->alignedNewCalled(s, static_cast(av)); + void* p = allocate_aligned_impl(s, av); + if (p == nullptr) + detail::throw_bad_alloc_helper(); + return p; +} + +void* operator new(std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT { +# ifdef TEST_HAS_NO_EXCEPTIONS + getGlobalMemCounter()->alignedNewCalled(s, static_cast(av)); +# else + try { + getGlobalMemCounter()->alignedNewCalled(s, static_cast(av)); + } catch (std::bad_alloc const&) { + return nullptr; + } +# endif + return allocate_aligned_impl(s, av); +} + +void operator delete(void* p, std::align_val_t av) TEST_NOEXCEPT { + getGlobalMemCounter()->alignedDeleteCalled(p, static_cast(av)); + free_aligned_impl(p, av); +} + +void operator delete(void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT { + getGlobalMemCounter()->alignedDeleteCalled(p, static_cast(av)); + free_aligned_impl(p, av); +} + +// operator new[](size_t, align_val_t[, nothrow_t]) and operator delete[](size_t, align_val_t[, nothrow_t]) +void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) { + getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast(av)); + void* p = allocate_aligned_impl(s, av); + if (p == nullptr) + detail::throw_bad_alloc_helper(); + return p; +} + +void* operator new[](std::size_t s, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT { +# ifdef TEST_HAS_NO_EXCEPTIONS + getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast(av)); +# else + try { + getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast(av)); + } catch (std::bad_alloc const&) { + return nullptr; + } +# endif + return allocate_aligned_impl(s, av); +} + +void operator delete[](void* p, std::align_val_t av) TEST_NOEXCEPT { + getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast(av)); + free_aligned_impl(p, av); +} + +void operator delete[](void* p, std::align_val_t av, std::nothrow_t const&) TEST_NOEXCEPT { + getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast(av)); + free_aligned_impl(p, av); +} + +# endif // TEST_HAS_NO_ALIGNED_ALLOCATION + +#endif // DISABLE_NEW_COUNT + +struct DisableAllocationGuard { + explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable) + { + // Don't re-disable if already disabled. + if (globalMemCounter.disable_allocations == true) m_disabled = false; + if (m_disabled) globalMemCounter.disableAllocations(); + } + + void release() { + if (m_disabled) globalMemCounter.enableAllocations(); + m_disabled = false; + } + + ~DisableAllocationGuard() { + release(); + } + +private: + bool m_disabled; + + DisableAllocationGuard(DisableAllocationGuard const&); + DisableAllocationGuard& operator=(DisableAllocationGuard const&); +}; + +#if TEST_STD_VER >= 20 + +struct ConstexprDisableAllocationGuard { + TEST_CONSTEXPR_CXX14 explicit ConstexprDisableAllocationGuard(bool disable = true) : m_disabled(disable) + { + if (!TEST_IS_CONSTANT_EVALUATED) { + // Don't re-disable if already disabled. + if (globalMemCounter.disable_allocations == true) m_disabled = false; + if (m_disabled) globalMemCounter.disableAllocations(); + } else { + m_disabled = false; + } + } + + TEST_CONSTEXPR_CXX14 void release() { + if (!TEST_IS_CONSTANT_EVALUATED) { + if (m_disabled) globalMemCounter.enableAllocations(); + m_disabled = false; + } + } + + TEST_CONSTEXPR_CXX20 ~ConstexprDisableAllocationGuard() { + release(); + } + +private: + bool m_disabled; + + ConstexprDisableAllocationGuard(ConstexprDisableAllocationGuard const&); + ConstexprDisableAllocationGuard& operator=(ConstexprDisableAllocationGuard const&); +}; + +#endif + +struct RequireAllocationGuard { + explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1) + : m_req_alloc(RequireAtLeast), + m_new_count_on_init(globalMemCounter.new_called), + m_outstanding_new_on_init(globalMemCounter.outstanding_new), + m_exactly(false) + { + } + + void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; } + void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; } + + ~RequireAllocationGuard() { + assert(globalMemCounter.checkOutstandingNewEq(static_cast(m_outstanding_new_on_init))); + std::size_t Expect = m_new_count_on_init + m_req_alloc; + assert(globalMemCounter.checkNewCalledEq(static_cast(Expect)) || + (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast(Expect)))); + } + +private: + std::size_t m_req_alloc; + const std::size_t m_new_count_on_init; + const std::size_t m_outstanding_new_on_init; + bool m_exactly; + RequireAllocationGuard(RequireAllocationGuard const&); + RequireAllocationGuard& operator=(RequireAllocationGuard const&); +}; + +#endif /* COUNT_NEW_H */ diff --git a/test/sources/libcxx/support/deduction_guides_sfinae_checks.h b/test/sources/libcxx/support/deduction_guides_sfinae_checks.h index fd73fb8f3..d3ee6f2eb 100644 --- a/test/sources/libcxx/support/deduction_guides_sfinae_checks.h +++ b/test/sources/libcxx/support/deduction_guides_sfinae_checks.h @@ -120,10 +120,10 @@ constexpr void SequenceContainerDeductionGuidesSfinaeAway() { template class Container, typename InstantiatedContainer> constexpr void ContainerAdaptorDeductionGuidesSfinaeAway() { using T = typename InstantiatedContainer::value_type; - using Alloc = std::allocator; + using Alloc [[maybe_unused]] = std::allocator; using Iter = T*; - using BadIter = int; + using BadIter [[maybe_unused]] = int; using BadAlloc = Empty; // (container) -- no constraints. @@ -165,8 +165,8 @@ constexpr void ContainerAdaptorDeductionGuidesSfinaeAway() { // - "bad" input iterators (that is, a type not qualifying as an input // iterator); // - a bad allocator; -// - an allocator in place of a comparator. - +// - an allocator in place of a comparator; +// - a range not satisfying the `input_range` concept. template class Container, typename InstantiatedContainer> constexpr void AssociativeContainerDeductionGuidesSfinaeAway() { using ValueType = typename InstantiatedContainer::value_type; @@ -228,6 +228,42 @@ constexpr void AssociativeContainerDeductionGuidesSfinaeAway() { // Note: (init_list, BAD_alloc) is interpreted as (init_list, comp) instead // and fails upon instantiation. There is no requirement to SFINAE away bad // comparators. + +#if TEST_STD_VER >= 23 + using Range = RangeT; + using BadRange = BadRangeT; + + // (from_range, range) + // + // Can deduce from (from_range, range) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range) + static_assert(SFINAEs_away); + + // (from_range, range, comp) + // + // Can deduce from (from_range, _range, comp) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, comp) + static_assert(SFINAEs_away); + + // (from_range, range, comp, alloc) + // + // Can deduce from (from_range, range, comp, alloc) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, comp, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, comp, BAD_alloc) + static_assert(SFINAEs_away); + + // (from_range, range, alloc) + // + // Can deduce from (from_range, range, alloc) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, alloc) + static_assert(SFINAEs_away); + // Note: (from_range, range, BAD_alloc) is interpreted as (from_range, range, comp) instead. +#endif } // For unordered containers the deduction guides should be SFINAE'd away when @@ -237,7 +273,8 @@ constexpr void AssociativeContainerDeductionGuidesSfinaeAway() { // - a bad allocator; // - a bad hash functor (an integral type in place of a hash); // - an allocator in place of a hash functor; -// - an allocator in place of a predicate. +// - an allocator in place of a predicate; +// - a range not satisfying the `input_range` concept. template class Container, typename InstantiatedContainer> constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { using ValueType = typename InstantiatedContainer::value_type; @@ -247,7 +284,7 @@ constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { using Iter = ValueType*; using InitList = std::initializer_list; - using BadHash = int; + using BadHash = short; struct BadAlloc {}; // The only requirement in the Standard is that integral types cannot be // considered input iterators, beyond that it is unspecified. @@ -302,8 +339,7 @@ constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { LIBCPP_STATIC_ASSERT(SFINAEs_away); // Cannot deduce from (iter, iter, buckets, BAD_hash, pred, alloc) - static_assert( - SFINAEs_away); + static_assert(SFINAEs_away); // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, pred, alloc) static_assert( SFINAEs_away); @@ -341,8 +377,7 @@ constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { // Cannot deduce from (iter, iter, buckets, BAD_hash, alloc) static_assert(SFINAEs_away); // Cannot deduce from (iter, iter, buckets, ALLOC_as_hash, alloc) - static_assert( - SFINAEs_away); + static_assert(SFINAEs_away); // Note: (iter, iter, buckets, hash, BAD_alloc) is interpreted as (iter, iter, // buckets, hash, pred), which is valid because there are no requirements for // the predicate. @@ -395,6 +430,87 @@ constexpr void UnorderedContainerDeductionGuidesSfinaeAway() { // // Cannot deduce from (init_list, BAD_alloc) static_assert(SFINAEs_away); + +#if TEST_STD_VER >= 23 + using Range = RangeT; + using BadRange = BadRangeT; + + // (from_range, range) + // + // Can deduce from (from_range, range) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range) + static_assert(SFINAEs_away); + + // (from_range, range, buckets) + // + // Can deduce from (from_range, range, buckets) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets) + static_assert(SFINAEs_away); + + // (from_range, range, buckets, hash) + // + // Can deduce from (from_range, range, buckets, hash) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets, hash) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, BAD_hash) + static_assert(SFINAEs_away); + + // (from_range, range, buckets, hash, pred) + // + // Can deduce from (from_range, range, buckets, hash, pred) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets, hash, pred) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, BAD_hash, pred) + static_assert(SFINAEs_away); + + // (from_range, range, buckets, hash, pred, alloc) + // + // Can deduce from (from_range, range, buckets, hash, pred, alloc) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets, hash, pred, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, BAD_hash, pred, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, hash, pred, BAD_alloc) + static_assert(SFINAEs_away); + + // (from_range, range, buckets, alloc) + // + // Can deduce from (from_range, range, buckets, alloc) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets, alloc) + static_assert(SFINAEs_away); + // Note: (from_range, range, buckets, BAD_alloc) is interpreted as (from_range, range, buckets, hash), which is valid + // because the only requirement for the hash parameter is that it's not integral. + + // (from_range, range, alloc) + // + // Can deduce from (from_range, range, alloc) + // TODO(LWG 2713): uncomment this test once the constructor is added. + // static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, BAD_alloc) + static_assert(SFINAEs_away); + + // (from_range, range, buckets, hash, alloc) + // + // Can deduce from (from_range, range, buckets, hash, alloc) + static_assert(!SFINAEs_away); + // Cannot deduce from (from_range, BAD_range, buckets, hash, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, BAD_hash, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, ALLOC_as_hash, alloc) + static_assert(SFINAEs_away); + // Cannot deduce from (from_range, range, buckets, hash, BAD_alloc) + // Note: (from_range, range, buckets, hash, BAD_alloc) is interpreted as (from_range, range, buckets, hash, pred), + // which is valid because the only requirement for the predicate parameter is that it does not resemble an allocator. +#endif } #endif // TEST_SUPPORT_DEDUCTION_GUIDES_SFINAE_CHECKS_H diff --git a/test/sources/libcxx/support/double_move_tracker.h b/test/sources/libcxx/support/double_move_tracker.h new file mode 100644 index 000000000..6f890d45e --- /dev/null +++ b/test/sources/libcxx/support/double_move_tracker.h @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +#ifndef TEST_SUPPORT_DOUBLE_MOVE_TRACKER_H +#define TEST_SUPPORT_DOUBLE_MOVE_TRACKER_H + +#include + +#include "test_macros.h" + +namespace support { + +struct double_move_tracker { + TEST_CONSTEXPR double_move_tracker() : moved_from_(false) {} + + double_move_tracker(double_move_tracker const&) = default; + + TEST_CONSTEXPR_CXX14 double_move_tracker(double_move_tracker&& other) : moved_from_(false) { + assert(!other.moved_from_); + other.moved_from_ = true; + } + + double_move_tracker& operator=(double_move_tracker const&) = default; + + TEST_CONSTEXPR_CXX14 double_move_tracker& operator=(double_move_tracker&& other) { + assert(!other.moved_from_); + other.moved_from_ = true; + moved_from_ = false; + return *this; + } + +private: + bool moved_from_; +}; + +} // namespace support + +#endif // TEST_SUPPORT_DOUBLE_MOVE_TRACKER_H diff --git a/test/sources/libcxx/support/exception_safety_helpers.h b/test/sources/libcxx/support/exception_safety_helpers.h new file mode 100644 index 000000000..126cf0789 --- /dev/null +++ b/test/sources/libcxx/support/exception_safety_helpers.h @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_EXCEPTION_SAFETY_HELPERS_H +#define SUPPORT_EXCEPTION_SAFETY_HELPERS_H + +#include +#include +#include +#include +#include "test_macros.h" + +#if !defined(TEST_HAS_NO_EXCEPTIONS) +template +struct ThrowingCopy { + static bool throwing_enabled; + static int created_by_copying; + static int destroyed; + int x = 0; // Allows distinguishing between different instances. + + ThrowingCopy() = default; + ThrowingCopy(int value) : x(value) {} + ~ThrowingCopy() { + ++destroyed; + } + + ThrowingCopy(const ThrowingCopy& other) : x(other.x) { + ++created_by_copying; + if (throwing_enabled && created_by_copying == N) { + throw -1; + } + } + + // Defined to silence GCC warnings. For test purposes, only copy construction is considered `created_by_copying`. + ThrowingCopy& operator=(const ThrowingCopy& other) { + x = other.x; + return *this; + } + + friend bool operator==(const ThrowingCopy& lhs, const ThrowingCopy& rhs) { return lhs.x == rhs.x; } + friend bool operator<(const ThrowingCopy& lhs, const ThrowingCopy& rhs) { return lhs.x < rhs.x; } + + static void reset() { + created_by_copying = destroyed = 0; + } +}; + +template +bool ThrowingCopy::throwing_enabled = true; +template +int ThrowingCopy::created_by_copying = 0; +template +int ThrowingCopy::destroyed = 0; + +template +struct std::hash> { + std::size_t operator()(const ThrowingCopy& value) const { + return value.x; + } +}; + +template +void test_exception_safety_throwing_copy(Func&& func) { + using T = ThrowingCopy; + T::reset(); + T in[Size]; + + try { + func(in, in + Size); + assert(false); // The function call above should throw. + + } catch (int) { + assert(T::created_by_copying == ThrowOn); + assert(T::destroyed == ThrowOn - 1); // No destructor call for the partially-constructed element. + } +} + +// Destroys the container outside the user callback to avoid destroying extra elements upon throwing (which would +// complicate asserting that the expected number of elements was destroyed). +template +void test_exception_safety_throwing_copy_container(Func&& func) { + using T = ThrowingCopy; + T::throwing_enabled = false; + T in[Size]; + Container c(in, in + Size); + T::throwing_enabled = true; + T::reset(); + + try { + func(std::move(c)); + assert(false); // The function call above should throw. + + } catch (int) { + assert(T::created_by_copying == ThrowOn); + assert(T::destroyed == ThrowOn - 1); // No destructor call for the partially-constructed element. + } +} + +#endif // !defined(TEST_HAS_NO_EXCEPTIONS) + +#endif // SUPPORT_EXCEPTION_SAFETY_HELPERS_H diff --git a/test/sources/libcxx/support/from_range_associative_containers.h b/test/sources/libcxx/support/from_range_associative_containers.h new file mode 100644 index 000000000..77495c8b4 --- /dev/null +++ b/test/sources/libcxx/support/from_range_associative_containers.h @@ -0,0 +1,314 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Modified for https://github.com/morzhovets/momo project. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_FROM_RANGE_ASSOCIATIVE_CONTAINERS_H +#define SUPPORT_FROM_RANGE_ASSOCIATIVE_CONTAINERS_H + +#include +#include +#include +#include +#include +#include + +#include "exception_safety_helpers.h" +#include "from_range_helpers.h" +#include "test_compare.h" +#include "MoveOnly.h" +#include "almost_satisfies_types.h" +#include "count_new.h" +#include "test_macros.h" + +namespace libcxx_from_range_assoc { + +template +concept HasFromRangeCtr = requires (Range&& range) { + Container(std::from_range, std::forward(range)); + Container(std::from_range, std::forward(range), std::less()); + Container(std::from_range, std::forward(range), std::less(), + std::allocator()); + Container(std::from_range, std::forward(range), std::allocator()); +}; + +template