aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-05-21 15:13:01 +0100
committerJonathan Wakely <jwakely@redhat.com>2024-05-22 09:43:41 +0100
commitb33f44ca6ce2dae7502ce138600e1631ffc9232c (patch)
tree9de4e86fc629e5e709cc7df148e23bbcd0322c9f
parent424f8a01df9b311250e416759ad61c00bba4af48 (diff)
downloadgcc-b33f44ca6ce2dae7502ce138600e1631ffc9232c.zip
gcc-b33f44ca6ce2dae7502ce138600e1631ffc9232c.tar.gz
gcc-b33f44ca6ce2dae7502ce138600e1631ffc9232c.tar.bz2
libstdc++: Ensure std::variant relops convert to bool [PR115145]
Ensure that the result of comparing the variant alternatives is converted to bool immediately rather than copied. libstdc++-v3/ChangeLog: PR libstdc++/115145 * include/std/variant (operator==, operator!=, operator<) (operator<=, operator>, operator>=): Add trailing-return-type to lambda expressions to trigger conversion to bool. * testsuite/20_util/variant/relops/115145.cc: New test.
-rw-r--r--libstdc++-v3/include/std/variant63
-rw-r--r--libstdc++-v3/testsuite/20_util/variant/relops/115145.cc36
2 files changed, 71 insertions, 28 deletions
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index cfb4bcd..371cbb90 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -1271,10 +1271,11 @@ namespace __detail::__variant
operator== [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l == __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l == __r;
+ });
}
template<typename... _Types>
@@ -1286,10 +1287,11 @@ namespace __detail::__variant
operator!= [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l != __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l != __r;
+ });
}
template<typename... _Types>
@@ -1301,10 +1303,11 @@ namespace __detail::__variant
operator< [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l < __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l < __r;
+ });
}
template<typename... _Types>
@@ -1316,10 +1319,11 @@ namespace __detail::__variant
operator<= [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l <= __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l <= __r;
+ });
}
template<typename... _Types>
@@ -1331,10 +1335,11 @@ namespace __detail::__variant
operator> [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l > __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l > __r;
+ });
}
template<typename... _Types>
@@ -1346,10 +1351,11 @@ namespace __detail::__variant
operator>= [[nodiscard]] (const variant<_Types...>& __lhs,
const variant<_Types...>& __rhs)
{
- return __detail::__variant::__compare(true, __lhs, __rhs,
- [](auto&& __l, auto&& __r) {
- return __l >= __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(true, __lhs, __rhs,
+ [](auto&& __l, auto&& __r) -> bool {
+ return __l >= __r;
+ });
}
constexpr bool operator==(monostate, monostate) noexcept { return true; }
@@ -1363,10 +1369,11 @@ namespace __detail::__variant
{
common_comparison_category_t<compare_three_way_result_t<_Types>...> __ret
= strong_ordering::equal;
- return __detail::__variant::__compare(__ret, __v, __w,
- [](auto&& __l, auto&& __r) {
- return __l <=> __r;
- });
+ namespace __variant = __detail::__variant;
+ return __variant::__compare(__ret, __v, __w,
+ [](auto&& __l, auto&& __r) {
+ return __l <=> __r;
+ });
}
constexpr strong_ordering
diff --git a/libstdc++-v3/testsuite/20_util/variant/relops/115145.cc b/libstdc++-v3/testsuite/20_util/variant/relops/115145.cc
new file mode 100644
index 0000000..f3443cb
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/variant/relops/115145.cc
@@ -0,0 +1,36 @@
+// { dg-do compile { target c++17 } }
+// PR libstdc++/115145
+// lambda in rewritten std::variant comparisons does not specify return type
+
+#include <variant>
+
+struct Bool {
+ operator bool() & { return val; }
+ const bool val;
+};
+
+Bool t{true}, f{false};
+
+struct A {
+ Bool& operator==(const A&) const { return t; }
+ Bool& operator!=(const A&) const { return f; }
+ Bool& operator<(const A&) const { return f; }
+ Bool& operator>(const A&) const { return f; }
+ Bool& operator<=(const A&) const { return t; }
+ Bool& operator>=(const A&) const { return t; }
+};
+
+bool check_bool(bool);
+template<typename T> void check_bool(T) = delete;
+
+void
+test_pr115145()
+{
+ std::variant<A> v;
+ check_bool( v == v );
+ check_bool( !(v != v) );
+ check_bool( !(v < v) );
+ check_bool( !(v > v) );
+ check_bool( v <= v );
+ check_bool( v >= v );
+}