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> 15 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> 23 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> 31 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> 39 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> 48 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 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