mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 08:06:40 +00:00
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
This commit is contained in:
parent
d256797c90
commit
bf434a5f17
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user