[libcxx-commits] [libcxx] 861b9ca - [libc++] Fix std::variant comparators not working on recursive instantiations (#182238)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Mar 7 01:13:38 PST 2026


Author: Nikolas Klauser
Date: 2026-03-07T10:13:34+01:00
New Revision: 861b9cacdcda23cc1c610a2f5ab1f8533bb8e621

URL: https://github.com/llvm/llvm-project/commit/861b9cacdcda23cc1c610a2f5ab1f8533bb8e621
DIFF: https://github.com/llvm/llvm-project/commit/861b9cacdcda23cc1c610a2f5ab1f8533bb8e621.diff

LOG: [libc++] Fix std::variant comparators not working on recursive instantiations (#182238)

We currently have an instantiation cycle in `variant`'s comparison
operators. This patch fixes that by replacing a `decltype(auto)` with an
explicit return type, removing the requirement to instantiate the
function in order to know the return type.

Fixes #182232

Added: 
    

Modified: 
    libcxx/include/variant
    libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/variant b/libcxx/include/variant
index 56c5efe92b642..9b2c4ee23ddcf 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -614,7 +614,8 @@ private:
   template <class _Visitor>
   struct __value_visitor {
     template <class... _Alts>
-    _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator()(_Alts&&... __alts) const {
+    _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Alts&&... __alts) const
+        -> invoke_result_t<_Visitor&&, decltype((std::forward<_Alts>(__alts).__value))...> {
       __std_visit_exhaustive_visitor_check< _Visitor, decltype((std::forward<_Alts>(__alts).__value))...>();
       return std::__invoke(std::forward<_Visitor>(__visitor), std::forward<_Alts>(__alts).__value...);
     }

diff  --git a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
index 2c00703662687..54eb1e7321ff9 100644
--- a/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.relops/relops.pass.cpp
@@ -317,6 +317,72 @@ void test_relational() {
 #endif
 }
 
+struct A1 {
+  bool operator==(const A1&) const { return true; }
+  bool operator!=(const A1&) const { return true; }
+  bool operator<(const A1&) const { return true; }
+  bool operator>(const A1&) const { return true; }
+  bool operator<=(const A1&) const { return true; }
+  bool operator>=(const A1&) const { return true; }
+};
+struct A2 {
+  bool operator==(const A2&) const { return true; }
+  bool operator!=(const A2&) const { return true; }
+  bool operator<(const A2&) const { return true; }
+  bool operator>(const A2&) const { return true; }
+  bool operator<=(const A2&) const { return true; }
+  bool operator>=(const A2&) const { return true; }
+};
+
+struct Array;
+
+using Var1 = std::variant<A1, Array>;
+using Var2 = std::variant<A2, Array>;
+
+struct Array {
+  Var1* ptr;
+
+  template <class Other>
+  friend constexpr bool operator==(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr == *rhs.ptr;
+  }
+
+  template <class Other>
+  friend constexpr bool operator!=(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr != *rhs.ptr;
+  }
+
+  template <class Other>
+  friend constexpr bool operator<(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr < *rhs.ptr;
+  }
+
+  template <class Other>
+  friend constexpr bool operator>(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr > *rhs.ptr;
+  }
+
+  template <class Other>
+  friend constexpr bool operator<=(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr <= *rhs.ptr;
+  }
+
+  template <class Other>
+  friend constexpr bool operator>=(const Array& lhs, const Other& rhs) {
+    return *lhs.ptr >= *rhs.ptr;
+  }
+};
+
+// See https://llvm.org/PR182232
+void test_recursive() {
+  (void)(Var2{} == Var2{});
+  (void)(Var2{} != Var2{});
+  (void)(Var2{} < Var2{});
+  (void)(Var2{} > Var2{});
+  (void)(Var2{} <= Var2{});
+  (void)(Var2{} >= Var2{});
+}
+
 int main(int, char**) {
   test_equality();
   test_relational();


        


More information about the libcxx-commits mailing list