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