Hi,

the attached patch fixes PR118185 (mentioned in the earlier thread about 118160). Tested on x86-64 Linux.

Thanks,
--
Giuseppe D'Angelo
From 9c61058809ac091335a5e73ad8080d8310e9942e Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
Date: Sun, 19 Jan 2025 16:30:20 +0100
Subject: [PATCH] libstdc++: perfectly forward std::ranges::clamp arguments

As reported in PR118185, std::ranges::clamp does not correctly forward
the projected value to the comparator. Add the missing forward.

libstdc++-v3/ChangeLog:

	PR libstdc++/118185
        PR libstdc++/100249
	* include/bits/ranges_algo.h (__clamp_fn): Correctly forward the
	projected value to the comparator.
	* testsuite/25_algorithms/clamp/118185.cc: New test.

Signed-off-by: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
---
 libstdc++-v3/include/bits/ranges_algo.h       |  4 +-
 .../testsuite/25_algorithms/clamp/118185.cc   | 42 +++++++++++++++++++
 2 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index e38a330d48c..bb6ab8b6b4b 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -2993,9 +2993,9 @@ namespace ranges
 					 std::__invoke(__proj, __hi),
 					 std::__invoke(__proj, __lo))));
 	auto&& __proj_val = std::__invoke(__proj, __val);
-	if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo)))
+	if (std::__invoke(__comp, std::forward<decltype(__proj_val)>(__proj_val), std::__invoke(__proj, __lo)))
 	  return __lo;
-	else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val))
+	else if (std::__invoke(__comp, std::__invoke(__proj, __hi), std::forward<decltype(__proj_val)>(__proj_val)))
 	  return __hi;
 	else
 	  return __val;
diff --git a/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc b/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc
new file mode 100644
index 00000000000..908eb708c1e
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/clamp/118185.cc
@@ -0,0 +1,42 @@
+// { dg-do compile { target c++20 } }
+
+#include <algorithm>
+#include <concepts>
+
+struct Comp
+{
+  constexpr bool operator()(const int&& x, const int&& y) { return x < y; }
+};
+
+struct Proj
+{
+  constexpr const int&& operator()(const int& x) const { return std::move(x); }
+};
+
+static_assert(std::indirect_strict_weak_order<Comp, std::projected<const int*, Proj>>);
+
+static_assert(std::ranges::clamp(+1, 0, 2, Comp{}, Proj{}) == 1);
+static_assert(std::ranges::clamp(-1, 0, 2, Comp{}, Proj{}) == 0);
+static_assert(std::ranges::clamp(10, 0, 2, Comp{}, Proj{}) == 2);
+
+
+// Testcase from PR118185
+
+struct Comp2
+{
+  constexpr bool operator()(const int&& x, const int&& y) const { return x < y; }
+  constexpr bool operator()(const int&& x, int& y) const { return x < y; }
+  constexpr bool operator()(int& x, const int&& y) const { return x < y; }
+  constexpr bool operator()(int& x, int& y) const { return x < y; }
+  constexpr bool operator()(std::same_as<const int&> auto && x, std::same_as<const int&> auto && y) const
+  {
+    return x < y;
+  }
+};
+
+static_assert(std::indirect_strict_weak_order<Comp2, std::projected<const int*, Proj>>);
+
+static_assert(std::ranges::clamp(+1, 0, 2, Comp2{}, Proj{}) == 1);
+static_assert(std::ranges::clamp(-1, 0, 2, Comp2{}, Proj{}) == 0);
+static_assert(std::ranges::clamp(10, 0, 2, Comp2{}, Proj{}) == 2);
+
-- 
2.34.1

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to