From 4632706b8a61b0e8570ea2bf4847d69eab313f63 Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 26 Apr 2025 16:49:36 +0100 Subject: [PATCH 1/5] [libc++] fix flat_{multi}set insert_range --- libcxx/include/__flat_set/utils.h | 4 +++- .../flat.multiset.modifiers/insert_range.pass.cpp | 10 ++++++++++ .../flat.set/flat.set.modifiers/insert_range.pass.cpp | 10 ++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__flat_set/utils.h b/libcxx/include/__flat_set/utils.h index ed3b4c48580fb..542bfd886aef5 100644 --- a/libcxx/include/__flat_set/utils.h +++ b/libcxx/include/__flat_set/utils.h @@ -11,6 +11,7 @@ #define _LIBCPP___FLAT_SET_UTILS_H #include <__config> +#include <__iterator/iterator_traits.h> #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__type_traits/container_traits.h> @@ -60,7 +61,8 @@ struct __flat_set_utils { // C++23 Sequence Container should have insert_range member function // Note that not all Sequence Containers provide append_range. __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); - } else if constexpr (ranges::common_range<_Range>) { + } else if constexpr (ranges::common_range<_Range> && + __has_input_iterator_category>::value) { __set.__keys_.insert(__set.__keys_.end(), ranges::begin(__rng), ranges::end(__rng)); } else { for (auto&& __x : __rng) { diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp index 566be3921bf77..2f6a68fa0581a 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "MinSequenceContainer.h" @@ -85,6 +86,15 @@ void test() { MoveOnly expected[] = {1, 1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } + { + // https://github.com/llvm/llvm-project/issues/136656 + MinSequenceContainer v; + std::flat_multiset s(v); + std::istringstream ints("0 1 1 0"); + auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | + std::views::transform([](int i) { return i * i; }); + s.insert_range(r); + } } void test_exception() { diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp index 966a696c096b9..3b53ca255ceeb 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "MinSequenceContainer.h" @@ -96,6 +97,15 @@ void test() { MoveOnly expected[] = {1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } + { + // https://github.com/llvm/llvm-project/issues/136656 + MinSequenceContainer v; + std::flat_set s(v); + std::istringstream ints("0 1 1 0"); + auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | + std::views::transform([](int i) { return i * i; }); + s.insert_range(r); + } } void test_exception() { From 5c0e4691e39c5568db39cf2ce426d753a265d53b Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 26 Apr 2025 19:53:17 +0100 Subject: [PATCH 2/5] ci --- .../flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp | 2 ++ .../flat.set/flat.set.modifiers/insert_range.pass.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp index 2f6a68fa0581a..fd5fdec5e6f8d 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp @@ -86,6 +86,7 @@ void test() { MoveOnly expected[] = {1, 1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } +#ifdef _LIBCPP_HAS_LOCALIZATION { // https://github.com/llvm/llvm-project/issues/136656 MinSequenceContainer v; @@ -95,6 +96,7 @@ void test() { std::views::transform([](int i) { return i * i; }); s.insert_range(r); } +#endif } void test_exception() { diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp index 3b53ca255ceeb..fa7143cb9216f 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp @@ -97,6 +97,7 @@ void test() { MoveOnly expected[] = {1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } +#ifdef _LIBCPP_HAS_LOCALIZATION { // https://github.com/llvm/llvm-project/issues/136656 MinSequenceContainer v; @@ -106,6 +107,7 @@ void test() { std::views::transform([](int i) { return i * i; }); s.insert_range(r); } +#endif } void test_exception() { From 104c9290e652dcb12674fdbc8b0c4557206eeb97 Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sun, 27 Apr 2025 13:46:24 +0100 Subject: [PATCH 3/5] ci --- .../flat.multiset.modifiers/insert_range.pass.cpp | 5 ++++- .../flat.set/flat.set.modifiers/insert_range.pass.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp index fd5fdec5e6f8d..81196d617f279 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp @@ -86,7 +86,7 @@ void test() { MoveOnly expected[] = {1, 1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } -#ifdef _LIBCPP_HAS_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION { // https://github.com/llvm/llvm-project/issues/136656 MinSequenceContainer v; @@ -94,6 +94,9 @@ void test() { std::istringstream ints("0 1 1 0"); auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | std::views::transform([](int i) { return i * i; }); + static_assert( + ![](auto& t) { return requires { t.insert_range(r); }; }(v), + "This test is to test the case where the underlying container does not provide insert_range"); s.insert_range(r); } #endif diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp index fa7143cb9216f..7c7f094e4f62b 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp @@ -97,7 +97,7 @@ void test() { MoveOnly expected[] = {1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } -#ifdef _LIBCPP_HAS_LOCALIZATION +#if _LIBCPP_HAS_LOCALIZATION { // https://github.com/llvm/llvm-project/issues/136656 MinSequenceContainer v; @@ -105,6 +105,9 @@ void test() { std::istringstream ints("0 1 1 0"); auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | std::views::transform([](int i) { return i * i; }); + static_assert( + ![](auto& t) { return requires { t.insert_range(r); }; }(v), + "This test is to test the case where the underlying container does not provide insert_range"); s.insert_range(r); } #endif From c8952ca09a152c393b11e6088dd70e394b38a06f Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sun, 4 May 2025 14:10:54 +0100 Subject: [PATCH 4/5] move test to libcxx --- .../flat.multiset/insert_range.pass.cpp | 40 +++++++++++++++++++ .../flat.set/insert_range.pass.cpp | 40 +++++++++++++++++++ .../insert_range.pass.cpp | 15 ------- .../flat.set.modifiers/insert_range.pass.cpp | 15 ------- 4 files changed, 80 insertions(+), 30 deletions(-) create mode 100644 libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp create mode 100644 libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp new file mode 100644 index 0000000000000..6817e650df189 --- /dev/null +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: no-localization + +// + +// https://github.com/llvm/llvm-project/issues/136656 + +#include +#include +#include +#include + +#include "MinSequenceContainer.h" +#include "test_macros.h" + +void test() { + MinSequenceContainer v; + std::flat_multiset s(v); + std::istringstream ints("0 1 1 0"); + auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | + std::views::transform([](int i) { return i * i; }); + static_assert( + ![](auto& t) { return requires { t.insert_range(r); }; }(v), + "This test is to test the case where the underlying container does not provide insert_range"); + s.insert_range(r); +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp new file mode 100644 index 0000000000000..18498ed2cde8b --- /dev/null +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.set/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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: no-localization + +// + +// https://github.com/llvm/llvm-project/issues/136656 + +#include +#include +#include +#include + +#include "MinSequenceContainer.h" +#include "test_macros.h" + +void test() { + MinSequenceContainer v; + std::flat_set s(v); + std::istringstream ints("0 1 1 0"); + auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | + std::views::transform([](int i) { return i * i; }); + static_assert( + ![](auto& t) { return requires { t.insert_range(r); }; }(v), + "This test is to test the case where the underlying container does not provide insert_range"); + s.insert_range(r); +} + +int main(int, char**) { + test(); + + return 0; +} diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp index 81196d617f279..566be3921bf77 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.modifiers/insert_range.pass.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include "MinSequenceContainer.h" @@ -86,20 +85,6 @@ void test() { MoveOnly expected[] = {1, 1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } -#if _LIBCPP_HAS_LOCALIZATION - { - // https://github.com/llvm/llvm-project/issues/136656 - MinSequenceContainer v; - std::flat_multiset s(v); - std::istringstream ints("0 1 1 0"); - auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | - std::views::transform([](int i) { return i * i; }); - static_assert( - ![](auto& t) { return requires { t.insert_range(r); }; }(v), - "This test is to test the case where the underlying container does not provide insert_range"); - s.insert_range(r); - } -#endif } void test_exception() { diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp index 7c7f094e4f62b..966a696c096b9 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.modifiers/insert_range.pass.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include "MinSequenceContainer.h" @@ -97,20 +96,6 @@ void test() { MoveOnly expected[] = {1, 3, 4, 5}; assert(std::ranges::equal(m, expected)); } -#if _LIBCPP_HAS_LOCALIZATION - { - // https://github.com/llvm/llvm-project/issues/136656 - MinSequenceContainer v; - std::flat_set s(v); - std::istringstream ints("0 1 1 0"); - auto r = std::ranges::subrange(std::istream_iterator(ints), std::istream_iterator()) | - std::views::transform([](int i) { return i * i; }); - static_assert( - ![](auto& t) { return requires { t.insert_range(r); }; }(v), - "This test is to test the case where the underlying container does not provide insert_range"); - s.insert_range(r); - } -#endif } void test_exception() { From 9ad0f1e732a118150c1226d0ce21a0603f1ef0cf Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 16 May 2025 13:16:52 -0400 Subject: [PATCH 5/5] Apply suggestions from code review --- .../container.adaptors/flat.multiset/insert_range.pass.cpp | 3 +++ .../container.adaptors/flat.set/insert_range.pass.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp index 6817e650df189..3ca021c2ac650 100644 --- a/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.multiset/insert_range.pass.cpp @@ -11,6 +11,9 @@ // +// As an extension, libc++ flat containers support inserting a non forward range into +// a pre-C++23 container that doesn't provide insert_range(...), since many containers +// out there are in that situation. // https://github.com/llvm/llvm-project/issues/136656 #include diff --git a/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp b/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp index 18498ed2cde8b..8023e251ccb17 100644 --- a/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp +++ b/libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp @@ -11,6 +11,9 @@ // +// As an extension, libc++ flat containers support inserting a non forward range into +// a pre-C++23 container that doesn't provide insert_range(...), since many containers +// out there are in that situation. // https://github.com/llvm/llvm-project/issues/136656 #include