[LV] Prevent query the computeCost() when VF=1 in emitInvalidCostRemarks(). (#117288)
[llvm-project.git] / clang / test / CXX / over / over.match / over.match.funcs / over.match.oper / p3-2a.cpp
bloba574d31a0925ada52a577d16a66297189af2f8ca
1 // RUN: %clang_cc1 -std=c++2a -verify %s
2 // RUN: %clang_cc1 -std=c++2a -verify -Wall -DNO_ERRORS %s
4 #ifndef NO_ERRORS
5 namespace bullet3 {
6 // the built-in candidates include all of the candidate operator fnuctions
7 // [...] that, compared to the given operator
9 // - do not have the same parameter-type-list as any non-member candidate
11 enum E { e };
13 // Suppress both builtin operator<=>(E, E) and operator<(E, E).
14 void operator<=>(E, E); // expected-note {{while rewriting}}
15 bool cmp = e < e; // expected-error {{invalid operands to binary expression ('void' and 'int')}}
17 // None of the other bullets have anything to test here. In principle we
18 // need to suppress both builtin operator@(A, B) and operator@(B, A) when we
19 // see a user-declared reversible operator@(A, B), and we do, but that's
20 // untestable because the only built-in reversible candidates are
21 // operator<=>(E, E) and operator==(E, E) for E an enumeration type, and
22 // those are both symmetric anyway.
25 namespace bullet4 {
26 // The rewritten candidate set is determined as follows:
28 template<int> struct X {};
29 X<1> x1;
30 X<2> x2;
32 struct Y {
33 int operator<=>(X<2>) = delete; // #1member
34 bool operator==(X<2>) = delete; // #2member
36 Y y;
38 // - For the relational operators, the rewritten candidates include all
39 // non-rewritten candidates for the expression x <=> y.
40 int operator<=>(X<1>, X<2>) = delete; // #1
42 // expected-note@#1 5{{candidate function has been explicitly deleted}}
43 // expected-note@#1 5{{candidate function (with reversed parameter order) not viable: no known conversion from 'X<1>' to 'X<2>' for 1st argument}}
44 bool lt = x1 < x2; // expected-error {{selected deleted operator '<=>'}}
45 bool le = x1 <= x2; // expected-error {{selected deleted operator '<=>'}}
46 bool gt = x1 > x2; // expected-error {{selected deleted operator '<=>'}}
47 bool ge = x1 >= x2; // expected-error {{selected deleted operator '<=>'}}
48 bool cmp = x1 <=> x2; // expected-error {{selected deleted operator '<=>'}}
50 // expected-note@#1member 5{{candidate function has been explicitly deleted}}
51 // expected-note@#1 5{{candidate function not viable: no known conversion from 'Y' to 'X<1>' for 1st argument}}
52 // expected-note@#1 5{{candidate function (with reversed parameter order) not viable: no known conversion from 'Y' to 'X<2>' for 1st argument}}
53 bool mem_lt = y < x2; // expected-error {{selected deleted operator '<=>'}}
54 bool mem_le = y <= x2; // expected-error {{selected deleted operator '<=>'}}
55 bool mem_gt = y > x2; // expected-error {{selected deleted operator '<=>'}}
56 bool mem_ge = y >= x2; // expected-error {{selected deleted operator '<=>'}}
57 bool mem_cmp = y <=> x2; // expected-error {{selected deleted operator '<=>'}}
59 // - For the relational and three-way comparison operators, the rewritten
60 // candidates also include a synthesized candidate, with the order of the
61 // two parameters reversed, for each non-rewritten candidate for the
62 // expression y <=> x.
64 // expected-note@#1 5{{candidate function (with reversed parameter order) has been explicitly deleted}}
65 // expected-note@#1 5{{candidate function not viable: no known conversion from 'X<2>' to 'X<1>' for 1st argument}}
66 bool rlt = x2 < x1; // expected-error {{selected deleted operator '<=>'}}
67 bool rle = x2 <= x1; // expected-error {{selected deleted operator '<=>'}}
68 bool rgt = x2 > x1; // expected-error {{selected deleted operator '<=>'}}
69 bool rge = x2 >= x1; // expected-error {{selected deleted operator '<=>'}}
70 bool rcmp = x2 <=> x1; // expected-error {{selected deleted operator '<=>'}}
72 // expected-note@#1member 5{{candidate function (with reversed parameter order) has been explicitly deleted}}
73 // expected-note@#1 5{{candidate function not viable: no known conversion from 'X<2>' to 'X<1>' for 1st argument}}
74 // expected-note@#1 5{{candidate function (with reversed parameter order) not viable: no known conversion from 'Y' to 'X<1>' for 2nd argument}}
75 bool mem_rlt = x2 < y; // expected-error {{selected deleted operator '<=>'}}
76 bool mem_rle = x2 <= y; // expected-error {{selected deleted operator '<=>'}}
77 bool mem_rgt = x2 > y; // expected-error {{selected deleted operator '<=>'}}
78 bool mem_rge = x2 >= y; // expected-error {{selected deleted operator '<=>'}}
79 bool mem_rcmp = x2 <=> y; // expected-error {{selected deleted operator '<=>'}}
81 // For the != operator, the rewritten candidates include all non-rewritten
82 // candidates for the expression x == y
83 int operator==(X<1>, X<2>) = delete; // #2
85 // expected-note@#2 2{{candidate function has been explicitly deleted}}
86 // expected-note@#2 2{{candidate function (with reversed parameter order) not viable: no known conversion from 'X<1>' to 'X<2>' for 1st argument}}
87 bool eq = x1 == x2; // expected-error {{selected deleted operator '=='}}
88 bool ne = x1 != x2; // expected-error {{selected deleted operator '=='}}
90 // expected-note@#2member 2{{candidate function has been explicitly deleted}}
91 // expected-note@#2 2{{candidate function not viable: no known conversion from 'Y' to 'X<1>' for 1st argument}}
92 // expected-note@#2 2{{candidate function (with reversed parameter order) not viable: no known conversion from 'Y' to 'X<2>' for 1st argument}}
93 bool mem_eq = y == x2; // expected-error {{selected deleted operator '=='}}
94 bool mem_ne = y != x2; // expected-error {{selected deleted operator '=='}}
96 // For the equality operators, the rewritten candidates also include a
97 // synthesized candidate, with the order of the two parameters reversed, for
98 // each non-rewritten candidate for the expression y == x
100 // expected-note@#2 2{{candidate function (with reversed parameter order) has been explicitly deleted}}
101 // expected-note@#2 2{{candidate function not viable: no known conversion from 'X<2>' to 'X<1>' for 1st argument}}
102 bool req = x2 == x1; // expected-error {{selected deleted operator '=='}}
103 bool rne = x2 != x1; // expected-error {{selected deleted operator '=='}}
105 // expected-note@#2member 2{{candidate function (with reversed parameter order) has been explicitly deleted}}
106 // expected-note@#2 2{{candidate function not viable: no known conversion from 'X<2>' to 'X<1>' for 1st argument}}
107 // expected-note@#2 2{{candidate function (with reversed parameter order) not viable: no known conversion from 'Y' to 'X<1>' for 2nd argument}}
108 bool mem_req = x2 == y; // expected-error {{selected deleted operator '=='}}
109 bool mem_rne = x2 != y; // expected-error {{selected deleted operator '=='}}
111 // For all other operators, the rewritten candidate set is empty.
112 X<3> operator+(X<1>, X<2>) = delete; // expected-note {{no known conversion from 'X<2>' to 'X<1>'}}
113 X<3> reversed_add = x2 + x1; // expected-error {{invalid operands}}
116 namespace PR44627 {
117 namespace ADL {
118 struct type {};
119 bool operator==(type lhs, int rhs) {
120 return true;
124 bool b1 = ADL::type() == 0;
125 bool b2 = 0 == ADL::type();
128 namespace P2468R2 {
129 // Problem cases prior to P2468R2 but now intentionally rejected.
130 struct SymmetricNonConst {
131 bool operator==(const SymmetricNonConst&); // expected-note {{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
132 // expected-note@-1 {{mark 'operator==' as const or add a matching 'operator!=' to resolve the ambiguity}}
134 bool cmp_non_const = SymmetricNonConst() == SymmetricNonConst(); // expected-warning {{ambiguous}}
136 struct SymmetricConst {
137 bool operator==(const SymmetricConst&) const;
139 bool cmp_const = SymmetricConst() == SymmetricConst();
141 struct SymmetricNonConstWithoutConstRef {
142 bool operator==(SymmetricNonConstWithoutConstRef);
144 bool cmp_non_const_wo_ref = SymmetricNonConstWithoutConstRef() == SymmetricNonConstWithoutConstRef();
146 struct B {
147 virtual bool operator==(const B&) const;
149 struct D : B {
150 bool operator==(const B&) const override; // expected-note {{operator}}
152 bool cmp_base_derived = D() == D(); // expected-warning {{ambiguous}}
154 // Reversed "3" not used because we find "2".
155 // Rewrite != from "3" but warn that "chosen rewritten candidate must return cv-bool".
156 using UBool = signed char;
157 struct ICUBase {
158 virtual UBool operator==(const ICUBase&) const; // 1.
159 UBool operator!=(const ICUBase &arg) const { return !operator==(arg); } // 2.
161 struct ICUDerived : ICUBase {
162 // 3.
163 UBool operator==(const ICUBase&) const override; // expected-note {{declared here}}
165 bool cmp_icu = ICUDerived() != ICUDerived(); // expected-warning {{ISO C++20 requires return type of selected 'operator==' function for rewritten '!=' comparison to be 'bool', not 'UBool' (aka 'signed char')}}
166 // Accepted by P2468R2.
167 // 1
168 struct S {
169 bool operator==(const S&) { return true; }
170 bool operator!=(const S&) { return false; }
172 bool ts = S{} != S{};
173 // 2
174 template<typename T> struct CRTPBase {
175 bool operator==(const T&) const;
176 bool operator!=(const T&) const;
178 struct CRTP : CRTPBase<CRTP> {};
179 bool cmp_crtp = CRTP() == CRTP();
180 bool cmp_crtp2 = CRTP() != CRTP();
181 // https://github.com/llvm/llvm-project/issues/57711
182 namespace issue_57711 {
183 template <class T>
184 bool compare(T l, T r)
185 requires requires { l == r; } {
186 return l == r;
189 void test() {
190 compare(CRTP(), CRTP()); // previously this was a hard error (due to SFINAE failure).
193 // 3
194 template <bool>
195 struct GenericIterator {
196 using ConstIterator = GenericIterator<true>;
197 using NonConstIterator = GenericIterator<false>;
198 GenericIterator() = default;
199 GenericIterator(const NonConstIterator&);
201 bool operator==(ConstIterator) const;
202 bool operator!=(ConstIterator) const;
204 using Iterator = GenericIterator<false>;
206 bool biter = Iterator{} == Iterator{};
208 // Intentionally rejected by P2468R2
209 struct ImplicitInt {
210 ImplicitInt();
211 ImplicitInt(int*);
212 bool operator==(const ImplicitInt&) const; // expected-note {{candidate function (with reversed parameter order)}}
213 operator int*() const;
215 bool implicit_int = nullptr != ImplicitInt{}; // expected-error {{use of overloaded operator '!=' is ambiguous (with operand types 'std::nullptr_t' and 'ImplicitInt')}}
216 // expected-note@-1 4 {{built-in candidate operator!=}}
218 // https://eel.is/c++draft/over.match.oper#example-2
219 namespace example {
220 struct A {};
221 template<typename T> bool operator==(A, T); // 1. expected-note {{candidate function template not viable: no known conversion from 'int' to 'A' for 1st argument}}
222 bool a1 = 0 == A(); // OK, calls reversed 1
223 template<typename T> bool operator!=(A, T);
224 bool a2 = 0 == A(); // expected-error {{invalid operands to binary expression ('int' and 'A')}}
226 struct B {
227 bool operator==(const B&); // 2
228 // expected-note@-1 {{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
230 struct C : B {
231 C();
232 C(B);
233 bool operator!=(const B&); // 3
235 bool c1 = B() == C(); // OK, calls 2; reversed 2 is not a candidate because search for operator!= in C finds 3
236 bool c2 = C() == B(); // Search for operator!= inside B never finds 3. expected-warning {{ISO C++20 considers use of overloaded operator '==' (with operand types 'C' and 'B') to be ambiguous despite there being a unique best viable function}}
238 struct D {};
239 template<typename T> bool operator==(D, T); // 4
240 inline namespace N {
241 template<typename T> bool operator!=(D, T); // 5
243 bool d1 = 0 == D(); // OK, calls reversed 4; 5 does not forbid 4 as a rewrite target as "search" does not look inside inline namespaces.
244 } // namespace example
246 namespace template_tests {
247 namespace template_head_does_not_match {
248 struct A {};
249 template<typename T, class U = int> bool operator==(A, T);
250 template <class T> bool operator!=(A, T);
251 bool x = 0 == A(); // Ok. Use rewritten candidate.
254 namespace template_with_different_param_name_are_equivalent {
255 struct A {};
256 template<typename T> bool operator==(A, T); // expected-note {{candidate function template not viable: no known conversion from 'int' to 'A' for 1st argument}}
257 template <typename U> bool operator!=(A, U);
258 bool x = 0 == A(); // expected-error {{invalid operands to binary expression ('int' and 'A')}}
261 namespace template_and_non_template {
262 struct A {
263 template<typename T> bool operator==(const T&);
264 // expected-note@-1{{mark 'operator==' as const or add a matching 'operator!=' to resolve the ambiguity}}
265 // expected-note@-2{{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
267 bool a = A() == A(); // expected-warning {{ambiguous despite there being a unique best viable function}}
269 struct B {
270 template<typename T> bool operator==(const T&) const;
271 bool operator!=(const B&);
273 bool b = B() == B(); // ok. No rewrite due to const.
275 struct C {};
276 template <class T=int>
277 bool operator==(C, int);
278 bool operator!=(C, int);
279 bool c = 0 == C(); // Ok. Use rewritten candidate as the non-template 'operator!=' does not correspond to template 'operator=='
281 } // template_tests
283 namespace using_decls {
284 namespace simple {
285 struct C {};
286 bool operator==(C, int); // expected-note {{candidate function not viable: no known conversion from 'int' to 'C' for 1st argument}}
287 bool a = 0 == C(); // Ok. Use rewritten candidate.
288 namespace other_ns { bool operator!=(C, int); }
289 bool b = 0 == C(); // Ok. Use rewritten candidate.
290 using other_ns::operator!=;
291 bool c = 0 == C(); // Rewrite not possible. expected-error {{invalid operands to binary expression ('int' and 'C')}}
293 namespace templated {
294 struct C {};
295 template<typename T>
296 bool operator==(C, T); // expected-note {{candidate function template not viable: no known conversion from 'int' to 'C' for 1st argument}}
297 bool a = 0 == C(); // Ok. Use rewritten candidate.
298 namespace other_ns { template<typename T> bool operator!=(C, T); }
299 bool b = 0 == C(); // Ok. Use rewritten candidate.
300 using other_ns::operator!=;
301 bool c = 0 == C(); // Rewrite not possible. expected-error {{invalid operands to binary expression ('int' and 'C')}}
302 } // templated
303 } // using_decls
305 // FIXME(GH58185): Match requires clause.
306 namespace match_requires_clause {
307 template<int x>
308 struct A {
309 bool operator==(int) requires (x==1); // 1.
310 bool operator!=(int) requires (x==2); // 2.
312 int a1 = 0 == A<1>(); // Should not find 2 as the requires clause does not match. \
313 // expected-error {{invalid operands to binary expression ('int' and 'A<1>')}}
316 namespace static_operators {
317 // Verify no crash.
318 struct X {
319 bool operator ==(X const&); // expected-note {{ambiguity is between a regular call}}
320 // expected-note@-1 {{mark 'operator==' as const or add a matching 'operator!=' to resolve the ambiguity}}
321 static bool operator !=(X const&, X const&); // expected-error {{overloaded 'operator!=' cannot be a static member function}}
323 bool x = X() == X(); // expected-warning {{ambiguous}}
325 } // namespace P2468R2
327 namespace GH53954{
328 namespace friend_template_1 {
329 struct P {
330 template <class T>
331 friend bool operator==(const P&, const T&) { return true; } // expected-note {{candidate}} \
332 // expected-note {{ambiguous candidate function with reversed arguments}}
334 struct A : public P {};
335 struct B : public P {};
336 bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
339 namespace friend_template_2 {
340 struct P {
341 template <class T>
342 friend bool operator==(const T&, const P&) { return true; } // expected-note {{candidate}} \
343 // expected-note {{ambiguous candidate function with reversed arguments}}
345 struct A : public P {};
346 struct B : public P {};
347 bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
350 namespace friend_template_class_template {
351 template<class S>
352 struct P {
353 template <class T>
354 friend bool operator==(const T&, const P&) { // expected-note 2 {{candidate}}
355 return true;
358 struct A : public P<int> {};
359 struct B : public P<bool> {};
360 bool check(A a, B b) { return a == b; } // expected-warning {{ambiguous}}
363 namespace friend_template_fixme {
364 // FIXME(GH70210): This should not rewrite operator== and definitely not a hard error.
365 struct P {
366 template <class T>
367 friend bool operator==(const T &, const P &) { return true; } // expected-note 2 {{candidate}}
368 template <class T>
369 friend bool operator!=(const T &, const P &) { return true; } // expected-note {{candidate}}
371 struct A : public P {};
372 struct B : public P {};
373 bool check(A a, B b) { return a != b; } // expected-error{{ambiguous}}
376 namespace member_template_1 {
377 struct P {
378 template<class S>
379 bool operator==(const S &) const; // expected-note {{candidate}} \
380 // expected-note {{ambiguous candidate function with reversed arguments}}
382 struct A : public P {};
383 struct B : public P {};
384 bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
385 } // namespace member_template
387 namespace member_template_2{
388 template <typename T>
389 class Foo {
390 public:
391 template <typename U = T>
392 bool operator==(const Foo& other) const;
394 bool x = Foo<int>{} == Foo<int>{};
395 } // namespace template_member_opeqeq
397 namespace non_member_template_1 {
398 struct P {};
399 template<class S>
400 bool operator==(const P&, const S &); // expected-note {{candidate}} \
401 // expected-note {{ambiguous candidate function with reversed arguments}}
403 struct A : public P {};
404 struct B : public P {};
405 bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
407 template<class S> bool operator!=(const P&, const S &);
408 bool fine(A a, B b) { return a == b; } // Ok. Found a matching operator!=.
409 } // namespace non_member_template_1
411 namespace non_member_template_2 {
412 struct P {};
413 template<class S>
414 bool operator==(const S&, const P&); // expected-note {{candidate}} \
415 // expected-note {{ambiguous candidate function with reversed arguments}}
417 struct A : public P {};
418 struct B : public P {};
419 bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
420 } // namespace non_member_template_2
422 namespace class_and_member_template {
423 template <class T>
424 struct S {
425 template <typename OtherT>
426 bool operator==(const OtherT &rhs); // expected-note {{candidate}} \
427 // expected-note {{reversed arguments}}
429 struct A : S<int> {};
430 struct B : S<bool> {};
431 bool x = A{} == B{}; // expected-warning {{ambiguous}}
432 } // namespace class_and_member_template
434 namespace ambiguous_case {
435 template <class T>
436 struct Foo {};
437 template <class T, class U> bool operator==(Foo<U>, Foo<T*>); // expected-note{{candidate}}
438 template <class T, class U> bool operator==(Foo<T*>, Foo<U>); // expected-note{{candidate}}
440 void test() {
441 Foo<int*>() == Foo<int*>(); // expected-error{{ambiguous}}
443 } // namespace ambiguous_case
444 } // namespace
445 namespace ADL_GH68901{
446 namespace test1 {
447 namespace A {
448 struct S {};
449 bool operator==(S, int); // expected-note {{no known conversion from 'int' to 'S' for 1st argument}}
450 bool a = 0 == A::S(); // Ok. Operator!= not visible.
451 bool operator!=(S, int);
452 } // namespace A
453 bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression ('int' and 'A::S')}}
454 } // namespace test1
456 namespace test2 {
457 namespace B {
458 struct Derived {};
459 struct Base : Derived {};
461 bool operator==(Derived& a, Base& b);
462 bool operator!=(Derived& a, Base& b);
463 } // namespace B
465 bool foo() {
466 B::Base a,b;
467 return a == b;
469 } // namespace test2
472 namespace template_ {
473 namespace ns {
474 template <class T> struct A {};
475 template <class T> struct B : A<T> {};
477 template <class T> bool operator==(B<T>, A<T>); // expected-note {{candidate template ignored: could not match 'B' against 'ns::A'}}
478 template <class T> bool operator!=(B<T>, A<T>);
481 void test() {
482 ns::A<int> a;
483 ns::B<int> b;
484 a == b; // expected-error {{invalid operands to binary expression}}
486 } // namespace test3
488 namespace using_not_eq {
489 namespace A {
490 struct S {};
491 namespace B {
492 bool operator!=(S, int);
494 bool operator==(S, int); // expected-note {{candidate}}
495 using B::operator!=;
496 } // namespace A
497 bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression}}
498 } // namespace reversed_lookup_not_like_ADL
500 namespace using_eqeq {
501 namespace A {
502 struct S {};
503 namespace B {
504 bool operator==(S, int); // expected-note {{candidate}}
505 bool operator!=(S, int);
507 using B::operator==;
508 } // namespace A
509 bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression}}
512 } // namespace ADL_GH68901
514 namespace function_scope_operator_eqeq {
515 // For non-members, we always lookup for matching operator!= in the namespace scope of
516 // operator== (and not in the scope of operator==).
517 struct X { operator int(); };
518 namespace test1{
519 bool h(X x) {
520 bool operator==(X, int); // expected-note {{reversed}}
521 return x == x; // expected-warning {{ambiguous}}
524 bool g(X x) {
525 bool operator==(X, int); // expected-note {{reversed}}
526 bool operator!=(X, int);
527 return x == x; // expected-warning {{ambiguous}}
529 } // namespace test1
531 namespace test2 {
532 bool operator!=(X, int);
534 bool h(X x) {
535 bool operator==(X, int);
536 return x == x;
539 bool i(X x) {
540 bool operator==(X, int);
541 bool operator!=(X, int);
542 return x == x;
544 } // namespace test2
545 } // namespace function_scope_operator_eqeq
547 #else // NO_ERRORS
549 namespace problem_cases {
550 // We can select a reversed candidate where we used to select a non-reversed
551 // one, and in the worst case this can dramatically change the meaning of the
552 // program. Make sure we at least warn on the worst cases under -Wall.
553 struct iterator;
554 struct const_iterator {
555 const_iterator(iterator);
556 bool operator==(const const_iterator&) const;
558 struct iterator {
559 bool operator==(const const_iterator &o) const { // expected-warning {{all paths through this function will call itself}}
560 return o == *this;
564 #endif // NO_ERRORS