-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[libc++] Verify forward_list self-merging is a no-op #129985
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesLWG3088 requires that Closes #104942. Full diff: https://github.com/llvm/llvm-project/pull/129985.diff 5 Files Affected:
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 9ae6322b7fdbe..c0245035f60ae 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -137,7 +137,7 @@
"`LWG3593 <https://wg21.link/LWG3593>`__","Several iterators' ``base() const &`` and ``lazy_split_view::outer-iterator::value_type::end()`` missing ``noexcept``","2021-10 (Virtual)","","",""
"`LWG3595 <https://wg21.link/LWG3595>`__","Exposition-only classes proxy and postfix-proxy for ``common_iterator`` should be fully ``constexpr``","2021-10 (Virtual)","|Complete|","14",""
"","","","","",""
-"`LWG3088 <https://wg21.link/LWG3088>`__","``forward_list::merge`` behaviour unclear when passed ``*this``","2022-02 (Virtual)","","",""
+"`LWG3088 <https://wg21.link/LWG3088>`__","``forward_list::merge`` behaviour unclear when passed ``*this``","2022-02 (Virtual)","|Complete|","21",""
"`LWG3471 <https://wg21.link/LWG3471>`__","``polymorphic_allocator::allocate`` does not satisfy ``Cpp17Allocator`` requirements","2022-02 (Virtual)","","",""
"`LWG3525 <https://wg21.link/LWG3525>`__","``uses_allocator_construction_args`` fails to handle types convertible to ``pair``","2022-02 (Virtual)","","",""
"`LWG3598 <https://wg21.link/LWG3598>`__","``system_category().default_error_condition(0)`` is underspecified","2022-02 (Virtual)","","",""
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
index 6e73b2fd73726..541a5417db4e5 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
@@ -9,6 +9,7 @@
// <forward_list>
// void merge(forward_list& x);
+// If (addressof(x) == this) does nothing; otherwise ...
#include <forward_list>
#include <iterator>
@@ -109,5 +110,12 @@ int main(int, char**) {
}
#endif
+ { // Make sure self-merging does nothing.
+ int a[] = {1, 2, 3, 4, 5};
+ std::forward_list<int> c(a, a + sizeof(a) / sizeof(a[0]));
+ c.merge(c);
+ assert((c == std::forward_list<int>(a, a + sizeof(a) / sizeof(a[0]))));
+ }
+
return 0;
}
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue_pred.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue_pred.pass.cpp
index fddf9f9dc0f46..22acb2836076b 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue_pred.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue_pred.pass.cpp
@@ -9,6 +9,7 @@
// <forward_list>
// template <class Compare> void merge(forward_list& x, Compare comp);
+// If (addressof(x) == this) does nothing; otherwise ...
#include <forward_list>
#include <iterator>
@@ -91,7 +92,6 @@ int main(int, char**) {
C c3(std::begin(t3), std::end(t3));
assert(c1 == c3);
}
-
#if TEST_STD_VER >= 11
{ // Test with a different allocator.
typedef int T;
@@ -110,5 +110,12 @@ int main(int, char**) {
}
#endif
+ { // Make sure self-merging does nothing.
+ int a[] = {5, 4, 3, 2, 1};
+ std::forward_list<int> c(a, a + sizeof(a) / sizeof(a[0]));
+ c.merge(c, std::greater<int>());
+ assert((c == std::forward_list<int>(a, a + sizeof(a) / sizeof(a[0]))));
+ }
+
return 0;
}
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue.pass.cpp
index d5084eccd98da..995762e8a04e3 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue.pass.cpp
@@ -11,6 +11,7 @@
// <forward_list>
// void merge(forward_list&& x);
+// If (addressof(x) == this) does nothing; otherwise ...
#include <forward_list>
#include <functional>
@@ -102,5 +103,12 @@ int main(int, char**) {
assert(c1 == c3);
}
+ { // Make sure self-merging does nothing.
+ int a[] = {1, 2, 3, 4, 5};
+ std::forward_list<int> c(a, a + sizeof(a) / sizeof(a[0]));
+ c.merge(std::move(c));
+ assert((c == std::forward_list<int>(a, a + sizeof(a) / sizeof(a[0]))));
+ }
+
return 0;
}
diff --git a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue_pred.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue_pred.pass.cpp
index 235707c65370d..0ec466cefce2b 100644
--- a/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue_pred.pass.cpp
+++ b/libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_rvalue_pred.pass.cpp
@@ -11,6 +11,7 @@
// <forward_list>
// template <class Compare> void merge(forward_list&& x, Compare comp);
+// If (addressof(x) == this) does nothing; otherwise ...
#include <forward_list>
#include <functional>
@@ -103,5 +104,12 @@ int main(int, char**) {
assert(c1 == c3);
}
+ { // Make sure self-merging does nothing.
+ int a[] = {5, 4, 3, 2, 1};
+ std::forward_list<int> c(a, a + sizeof(a) / sizeof(a[0]));
+ c.merge(std::move(c), std::greater<int>());
+ assert((c == std::forward_list<int>(a, a + sizeof(a) / sizeof(a[0]))));
+ }
+
return 0;
}
|
libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue_pred.pass.cpp
Show resolved
Hide resolved
libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/merge_lvalue.pass.cpp
Outdated
Show resolved
Hide resolved
2bcced8 to
f05b937
Compare
LWG3088 requires that
forward_list::merge()is a no-op when passed*this, which aligns with the behavior oflist::merge. Although libc++'s implementation offorward_list::merge()already meets this requirement, there were no tests to verify this behavior. This patch adds the necessary tests to ensure that self-merging remains a no-op and prevents any future regressions on this.Closes #104942.