1*01c11569SPiotr Zegar // RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DGCC
2*01c11569SPiotr Zegar // RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DCLANG
389a1d03eSRichard
489a1d03eSRichard namespace std {
5db335d02SJens Massberg class strong_ordering;
6db335d02SJens Massberg
7db335d02SJens Massberg // Mock how STD defined unspecified parameters for the operators below.
8*01c11569SPiotr Zegar #ifdef CLANG
9db335d02SJens Massberg struct _CmpUnspecifiedParam {
10db335d02SJens Massberg consteval
_CmpUnspecifiedParamstd::_CmpUnspecifiedParam11db335d02SJens Massberg _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
12db335d02SJens Massberg };
13db335d02SJens Massberg
14*01c11569SPiotr Zegar #define UNSPECIFIED_TYPE _CmpUnspecifiedParam
15*01c11569SPiotr Zegar #endif
16*01c11569SPiotr Zegar
17*01c11569SPiotr Zegar #ifdef GCC
18*01c11569SPiotr Zegar namespace __cmp_cat {
19*01c11569SPiotr Zegar struct __unspec {
__unspecstd::__cmp_cat::__unspec20*01c11569SPiotr Zegar constexpr __unspec(__unspec*) noexcept { }
21*01c11569SPiotr Zegar };
22*01c11569SPiotr Zegar }
23*01c11569SPiotr Zegar
24*01c11569SPiotr Zegar #define UNSPECIFIED_TYPE __cmp_cat::__unspec
25*01c11569SPiotr Zegar #endif
26*01c11569SPiotr Zegar
2789a1d03eSRichard struct strong_ordering {
28db335d02SJens Massberg signed char value;
29db335d02SJens Massberg
operator ==(strong_ordering v,UNSPECIFIED_TYPE)30db335d02SJens Massberg friend constexpr bool operator==(strong_ordering v,
31*01c11569SPiotr Zegar UNSPECIFIED_TYPE) noexcept {
32db335d02SJens Massberg return v.value == 0;
33db335d02SJens Massberg }
operator <(strong_ordering v,UNSPECIFIED_TYPE)34db335d02SJens Massberg friend constexpr bool operator<(strong_ordering v,
35*01c11569SPiotr Zegar UNSPECIFIED_TYPE) noexcept {
36db335d02SJens Massberg return v.value < 0;
37db335d02SJens Massberg }
operator >(strong_ordering v,UNSPECIFIED_TYPE)38db335d02SJens Massberg friend constexpr bool operator>(strong_ordering v,
39*01c11569SPiotr Zegar UNSPECIFIED_TYPE) noexcept {
40db335d02SJens Massberg return v.value > 0;
41db335d02SJens Massberg }
operator >=(strong_ordering v,UNSPECIFIED_TYPE)42db335d02SJens Massberg friend constexpr bool operator>=(strong_ordering v,
43*01c11569SPiotr Zegar UNSPECIFIED_TYPE) noexcept {
44db335d02SJens Massberg return v.value >= 0;
45db335d02SJens Massberg }
4689a1d03eSRichard static const strong_ordering equal, greater, less;
4789a1d03eSRichard };
48*01c11569SPiotr Zegar
4989a1d03eSRichard constexpr strong_ordering strong_ordering::equal = {0};
5089a1d03eSRichard constexpr strong_ordering strong_ordering::greater = {1};
5189a1d03eSRichard constexpr strong_ordering strong_ordering::less = {-1};
5289a1d03eSRichard } // namespace std
5389a1d03eSRichard
5489a1d03eSRichard class A {
55db335d02SJens Massberg int a;
5689a1d03eSRichard public:
5789a1d03eSRichard auto operator<=>(const A &other) const = default;
58db335d02SJens Massberg // CHECK-FIXES: auto operator<=>(const A &other) const = default;
5989a1d03eSRichard };
6089a1d03eSRichard
test_cxx_rewritten_binary_ops()6189a1d03eSRichard void test_cxx_rewritten_binary_ops() {
6289a1d03eSRichard A a1, a2;
6389a1d03eSRichard bool result;
6489a1d03eSRichard // should not change next line to (a1 nullptr a2)
6589a1d03eSRichard result = (a1 < a2);
6689a1d03eSRichard // CHECK-FIXES: result = (a1 < a2);
6789a1d03eSRichard // should not change next line to (a1 nullptr a2)
6889a1d03eSRichard result = (a1 >= a2);
6989a1d03eSRichard // CHECK-FIXES: result = (a1 >= a2);
7089a1d03eSRichard int *ptr = 0;
7189a1d03eSRichard // CHECK-FIXES: int *ptr = nullptr;
7289a1d03eSRichard result = (a1 > (ptr == 0 ? a1 : a2));
7389a1d03eSRichard // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
7489a1d03eSRichard result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
7589a1d03eSRichard // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : a2));
7689a1d03eSRichard }
77db335d02SJens Massberg
testValidZero()78*01c11569SPiotr Zegar void testValidZero() {
79*01c11569SPiotr Zegar A a1, a2;
80*01c11569SPiotr Zegar auto result = a1 <=> a2;
81*01c11569SPiotr Zegar if (result < 0) {}
82*01c11569SPiotr Zegar // CHECK-FIXES: if (result < 0) {}
83*01c11569SPiotr Zegar }
84*01c11569SPiotr Zegar
85db335d02SJens Massberg template<class T1, class T2>
86db335d02SJens Massberg struct P {
87db335d02SJens Massberg T1 x1;
88db335d02SJens Massberg T2 x2;
89db335d02SJens Massberg friend auto operator<=>(const P&, const P&) = default;
90db335d02SJens Massberg // CHECK-FIXES: friend auto operator<=>(const P&, const P&) = default;
91db335d02SJens Massberg };
92db335d02SJens Massberg
foo(P<int,int> x,P<int,int> y)93db335d02SJens Massberg bool foo(P<int,int> x, P<int, int> y) { return x < y; }
94db335d02SJens Massberg // CHECK-FIXES: bool foo(P<int,int> x, P<int, int> y) { return x < y; }
95