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

Barry Revzin via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 25 09:51:52 PST 2024


================
@@ -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();
----------------
brevzin wrote:

Given that clang supports this, this seems pretty nice:
```cpp
struct Cmp {
    consteval Cmp([[maybe_unused]] int zero)
        __attribute__((diagnose_if(zero != 0, "Comparisons must be against zero", "error"))) { }
    template <class T> consteval Cmp(T) = delete;
};
```
Sure it supports `(x <=> y) < (1 - 1)` but who cares, nobody's going to write that. 

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


More information about the libcxx-commits mailing list