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