@@ -324,6 +324,170 @@ bool x = X() == X(); // expected-warning {{ambiguous}}
324324}
325325} // namespace P2468R2
326326
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+
327491#else // NO_ERRORS
328492
329493namespace problem_cases {
0 commit comments