https://github.com/pandaninjas updated https://github.com/llvm/llvm-project/pull/66315
>From ead65bfcb70be46788bc9e88c891e7ae7f91b8d7 Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Wed, 13 Sep 2023 17:38:17 -0700 Subject: [PATCH 01/14] [libc++] Prevent calling the projection more than three times --- libcxx/include/__algorithm/ranges_clamp.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 9613f7f37720a6c..ca46675eb4b3041 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,9 +37,10 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - if (std::invoke(__comp, std::invoke(__proj, __value), std::invoke(__proj, __low))) + auto &projection = std::invoke(__proj, __value); + if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __value))) + else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) return __high; else return __value; >From c18d60870ac342a95a5528396a8e0c7b91717cbb Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Wed, 13 Sep 2023 18:56:44 -0700 Subject: [PATCH 02/14] [libc++] Run clang-format on file --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index ca46675eb4b3041..3469a6419b2270f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - auto &projection = std::invoke(__proj, __value); + auto& projection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From b40e791f0e9fedbb19936851e1e71decf00331fa Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Wed, 13 Sep 2023 19:11:20 -0700 Subject: [PATCH 03/14] [libcxx] CamelCase projection and make variable name more descriptive --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3469a6419b2270f..3adb5fa828e1ee5 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,7 +37,7 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - auto& projection = std::invoke(__proj, __value); + auto& ValueProjection = std::invoke(__proj, __value); if (std::invoke(__comp, projection, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) >From a8907624defa4cc4f47520a2d93a8bd042816aa2 Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Wed, 13 Sep 2023 19:11:47 -0700 Subject: [PATCH 04/14] [libcxx] properly change variable name --- libcxx/include/__algorithm/ranges_clamp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3adb5fa828e1ee5..3d7a224b3649a3f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -38,9 +38,9 @@ struct __fn { "Bad bounds passed to std::ranges::clamp"); auto& ValueProjection = std::invoke(__proj, __value); - if (std::invoke(__comp, projection, std::invoke(__proj, __low))) + if (std::invoke(__comp, ValueProjection, std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), projection)) + else if (std::invoke(__comp, std::invoke(__proj, __high), ValueProjection)) return __high; else return __value; >From 15d3b2b79fbd61f97b0312e0913cede36b5b202d Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Thu, 14 Sep 2023 10:37:34 -0700 Subject: [PATCH 05/14] Apply suggestions from code review --- libcxx/include/__algorithm/ranges_clamp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 3d7a224b3649a3f..a97538e4c0e3f65 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,10 +37,10 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - auto& ValueProjection = std::invoke(__proj, __value); - if (std::invoke(__comp, ValueProjection, std::invoke(__proj, __low))) + auto&& __projected = std::invoke(__proj, __value); + if (std::invoke(__comp, std::forward(__projected), std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), ValueProjection)) + else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward(__projected))) return __high; else return __value; >From 67a6c91976c76fe1d399a81af8f45ecb549c62ec Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Thu, 14 Sep 2023 11:09:55 -0700 Subject: [PATCH 06/14] [libc++] add test to ensure projection is not called more than 3 times --- ..._not_called_more_than_three_times.pass.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp diff --git a/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp b/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp new file mode 100644 index 000000000000000..8d0713cd573fb34 --- /dev/null +++ b/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp @@ -0,0 +1,20 @@ +#include <algorithm> +#include <assert_macros.h> + +int Projection(const int value) +{ + static int counter = 0; + + if (counter++ == 3) + { + TEST_FAIL("projection called more than 3 times") + } + + return value; +} + +int main() +{ + TEST_DOES_NOT_THROW(std::ranges::clamp(3, 2, 4, std::ranges::less{}, &Projection)); + return 0; +} >From cf56669a8ae02b1cb0bf35ef7a37146615778008 Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Thu, 14 Sep 2023 11:10:41 -0700 Subject: [PATCH 07/14] [libc++] run clang-format on files --- ..._not_called_more_than_three_times.pass.cpp | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp b/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp index 8d0713cd573fb34..fd47de4eb390534 100644 --- a/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp @@ -1,20 +1,17 @@ #include <algorithm> #include <assert_macros.h> -int Projection(const int value) -{ - static int counter = 0; +int Projection(const int value) { + static int counter = 0; - if (counter++ == 3) - { - TEST_FAIL("projection called more than 3 times") - } + if (counter++ == 3) { + TEST_FAIL("projection called more than 3 times") + } - return value; + return value; } -int main() -{ - TEST_DOES_NOT_THROW(std::ranges::clamp(3, 2, 4, std::ranges::less{}, &Projection)); - return 0; +int main() { + std::ranges::clamp(3, 2, 4, std::ranges::less{}, &Projection); + return 0; } >From 04debcbd954222ce20ad3558f7b9bde42401ce75 Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Thu, 14 Sep 2023 17:48:53 -0700 Subject: [PATCH 08/14] [libc++] use decltype in std::forward --- libcxx/include/__algorithm/ranges_clamp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index a97538e4c0e3f65..182aed4fc53cbed 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -38,9 +38,9 @@ struct __fn { "Bad bounds passed to std::ranges::clamp"); auto&& __projected = std::invoke(__proj, __value); - if (std::invoke(__comp, std::forward(__projected), std::invoke(__proj, __low))) + if (std::invoke(__comp, std::forward<decltype(__projected)>(__projected), std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward(__projected))) + else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward<decltype(__projected)>(__projected)) return __high; else return __value; >From a377e11f8c502ca1a6557bf90d48efdec409e2a0 Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 10:56:31 -0700 Subject: [PATCH 09/14] Apply testing changes from code review --- .../alg.sorting/alg.clamp/ranges.clamp.pass.cpp | 9 ++++++++- ...on_not_called_more_than_three_times.pass.cpp | 17 ----------------- 2 files changed, 8 insertions(+), 18 deletions(-) delete mode 100644 libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp index 036552f75de4eb4..189d8cc4d886e8e 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp @@ -108,7 +108,14 @@ constexpr bool test() { auto prvalue_proj = [](const CheckDoubleMove& x) -> CheckDoubleMove { return x; }; assert(&std::ranges::clamp(val, low, high, moving_comp, prvalue_proj) == &val); } - + { // Make sure we don't call the projection more than three times per [alg.clamp], see #64717 + auto projection_function = [](const int value) -> int { + static int counter = 0; + assert(counter++ != 3); + return value; + }; + std::ranges::clamp(3, 2, 4, std::ranges::less{}, &projection_function); + } return true; } diff --git a/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp b/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp deleted file mode 100644 index fd47de4eb390534..000000000000000 --- a/libcxx/test/std/algorithms/ranges_projection_not_called_more_than_three_times.pass.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include <algorithm> -#include <assert_macros.h> - -int Projection(const int value) { - static int counter = 0; - - if (counter++ == 3) { - TEST_FAIL("projection called more than 3 times") - } - - return value; -} - -int main() { - std::ranges::clamp(3, 2, 4, std::ranges::less{}, &Projection); - return 0; -} >From 4e1857f82ffb001300d7e7e4fdd2421bf9db545a Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 11:21:49 -0700 Subject: [PATCH 10/14] [libcxx] Fix typo in ranges_clamp.h --- libcxx/include/__algorithm/ranges_clamp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index 182aed4fc53cbed..e6c86207254a19f 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -40,7 +40,7 @@ struct __fn { auto&& __projected = std::invoke(__proj, __value); if (std::invoke(__comp, std::forward<decltype(__projected)>(__projected), std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward<decltype(__projected)>(__projected)) + else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward<decltype(__projected)>(__projected))) return __high; else return __value; >From d2adb7371df960f819d40fdac1a1b28af33c180d Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 11:45:48 -0700 Subject: [PATCH 11/14] [libcxx] fix tests, apply changes from code review --- libcxx/include/__algorithm/ranges_clamp.h | 6 +++--- .../algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index e6c86207254a19f..e3bac65856fe984 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,10 +37,10 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - auto&& __projected = std::invoke(__proj, __value); - if (std::invoke(__comp, std::forward<decltype(__projected)>(__projected), std::invoke(__proj, __low))) + auto&& __projected = std::forward<decltype(__projected)>(std::invoke(__proj, __value)); + if (std::invoke(__comp, __projected), std::invoke(__proj, __low))) return __low; - else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward<decltype(__projected)>(__projected))) + else if (std::invoke(__comp, std::invoke(__proj, __high), __projected)) return __high; else return __value; diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp index 189d8cc4d886e8e..2ff685f67ac0ce3 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp @@ -109,12 +109,12 @@ constexpr bool test() { assert(&std::ranges::clamp(val, low, high, moving_comp, prvalue_proj) == &val); } { // Make sure we don't call the projection more than three times per [alg.clamp], see #64717 - auto projection_function = [](const int value) -> int { - static int counter = 0; + int counter = 0; + auto projection_function = [counter](const int value) -> int { assert(counter++ != 3); return value; }; - std::ranges::clamp(3, 2, 4, std::ranges::less{}, &projection_function); + std::ranges::clamp(3, 2, 4, std::ranges::less{}, projection_function); } return true; } >From 403ac820e7a89e12820b021ce643c713e8de17a9 Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 12:54:17 -0700 Subject: [PATCH 12/14] Apply testing changes from code review --- .../alg.clamp/ranges.clamp.pass.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp index 2ff685f67ac0ce3..8470af2620af3a1 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp @@ -116,6 +116,25 @@ constexpr bool test() { }; std::ranges::clamp(3, 2, 4, std::ranges::less{}, projection_function); } + { + struct Foo { + std::string s; + }; + + // taking by value is important here + auto comparator = [](std::string a, std::string b) { + return std::atoi(a.c_str()) < std::atoi(b.c_str()); + }; + + auto projection = [](Foo const& foo) { + return foo.s; + }; + + Foo foo{"12"}; + Foo high{"10"}; + Foo low{"1"}; + assert(std::ranges::clamp(foo, low, high, comparator, projection).s == "10"); + } return true; } >From 1f686fc8883af3af6d66216555bc85dc9931ea02 Mon Sep 17 00:00:00 2001 From: Jocelyn Castellano <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 13:32:11 -0700 Subject: [PATCH 13/14] Apply suggestions from code review Co-authored-by: Louis Dionne <ldionn...@gmail.com> --- libcxx/include/__algorithm/ranges_clamp.h | 4 ++-- .../algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libcxx/include/__algorithm/ranges_clamp.h b/libcxx/include/__algorithm/ranges_clamp.h index e3bac65856fe984..9017354667c80e3 100644 --- a/libcxx/include/__algorithm/ranges_clamp.h +++ b/libcxx/include/__algorithm/ranges_clamp.h @@ -37,8 +37,8 @@ struct __fn { _LIBCPP_ASSERT_UNCATEGORIZED(!bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))), "Bad bounds passed to std::ranges::clamp"); - auto&& __projected = std::forward<decltype(__projected)>(std::invoke(__proj, __value)); - if (std::invoke(__comp, __projected), std::invoke(__proj, __low))) + auto&& __projected = std::invoke(__proj, __value); + if (std::invoke(__comp, __projected, std::invoke(__proj, __low))) return __low; else if (std::invoke(__comp, std::invoke(__proj, __high), __projected)) return __high; diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp index 8470af2620af3a1..63f8281a2821fee 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp @@ -110,7 +110,7 @@ constexpr bool test() { } { // Make sure we don't call the projection more than three times per [alg.clamp], see #64717 int counter = 0; - auto projection_function = [counter](const int value) -> int { + auto projection_function = [&counter](const int value) -> int { assert(counter++ != 3); return value; }; >From 7a01f9551684b0d76a2fab8d8a41bd12dcce6bae Mon Sep 17 00:00:00 2001 From: PandaNinjas <ad...@malwarefight.wip.la> Date: Fri, 15 Sep 2023 14:42:24 -0700 Subject: [PATCH 14/14] Apply testing changes from code review --- .../std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp index 63f8281a2821fee..5095b366ef2a843 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp @@ -111,10 +111,11 @@ constexpr bool test() { { // Make sure we don't call the projection more than three times per [alg.clamp], see #64717 int counter = 0; auto projection_function = [&counter](const int value) -> int { - assert(counter++ != 3); + counter++; return value; }; std::ranges::clamp(3, 2, 4, std::ranges::less{}, projection_function); + assert(counter <= 3); } { struct Foo { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits