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

Richard Smith via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 29 15:44:45 PDT 2020


Author: Richard Smith
Date: 2020-09-29T15:44:05-07:00
New Revision: bf434a5f173eed4112a10e28e8a6236d48f9da07

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

LOG: Improve the representation of <compare>'s zero-only type.

* 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.

Differential Revision: https://reviews.llvm.org/D85051

Added: 
    libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp

Modified: 
    libcxx/include/__config
    libcxx/include/compare

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__config b/libcxx/include/__config
index c29fd4267f32..1b87a6b43996 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -837,6 +837,12 @@ typedef unsigned int   char32_t;
 #  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

diff  --git a/libcxx/include/compare b/libcxx/include/compare
index 717859a1e3af..c1cd81bb6fc1 100644
--- a/libcxx/include/compare
+++ b/libcxx/include/compare
@@ -154,8 +154,13 @@ enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char {
   __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

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
new file mode 100644
index 000000000000..40f6677d43c9
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/zero_type.verify.cpp
@@ -0,0 +1,60 @@
+// -*- 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(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);
+
+template <typename T>
+void test_category(T v) {
+  TEST_OP(v, ==);  // expected-error 18 {{}}
+  TEST_OP(v, !=);  // expected-error 18 {{}}
+  TEST_OP(v, <);   // expected-error 18 {{}}
+  TEST_OP(v, <=);  // expected-error 18 {{}}
+  TEST_OP(v, >);   // expected-error 18 {{}}
+  TEST_OP(v, >=);  // expected-error 18 {{}}
+  TEST_OP(v, <=>); // expected-error 18 {{}}
+
+  void(v == 0);
+  void(0 == v);
+  void(v != 0);
+  void(0 != v);
+  void(v < 0);
+  void(0 < v);
+  void(v <= 0);
+  void(0 <= v);
+  void(v > 0);
+  void(0 > v);
+  void(v >= 0);
+  void(0 >= v);
+#ifndef _LIBCPP_HAS_NO_THREE_WAY_COMPARISON
+  void(v <=> 0); // expected-error 3 {{}}
+  void(0 <=> v); // expected-error 3 {{}}
+#endif
+}
+
+int main(int, char**) {
+  test_category(std::strong_ordering::equivalent);
+  test_category(std::weak_ordering::equivalent);
+  test_category(std::partial_ordering::equivalent);
+  return 0;
+}


        


More information about the libcxx-commits mailing list