[libcxx-commits] [libcxx] [libc++] Avoid -Wzero-as-null-pointer-constant in operator<=> (PR #79465)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 19 12:11:17 PDT 2024


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/79465

>From b91b1f687c1d58d36069e0a4d2cb930271fb7e9b Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 25 Jan 2024 10:34:32 -0500
Subject: [PATCH 1/5] [libc++] Avoid -Wzero-as-null-pointer-constant in
 operator<=>

Issue #43670 describes a situation where the following comparison
will issue a warning when -Wzero-as-null-pointer-constant is enabled:

    #include <compare>
    auto b = (1 <=> 2) < 0;

This code uses operator<(strong_ordering, Unspecified), which is
specified by the Standard to only work with a literal 0. In the
library, this is achieved by constructing Unspecified from a pointer,
which works but has the downside of triggering the warning.

This patch uses an alternative implementation where we require that
the operator is used exactly with an int of value 0 (known at compile-time),
however that value can technically be an expression like `1 - 1`, which
makes us a bit less strict than what's specified in the Standard.

Fixes #43670
---
 libcxx/include/__compare/ordering.h           | 20 +++---
 .../reject-other-than-literal-zero.verify.cpp | 70 +++++++++++++++++++
 .../cmp.categories.pre/zero_type.verify.cpp   | 57 ---------------
 3 files changed, 82 insertions(+), 65 deletions(-)
 create mode 100644 libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
 delete mode 100644 libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp

diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h
index 2995d381304f0e..778cf5dab4ce56 100644
--- a/libcxx/include/__compare/ordering.h
+++ b/libcxx/include/__compare/ordering.h
@@ -30,14 +30,17 @@ class partial_ordering;
 class weak_ordering;
 class strong_ordering;
 
-template <class _Tp, class... _Args>
-inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...);
-
 struct _CmpUnspecifiedParam {
-  _LIBCPP_HIDE_FROM_ABI constexpr _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
-
-  template <class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>>
-  _CmpUnspecifiedParam(_Tp) = delete;
+  template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int>>>
+  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept {
+    // If anything other than 0 is provided, the behavior is undefined.
+    // We catch this case by making this function consteval and making the program ill-formed if
+    // a value other than 0 is provided. This technically also accepts things that are not
+    // literal 0s like `1 - 1`. The alternative is to use the fact that a pointer can be
+    // constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
+    if (__zero != 0)
+      __builtin_trap();
+  }
 };
 
 class partial_ordering {
@@ -269,7 +272,8 @@ inline constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater)
 /// The types partial_ordering, weak_ordering, and strong_ordering are
 /// collectively termed the comparison category types.
 template <class _Tp>
-concept __comparison_category = __one_of_v<_Tp, partial_ordering, weak_ordering, strong_ordering>;
+concept __comparison_category =
+    is_same_v<_Tp, partial_ordering> || is_same_v<_Tp, weak_ordering> || is_same_v<_Tp, strong_ordering>;
 
 #endif // _LIBCPP_STD_VER >= 20
 
diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
new file mode 100644
index 00000000000000..f2b30284d42a60
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// In MSVC mode, there's a slightly different number of errors printed for
+// each of these, so it doesn't add up to the exact expected count of 18.
+// XFAIL: msvc
+
+// <compare>
+
+// Ensure we reject all cases where an argument other than a literal 0 is used
+// for a comparison against a comparison category type.
+
+// Also ensure that we don't warn about providing a null pointer constant when
+// comparing an ordering type against literal 0, since one of the common
+// implementation strategies is to use a pointer as the "unspecified type".
+// ADDITIONAL_COMPILE_FLAGS: -Wzero-as-null-pointer-constant
+
+#include <compare>
+
+#include "test_macros.h"
+
+#define TEST_FAIL(v, op)                                                                                               \
+  do {                                                                                                                 \
+    void(v op 0L);                                                                                                     \
+    void(0L op v);                                                                                                     \
+    void(v op 1);                                                                                                      \
+    void(1 op v);                                                                                                      \
+    void(v op nullptr);                                                                                                \
+    void(nullptr op v);                                                                                                \
+  } while (false)
+
+#define TEST_PASS(v, op)                                                                                               \
+  do {                                                                                                                 \
+    void(v op 0);                                                                                                      \
+    void(0 op v);                                                                                                      \
+    LIBCPP_ONLY(void(v op(1 - 1)));                                                                                    \
+    LIBCPP_ONLY(void((1 - 1) op v));                                                                                   \
+  } while (false)
+
+template <typename T>
+void test_category(T v) {
+  TEST_FAIL(v, ==);  // expected-error 18 {{}}
+  TEST_FAIL(v, !=);  // expected-error 18 {{}}
+  TEST_FAIL(v, <);   // expected-error 18 {{}}
+  TEST_FAIL(v, <=);  // expected-error 18 {{}}
+  TEST_FAIL(v, >);   // expected-error 18 {{}}
+  TEST_FAIL(v, >=);  // expected-error 18 {{}}
+  TEST_FAIL(v, <=>); // expected-error 18 {{}}
+
+  TEST_PASS(v, ==);
+  TEST_PASS(v, !=);
+  TEST_PASS(v, <);
+  TEST_PASS(v, >);
+  TEST_PASS(v, <=);
+  TEST_PASS(v, >=);
+  TEST_PASS(v, <=>);
+}
+
+void f() {
+  test_category(std::strong_ordering::equivalent);
+  test_category(std::weak_ordering::equivalent);
+  test_category(std::partial_ordering::equivalent);
+}
diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp
deleted file mode 100644
index 8e3c793de4b92a..00000000000000
--- a/libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// In MSVC mode, there's a slightly different number of errors printed for
-// each of these, so it doesn't add up to the exact expected count of 18.
-// XFAIL: msvc
-
-// <compare>
-
-// Ensure we reject all cases where an argument other than a literal 0 is used
-// for a comparison against a comparison category type.
-
-#include <compare>
-
-#define TEST_FAIL(v, op)                                                       \
-  void(v op 0L);                                                               \
-  void(0L op v);                                                               \
-  void(v op nullptr);                                                          \
-  void(nullptr op v);                                                          \
-  void(v op(1 - 1));                                                           \
-  void((1 - 1) op v)
-
-#define TEST_PASS(v, op)                                                       \
-  void(v op 0);                                                                \
-  void(0 op v)
-
-template <typename T>
-void test_category(T v) {
-  TEST_FAIL(v, ==);  // expected-error 18 {{}}
-  TEST_FAIL(v, !=);  // expected-error 18 {{}}
-  TEST_FAIL(v, <);   // expected-error 18 {{}}
-  TEST_FAIL(v, <=);  // expected-error 18 {{}}
-  TEST_FAIL(v, >);   // expected-error 18 {{}}
-  TEST_FAIL(v, >=);  // expected-error 18 {{}}
-  TEST_FAIL(v, <=>); // expected-error 18 {{}}
-
-  TEST_PASS(v, ==);
-  TEST_PASS(v, !=);
-  TEST_PASS(v, <);
-  TEST_PASS(v, >);
-  TEST_PASS(v, <=);
-  TEST_PASS(v, >=);
-  TEST_PASS(v, <=>);
-}
-
-void f() {
-  test_category(std::strong_ordering::equivalent);
-  test_category(std::weak_ordering::equivalent);
-  test_category(std::partial_ordering::equivalent);
-}

>From 3da7bf5980c2c4db8c6bd13012ea6d0fa4614399 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 25 Jan 2024 15:28:09 -0500
Subject: [PATCH 2/5] Use diagnose_if and improve tests

---
 libcxx/include/__compare/ordering.h           | 19 ++++---
 libcxx/include/__config                       |  6 +++
 .../reject-other-than-literal-zero.verify.cpp | 49 +++++++++++++++----
 3 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h
index 778cf5dab4ce56..274cff61d2b288 100644
--- a/libcxx/include/__compare/ordering.h
+++ b/libcxx/include/__compare/ordering.h
@@ -31,16 +31,15 @@ class weak_ordering;
 class strong_ordering;
 
 struct _CmpUnspecifiedParam {
-  template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int>>>
-  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept {
-    // If anything other than 0 is provided, the behavior is undefined.
-    // We catch this case by making this function consteval and making the program ill-formed if
-    // a value other than 0 is provided. This technically also accepts things that are not
-    // literal 0s like `1 - 1`. The alternative is to use the fact that a pointer can be
-    // constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
-    if (__zero != 0)
-      __builtin_trap();
-  }
+  // If anything other than a literal 0 is provided, the behavior is undefined by the Standard.
+  //
+  // We handle this by making this function consteval and making the program ill-formed if
+  // a value other than 0 is provided. This technically also accepts things that are not
+  // literal 0s like `1 - 1`. The alternative is to use the fact that a pointer can be
+  // constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
+  template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int> > >
+  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept _LIBCPP_DIAGNOSE_ERROR(
+      __zero != 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types") {}
 };
 
 class partial_ordering {
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 392053a64a8dc1..9fb13450f33b56 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1137,6 +1137,12 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_DIAGNOSE_WARNING(...)
 #  endif
 
+#  if __has_attribute(__diagnose_if__)
+#    define _LIBCPP_DIAGNOSE_ERROR(...) __attribute__((__diagnose_if__(__VA_ARGS__, "error")))
+#  else
+#    define _LIBCPP_DIAGNOSE_ERROR(...)
+#  endif
+
 // Use a function like macro to imply that it must be followed by a semicolon
 #  if __has_cpp_attribute(fallthrough)
 #    define _LIBCPP_FALLTHROUGH() [[fallthrough]]
diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
index f2b30284d42a60..e0010665909389 100644
--- a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
@@ -26,16 +26,29 @@
 
 #include "test_macros.h"
 
-#define TEST_FAIL(v, op)                                                                                               \
+#define TEST_FAIL_INVALID_VALUE(v, op)                                                                                 \
   do {                                                                                                                 \
-    void(v op 0L);                                                                                                     \
-    void(0L op v);                                                                                                     \
     void(v op 1);                                                                                                      \
     void(1 op v);                                                                                                      \
+  } while (false)
+
+#define TEST_FAIL_INVALID_TYPE(v, op)                                                                                  \
+  do {                                                                                                                 \
+    void(v op 0L);                                                                                                     \
+    void(0L op v);                                                                                                     \
+    void(v op 0.0);                                                                                                    \
+    void(0.0 op v);                                                                                                    \
     void(v op nullptr);                                                                                                \
     void(nullptr op v);                                                                                                \
   } while (false)
 
+#define TEST_FAIL_NOT_COMPILE_TIME(v, op)                                                                              \
+  do {                                                                                                                 \
+    int i = 0;                                                                                                         \
+    void(v op i);                                                                                                      \
+    void(i op v);                                                                                                      \
+  } while (false)
+
 #define TEST_PASS(v, op)                                                                                               \
   do {                                                                                                                 \
     void(v op 0);                                                                                                      \
@@ -46,13 +59,29 @@
 
 template <typename T>
 void test_category(T v) {
-  TEST_FAIL(v, ==);  // expected-error 18 {{}}
-  TEST_FAIL(v, !=);  // expected-error 18 {{}}
-  TEST_FAIL(v, <);   // expected-error 18 {{}}
-  TEST_FAIL(v, <=);  // expected-error 18 {{}}
-  TEST_FAIL(v, >);   // expected-error 18 {{}}
-  TEST_FAIL(v, >=);  // expected-error 18 {{}}
-  TEST_FAIL(v, <=>); // expected-error 18 {{}}
+  TEST_FAIL_INVALID_TYPE(v, ==);  // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, !=);  // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, <);   // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, <=);  // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, >);   // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, >=);  // expected-error 18 {{invalid operands to binary expression}}
+  TEST_FAIL_INVALID_TYPE(v, <=>); // expected-error 18 {{invalid operands to binary expression}}
+
+  TEST_FAIL_INVALID_VALUE(v, ==);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, !=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, <);   // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, <=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, >);   // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, >=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
+  TEST_FAIL_INVALID_VALUE(v, <=>); // expected-error 6 {{Only literal 0 is allowed as the operand}}
+
+  TEST_FAIL_NOT_COMPILE_TIME(v, ==);  // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, !=);  // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, <);   // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, <=);  // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, >);   // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, >=);  // expected-error 6 {{call to consteval function}}
+  TEST_FAIL_NOT_COMPILE_TIME(v, <=>); // expected-error 6 {{call to consteval function}}
 
   TEST_PASS(v, ==);
   TEST_PASS(v, !=);

>From 96d64aeb0c13b266cbad7ca441aa011b7ec30bce Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 29 Jan 2024 10:56:41 -0500
Subject: [PATCH 3/5] Use __enable_if__ attribute

---
 libcxx/include/__compare/ordering.h           | 15 +++---
 libcxx/include/__config                       |  6 ---
 .../reject-other-than-literal-zero.verify.cpp | 47 +++++--------------
 3 files changed, 22 insertions(+), 46 deletions(-)

diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h
index 274cff61d2b288..bea15456b89bae 100644
--- a/libcxx/include/__compare/ordering.h
+++ b/libcxx/include/__compare/ordering.h
@@ -33,13 +33,16 @@ class strong_ordering;
 struct _CmpUnspecifiedParam {
   // If anything other than a literal 0 is provided, the behavior is undefined by the Standard.
   //
-  // We handle this by making this function consteval and making the program ill-formed if
-  // a value other than 0 is provided. This technically also accepts things that are not
-  // literal 0s like `1 - 1`. The alternative is to use the fact that a pointer can be
-  // constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
+  // The alternative to the `__enable_if__` attribute would be to use the fact that a pointer
+  // can be constructed from literal 0, but this conflicts with `-Wzero-as-null-pointer-constant`.
   template <class _Tp, class = __enable_if_t<is_same_v<_Tp, int> > >
-  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept _LIBCPP_DIAGNOSE_ERROR(
-      __zero != 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types") {}
+  _LIBCPP_HIDE_FROM_ABI consteval _CmpUnspecifiedParam(_Tp __zero) noexcept
+#  if __has_attribute(__enable_if__)
+      __attribute__((__enable_if__(
+          __zero == 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types")))
+#  endif
+  {
+  }
 };
 
 class partial_ordering {
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 9fb13450f33b56..392053a64a8dc1 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1137,12 +1137,6 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_DIAGNOSE_WARNING(...)
 #  endif
 
-#  if __has_attribute(__diagnose_if__)
-#    define _LIBCPP_DIAGNOSE_ERROR(...) __attribute__((__diagnose_if__(__VA_ARGS__, "error")))
-#  else
-#    define _LIBCPP_DIAGNOSE_ERROR(...)
-#  endif
-
 // Use a function like macro to imply that it must be followed by a semicolon
 #  if __has_cpp_attribute(fallthrough)
 #    define _LIBCPP_FALLTHROUGH() [[fallthrough]]
diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
index e0010665909389..f59f6804b54e9b 100644
--- a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
@@ -26,24 +26,19 @@
 
 #include "test_macros.h"
 
-#define TEST_FAIL_INVALID_VALUE(v, op)                                                                                 \
-  do {                                                                                                                 \
-    void(v op 1);                                                                                                      \
-    void(1 op v);                                                                                                      \
-  } while (false)
-
-#define TEST_FAIL_INVALID_TYPE(v, op)                                                                                  \
+#define TEST_FAIL(v, op)                                                                                               \
   do {                                                                                                                 \
+    /* invalid types */                                                                                                \
     void(v op 0L);                                                                                                     \
     void(0L op v);                                                                                                     \
     void(v op 0.0);                                                                                                    \
     void(0.0 op v);                                                                                                    \
     void(v op nullptr);                                                                                                \
     void(nullptr op v);                                                                                                \
-  } while (false)
-
-#define TEST_FAIL_NOT_COMPILE_TIME(v, op)                                                                              \
-  do {                                                                                                                 \
+    /* invalid value */                                                                                                \
+    void(v op 1);                                                                                                      \
+    void(1 op v);                                                                                                      \
+    /* value not known at compile-time */                                                                              \
     int i = 0;                                                                                                         \
     void(v op i);                                                                                                      \
     void(i op v);                                                                                                      \
@@ -59,29 +54,13 @@
 
 template <typename T>
 void test_category(T v) {
-  TEST_FAIL_INVALID_TYPE(v, ==);  // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, !=);  // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, <);   // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, <=);  // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, >);   // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, >=);  // expected-error 18 {{invalid operands to binary expression}}
-  TEST_FAIL_INVALID_TYPE(v, <=>); // expected-error 18 {{invalid operands to binary expression}}
-
-  TEST_FAIL_INVALID_VALUE(v, ==);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, !=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, <);   // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, <=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, >);   // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, >=);  // expected-error 6 {{Only literal 0 is allowed as the operand}}
-  TEST_FAIL_INVALID_VALUE(v, <=>); // expected-error 6 {{Only literal 0 is allowed as the operand}}
-
-  TEST_FAIL_NOT_COMPILE_TIME(v, ==);  // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, !=);  // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, <);   // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, <=);  // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, >);   // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, >=);  // expected-error 6 {{call to consteval function}}
-  TEST_FAIL_NOT_COMPILE_TIME(v, <=>); // expected-error 6 {{call to consteval function}}
+  TEST_FAIL(v, ==);  // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, !=);  // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, <);   // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, <=);  // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, >);   // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, >=);  // expected-error 30 {{invalid operands to binary expression}}
+  TEST_FAIL(v, <=>); // expected-error 30 {{invalid operands to binary expression}}
 
   TEST_PASS(v, ==);
   TEST_PASS(v, !=);

>From 3c9161f4d3b99396dbaa396a29a8bd33b55f6e6f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 15 Apr 2024 11:30:54 -0400
Subject: [PATCH 4/5] Avoid warning on GCC

---
 libcxx/include/__compare/ordering.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h
index bea15456b89bae..379f3459c681dd 100644
--- a/libcxx/include/__compare/ordering.h
+++ b/libcxx/include/__compare/ordering.h
@@ -42,6 +42,7 @@ struct _CmpUnspecifiedParam {
           __zero == 0, "Only literal 0 is allowed as the operand of a comparison with one of the ordering types")))
 #  endif
   {
+    (void)__zero;
   }
 };
 

>From 49418ba2433172fb3e379eb70924459ae3064044 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 19 Aug 2024 15:11:05 -0400
Subject: [PATCH 5/5] Remove outdated XFAIL for msvc

---
 .../reject-other-than-literal-zero.verify.cpp                 | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
index f59f6804b54e9b..b6bc4dd4f097a4 100644
--- a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp
@@ -8,10 +8,6 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
-// In MSVC mode, there's a slightly different number of errors printed for
-// each of these, so it doesn't add up to the exact expected count of 18.
-// XFAIL: msvc
-
 // <compare>
 
 // Ensure we reject all cases where an argument other than a literal 0 is used



More information about the libcxx-commits mailing list