[libcxx-commits] [PATCH] D85051: Improve the representation of <compare>'s zero-only type.

Richard Smith - zygoloid via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 31 15:16:44 PDT 2020


rsmith created this revision.
rsmith added reviewers: EricWF, mclow.lists.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.
rsmith requested review of this revision.

- Use an empty struct instead of a member pointer to represent this type, so that we don't actually pass a zero member pointer at runtime.

- Mark the constructor as consteval to ensure that no code is emitted for it whenever possible.

- Add a honeypot constructor to reject all non-int arguments, so that the only argument that can arrive at the real constructor is the literal 0.

This results in better generated code, and rejecting invalid comparisons
against nullptr, 0L, and so on, while also rejecting invalid comparisons
against (1-1) and similar that would be allowed if we required an
integer constant expression with value 0.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85051

Files:
  libcxx/include/__config
  libcxx/include/compare
  libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.fail.cpp


Index: libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.fail.cpp
===================================================================
--- /dev/null
+++ libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.fail.cpp
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <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_OP(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);
+
+template <typename T>
+void test_category(T v) {
+  TEST_OP(==);  // expected-error 18 {{}}
+  TEST_OP(!=);  // expected-error 18 {{}}
+  TEST_OP(<);   // expected-error 18 {{}}
+  TEST_OP(<=);  // expected-error 18 {{}}
+  TEST_OP(>);   // expected-error 18 {{}}
+  TEST_OP(>=);  // expected-error 18 {{}}
+  TEST_OP(<=>); // expected-error 18 {{}}
+}
+
+int main(int, char**) {
+  test_category(std::strong_ordering::equivalent);
+  test_category(std::weak_ordering::equivalent);
+  test_category(std::partial_ordering::equivalent);
+  return 0;
+}
Index: libcxx/include/compare
===================================================================
--- libcxx/include/compare
+++ libcxx/include/compare
@@ -154,8 +154,13 @@
   __unordered = -127
 };
 
-struct _CmpUnspecifiedType;
-using _CmpUnspecifiedParam = void (_CmpUnspecifiedType::*)();
+struct _CmpUnspecifiedParam {
+  _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL
+  _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) {}
+
+  template<typename _Tp, typename = _VSTD::enable_if_t<!_VSTD::is_same_v<_Tp, int>>>
+  _CmpUnspecifiedParam(_Tp) = delete;
+};
 
 class  weak_equality {
   _LIBCPP_INLINE_VISIBILITY
Index: libcxx/include/__config
===================================================================
--- libcxx/include/__config
+++ libcxx/include/__config
@@ -847,6 +847,12 @@
 #  define _LIBCPP_CONSTEXPR constexpr
 #endif
 
+#ifndef __cpp_consteval
+#  define _LIBCPP_CONSTEVAL _LIBCPP_CONSTEXPR
+#else
+#  define _LIBCPP_CONSTEVAL consteval
+#endif
+
 #ifdef _LIBCPP_CXX03_LANG
 #  define _LIBCPP_DEFAULT {}
 #else


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D85051.282330.patch
Type: text/x-patch
Size: 2976 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20200731/62883fda/attachment.bin>


More information about the libcxx-commits mailing list