@@ -324,6 +324,170 @@ bool x = X() == X(); // expected-warning {{ambiguous}}
324
324
}
325
325
} // namespace P2468R2
326
326
327
+ namespace GH53954 {
328
+ namespace friend_template_1 {
329
+ struct P {
330
+ template <class T >
331
+ friend bool operator ==(const P&, const T&); // expected-note {{candidate}} \
332
+ // expected-note {{ambiguous candidate function with reversed arguments}}
333
+ };
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}}
337
+ }
338
+
339
+ namespace friend_template_2 {
340
+ struct P {
341
+ template <class T >
342
+ friend bool operator ==(const T&, const P&); // expected-note {{candidate}} \
343
+ // expected-note {{ambiguous candidate function with reversed arguments}}
344
+ };
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}}
348
+ }
349
+
350
+ namespace member_template {
351
+ struct P {
352
+ template <class S >
353
+ bool operator ==(const S &) const ; // expected-note {{candidate}} \
354
+ // expected-note {{ambiguous candidate function with reversed arguments}}
355
+ };
356
+ struct A : public P {};
357
+ struct B : public P {};
358
+ bool check (A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
359
+ }
360
+
361
+ namespace non_member_template_1 {
362
+ struct P {};
363
+ template <class S >
364
+ bool operator ==(const P&, const S &); // expected-note {{candidate}} \
365
+ // expected-note {{ambiguous candidate function with reversed arguments}}
366
+
367
+ struct A : public P {};
368
+ struct B : public P {};
369
+ bool check (A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
370
+
371
+ template <class S >
372
+ bool operator !=(const P&, const S &);
373
+ bool fine (A a, B b) { return a == b; } // Ok. Found a matching operator!=.
374
+ }
375
+ }
376
+
377
+
378
+ namespace ADL_GH68901 {
379
+ namespace test1 {
380
+ namespace A {
381
+ struct S {};
382
+ bool operator ==(S, int ); // expected-note {{no known conversion from 'int' to 'S' for 1st argument}}
383
+ bool a = 0 == A::S(); // Ok. Operator!= not visible.
384
+ bool operator !=(S, int );
385
+ } // namespace A
386
+ bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression ('int' and 'A::S')}}
387
+ } // namespace test1
388
+
389
+ namespace test2 {
390
+ namespace B {
391
+ struct Derived {};
392
+ struct Base : Derived {};
393
+
394
+ bool operator ==(Derived& a, Base& b);
395
+ bool operator !=(Derived& a, Base& b);
396
+ } // namespace B
397
+
398
+ bool foo () {
399
+ B::Base a,b;
400
+ return a == b;
401
+ }
402
+ } // namespace test2
403
+
404
+
405
+ namespace template_ {
406
+ namespace ns {
407
+ template <class T > struct A {};
408
+ template <class T > struct B : A<T> {};
409
+
410
+ template <class T > bool operator ==(B<T>, A<T>); // expected-note {{candidate template ignored: could not match 'B' against 'A'}}
411
+ template <class T > bool operator !=(B<T>, A<T>);
412
+ }
413
+
414
+ void test () {
415
+ ns::A<int > a;
416
+ ns::B<int > b;
417
+ a == b; // expected-error {{invalid operands to binary expression}}
418
+ }
419
+ } // namespace test3
420
+
421
+ namespace using_not_eq {
422
+ namespace A {
423
+ struct S {};
424
+ namespace B {
425
+ bool operator !=(S, int );
426
+ }
427
+ bool operator ==(S, int ); // expected-note {{candidate}}
428
+ using B::operator !=;
429
+ } // namespace A
430
+ bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression}}
431
+ } // namespace reversed_lookup_not_like_ADL
432
+
433
+ namespace using_eqeq {
434
+ namespace A {
435
+ struct S {};
436
+ namespace B {
437
+ bool operator ==(S, int ); // expected-note {{candidate}}
438
+ bool operator !=(S, int );
439
+ }
440
+ using B::operator ==;
441
+ } // namespace A
442
+ bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression}}
443
+ }
444
+
445
+ } // namespace ADL_GH68901
446
+
447
+ namespace function_scope_operator_eqeq {
448
+ // For non-members, we always lookup for matching operator!= in the namespace scope of
449
+ // operator== (and not in the scope of operator==).
450
+ struct X { operator int (); };
451
+ namespace test1 {
452
+ bool h (X x) {
453
+ bool operator ==(X, int ); // expected-note {{reversed}}
454
+ return x == x; // expected-warning {{ambiguous}}
455
+ }
456
+
457
+ bool g (X x) {
458
+ bool operator ==(X, int ); // expected-note {{reversed}}
459
+ bool operator !=(X, int );
460
+ return x == x; // expected-warning {{ambiguous}}
461
+ }
462
+ } // namespace test1
463
+
464
+ namespace test2 {
465
+ bool operator !=(X, int );
466
+
467
+ bool h (X x) {
468
+ bool operator ==(X, int );
469
+ return x == x;
470
+ }
471
+
472
+ bool i (X x) {
473
+ bool operator ==(X, int );
474
+ bool operator !=(X, int );
475
+ return x == x;
476
+ }
477
+ } // namespace test2
478
+ } // namespace function_scope_operator_eqeq
479
+
480
+ namespace non_member_template_2 {
481
+ struct P {};
482
+ template <class S >
483
+ bool operator ==(const S&, const P&); // expected-note {{candidate}} \
484
+ // expected-note {{ambiguous candidate function with reversed arguments}}
485
+
486
+ struct A : public P {};
487
+ struct B : public P {};
488
+ bool check (A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
489
+ }
490
+
327
491
#else // NO_ERRORS
328
492
329
493
namespace problem_cases {
0 commit comments