1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
// RUN: %clang_cc1 -std=c++2a -verify %s
struct B {};
template<typename T = void>
bool operator<(const B&, const B&) = default; // expected-error {{comparison operator template cannot be defaulted}}
struct A {
friend bool operator==(const A&, const A&) = default;
friend bool operator!=(const A&, const B&) = default; // expected-error {{parameters for defaulted equality comparison operator must have the same type (found 'const A &' vs 'const B &')}}
friend bool operator!=(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted equality comparison}}
friend bool operator<(const A&, const A&);
friend bool operator<(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted relational comparison}}
friend bool operator>(A, A) = default; // expected-warning {{implicitly deleted}}
bool operator<(const A&) const;
bool operator<=(const A&) const = default;
bool operator==(const A&) const volatile && = default; // surprisingly, OK
bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}}
bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}}
static bool operator>(const B&) = default; // expected-error {{overloaded 'operator>' cannot be a static member function}}
friend bool operator>(A, const A&) = default; // expected-error {{must have the same type}} expected-note {{would be the best match}}
template<typename T = void>
friend bool operator==(const A&, const A&) = default; // expected-error {{comparison operator template cannot be defaulted}}
template<typename T = void>
bool operator==(const A&) const = default; // expected-error {{comparison operator template cannot be defaulted}}
};
template<typename T> struct Dependent {
using U = typename T::type;
bool operator==(U) const = default; // expected-error {{found 'Dependent<Bad>::U'}}
friend bool operator==(U, U) = default; // expected-error {{found 'Dependent<Bad>::U'}}
};
struct Good { using type = const Dependent<Good>&; };
template struct Dependent<Good>;
struct Bad { using type = Dependent<Bad>&; };
template struct Dependent<Bad>; // expected-note {{in instantiation of}}
namespace std {
struct strong_ordering {
int n;
constexpr operator int() const { return n; }
static const strong_ordering equal, greater, less;
};
constexpr strong_ordering strong_ordering::equal = {0};
constexpr strong_ordering strong_ordering::greater = {1};
constexpr strong_ordering strong_ordering::less = {-1};
}
namespace LookupContext {
struct A {};
namespace N {
template <typename T> auto f() {
bool operator==(const T &, const T &);
bool operator<(const T &, const T &);
struct B {
T a;
std::strong_ordering operator<=>(const B &) const = default;
};
return B();
}
auto g() {
struct Cmp { Cmp(std::strong_ordering); };
Cmp operator<=>(const A&, const A&);
bool operator!=(const Cmp&, int);
struct B {
A a;
Cmp operator<=>(const B &) const = default;
};
return B();
}
auto h() {
struct B;
bool operator==(const B&, const B&);
bool operator!=(const B&, const B&); // expected-note 2{{best match}}
std::strong_ordering operator<=>(const B&, const B&);
bool operator<(const B&, const B&); // expected-note 2{{best match}}
bool operator<=(const B&, const B&); // expected-note 2{{best match}}
bool operator>(const B&, const B&); // expected-note 2{{best match}}
bool operator>=(const B&, const B&); // expected-note 2{{best match}}
struct B {
bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
};
return B();
}
}
namespace M {
bool operator==(const A &, const A &) = delete;
bool operator<(const A &, const A &) = delete;
bool cmp = N::f<A>() < N::f<A>();
void operator<=>(const A &, const A &) = delete;
auto cmp2 = N::g() <=> N::g();
void use_h() {
N::h() != N::h(); // expected-error {{implicitly deleted}}
N::h() < N::h(); // expected-error {{implicitly deleted}}
N::h() <= N::h(); // expected-error {{implicitly deleted}}
N::h() > N::h(); // expected-error {{implicitly deleted}}
N::h() >= N::h(); // expected-error {{implicitly deleted}}
}
}
}
namespace evil1 {
template <class T> struct Bad {
// expected-error@+1{{found 'const float &'}}
bool operator==(T const &) const = default;
Bad(int = 0);
};
template <class T> struct Weird {
// expected-error@+1{{'float' cannot be used prior to '::'}}
bool operator==(typename T::Weird_ const &) const = default;
Weird(int = 0);
};
struct evil {
using Weird_ = Weird<evil>;
};
template struct Bad<float>; // expected-note{{evil1::Bad<float>' requested}}
template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}}
template struct Weird<evil>;
} // namespace evil1
namespace P1946 {
struct A {
friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}}
};
struct B {
A a; // expected-note {{no viable three-way comparison}}
friend bool operator==(B, B) = default; // ok
friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}}
};
}
namespace p2085 {
// out-of-class defaulting
struct S1 {
bool operator==(S1 const &) const;
};
bool S1::operator==(S1 const &) const = default;
bool F1(S1 &s) {
return s != s;
}
struct S2 {
friend bool operator==(S2 const &, S2 const &);
};
bool operator==(S2 const &, S2 const &) = default;
bool F2(S2 &s) {
return s != s;
}
struct S3 {}; // expected-note{{here}}
bool operator==(S3 const &, S3 const &) = default; // expected-error{{not a friend}}
struct S4; // expected-note{{forward declaration}}
bool operator==(S4 const &, S4 const &) = default; // expected-error{{not a friend}}
struct S5; // expected-note 3{{forward declaration}}
bool operator==(S5, S5) = default; // expected-error{{not a friend}} expected-error 2{{has incomplete type}}
enum e {};
bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}}
bool operator==(e *, int *) = default; // expected-error{{must have at least one}}
} // namespace p2085
namespace p2085_2 {
template <class T> struct S6 {
// expected-error@+2{{found 'const int &'}}
// expected-error@+1{{found 'const float &'}}
bool operator==(T const &) const;
};
template <class T> bool S6<T>::operator==(T const &) const = default;
template struct S6<int>; // expected-note{{S6<int>::operator==' requested}}
void f1() {
S6<float> a;
(void)(a == 0); // expected-note{{S6<float>::operator==' requested}}
}
template <class T> struct S7 {
// expected-error@+2{{'float' cannot be used}}
// expected-error@+1{{'int' cannot be used}}
bool operator==(typename T::S7_ const &) const;
S7(int = 0);
};
template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default;
struct evil {
using S7_ = S7<evil>;
};
template struct S7<float>; // expected-note{{S7<float>' requested}}
void f2() {
S7<int> a; // expected-note{{S7<int>' requested}}
S7<evil> b;
(void)(a == 0); // expected-error{{invalid operands}}
(void)(b == 0);
}
} // namespace p2085_2
|