1*5e9746f5SRichard Smith // This is a test for a hack in Clang that works around a problem introduced by
2*5e9746f5SRichard Smith // DR583: it's no longer possible to compare a pointer against nullptr_t, but
3*5e9746f5SRichard Smith // we still want to permit those comparisons within less<> and friends.
4*5e9746f5SRichard Smith
5*5e9746f5SRichard Smith // RUN: %clang_cc1 -verify %s -std=c++14
6*5e9746f5SRichard Smith
7*5e9746f5SRichard Smith namespace std {
8*5e9746f5SRichard Smith template<typename T = void> struct less {};
9*5e9746f5SRichard Smith template<typename T = void> struct less_equal {};
10*5e9746f5SRichard Smith template<typename T = void> struct greater {};
11*5e9746f5SRichard Smith template<typename T = void> struct greater_equal {};
12*5e9746f5SRichard Smith
13*5e9746f5SRichard Smith template<> struct less<> {
14*5e9746f5SRichard Smith template <class T1, class T2>
operator ()std::less15*5e9746f5SRichard Smith auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u))
16*5e9746f5SRichard Smith -> decltype(t < u) {
17*5e9746f5SRichard Smith return t < u;
18*5e9746f5SRichard Smith }
19*5e9746f5SRichard Smith };
20*5e9746f5SRichard Smith
21*5e9746f5SRichard Smith template<> struct less_equal<> {
22*5e9746f5SRichard Smith template <class T1, class T2>
operator ()std::less_equal23*5e9746f5SRichard Smith auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t <= u))
24*5e9746f5SRichard Smith -> decltype(t <= u) {
25*5e9746f5SRichard Smith return t <= u;
26*5e9746f5SRichard Smith }
27*5e9746f5SRichard Smith };
28*5e9746f5SRichard Smith
29*5e9746f5SRichard Smith template<> struct greater<> {
30*5e9746f5SRichard Smith template <class T1, class T2>
operator ()std::greater31*5e9746f5SRichard Smith auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t > u))
32*5e9746f5SRichard Smith -> decltype(t > u) {
33*5e9746f5SRichard Smith return t > u;
34*5e9746f5SRichard Smith }
35*5e9746f5SRichard Smith };
36*5e9746f5SRichard Smith
37*5e9746f5SRichard Smith template<> struct greater_equal<> {
38*5e9746f5SRichard Smith template <class T1, class T2>
operator ()std::greater_equal39*5e9746f5SRichard Smith auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t >= u))
40*5e9746f5SRichard Smith -> decltype(t >= u) {
41*5e9746f5SRichard Smith return t >= u;
42*5e9746f5SRichard Smith }
43*5e9746f5SRichard Smith };
44*5e9746f5SRichard Smith
45*5e9746f5SRichard Smith template<typename = void> struct unrelated;
46*5e9746f5SRichard Smith template<> struct unrelated<> {
47*5e9746f5SRichard Smith template <class T1, class T2>
operator ()std::unrelated48*5e9746f5SRichard Smith auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) // expected-note {{substitution failure}}
49*5e9746f5SRichard Smith -> decltype(t < u) {
50*5e9746f5SRichard Smith return t < u;
51*5e9746f5SRichard Smith }
52*5e9746f5SRichard Smith };
53*5e9746f5SRichard Smith };
54*5e9746f5SRichard Smith
test(int * p)55*5e9746f5SRichard Smith void test(int *p) {
56*5e9746f5SRichard Smith using namespace std;
57*5e9746f5SRichard Smith less<>()(p, nullptr);
58*5e9746f5SRichard Smith less<>()(nullptr, p);
59*5e9746f5SRichard Smith less_equal<>()(p, nullptr);
60*5e9746f5SRichard Smith less_equal<>()(nullptr, p);
61*5e9746f5SRichard Smith greater<>()(p, nullptr);
62*5e9746f5SRichard Smith greater<>()(nullptr, p);
63*5e9746f5SRichard Smith greater_equal<>()(p, nullptr);
64*5e9746f5SRichard Smith greater_equal<>()(nullptr, p);
65*5e9746f5SRichard Smith
66*5e9746f5SRichard Smith unrelated<>()(p, nullptr); // expected-error {{no matching function}}
67*5e9746f5SRichard Smith }
68