Use the correct namespace for looking up matching operator!= (#68922)
[platform/upstream/llvm.git] / clang / test / CXX / over / over.match / over.match.funcs / over.match.oper / p3-2a.cpp
index 5c6804e..016eaf7 100644 (file)
@@ -324,6 +324,170 @@ bool x = X() == X(); // expected-warning {{ambiguous}}
 }
 } // namespace P2468R2
 
+namespace GH53954{
+namespace friend_template_1 {
+struct P {
+    template <class T>
+    friend bool operator==(const P&, const T&); // expected-note {{candidate}} \
+                                                // expected-note {{ambiguous candidate function with reversed arguments}}
+};
+struct A : public P {};
+struct B : public P {};
+bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
+}
+
+namespace friend_template_2 {
+struct P {
+    template <class T>
+    friend bool operator==(const T&, const P&); // expected-note {{candidate}} \
+                                                // expected-note {{ambiguous candidate function with reversed arguments}}
+};
+struct A : public P {};
+struct B : public P {};
+bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
+}
+
+namespace member_template {
+struct P {
+  template<class S>
+  bool operator==(const S &) const; // expected-note {{candidate}} \
+                                    // expected-note {{ambiguous candidate function with reversed arguments}}
+};
+struct A : public P {};
+struct B : public P {};
+bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
+}
+
+namespace non_member_template_1 {
+struct P {};
+template<class S>
+bool operator==(const P&, const S &); // expected-note {{candidate}} \
+                                      // expected-note {{ambiguous candidate function with reversed arguments}}
+
+struct A : public P {};
+struct B : public P {};
+bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
+
+template<class S>
+bool operator!=(const P&, const S &);
+bool fine(A a, B b) { return a == b; } // Ok. Found a matching operator!=.
+}
+}
+
+
+namespace ADL_GH68901{
+namespace test1 {
+namespace A {
+struct S {};
+bool operator==(S, int); // expected-note {{no known conversion from 'int' to 'S' for 1st argument}}
+bool a = 0 == A::S(); // Ok. Operator!= not visible.
+bool operator!=(S, int);
+} // namespace A
+bool a = 0 == A::S(); // expected-error {{invalid operands to binary expression ('int' and 'A::S')}}
+} // namespace test1
+
+namespace test2 {
+namespace B {
+struct Derived {};
+struct Base : Derived {};
+
+bool operator==(Derived& a, Base& b);
+bool operator!=(Derived& a, Base& b);
+}  // namespace B
+
+bool foo() {
+  B::Base a,b;
+  return a == b;
+}
+} // namespace test2
+
+
+namespace template_ {
+namespace ns {
+template <class T> struct A {};
+template <class T> struct B : A<T> {};
+
+template <class T> bool operator==(B<T>, A<T>); // expected-note {{candidate template ignored: could not match 'B' against 'A'}}
+template <class T> bool operator!=(B<T>, A<T>);
+}
+
+void test() {
+    ns::A<int> a;
+    ns::B<int> b;
+    a == b; // expected-error {{invalid operands to binary expression}}
+}
+} // namespace test3
+
+namespace using_not_eq {
+namespace A {
+struct S {};
+namespace B {
+bool operator!=(S, int);
+}
+bool operator==(S, int); // expected-note {{candidate}}
+using B::operator!=;
+}  // namespace A
+bool a = 0 == A::S();  // expected-error {{invalid operands to binary expression}}
+} // namespace reversed_lookup_not_like_ADL
+
+namespace using_eqeq {
+namespace A {
+struct S {};
+namespace B {
+bool operator==(S, int); // expected-note {{candidate}}
+bool operator!=(S, int);
+}
+using B::operator==;
+}  // namespace A
+bool a = 0 == A::S();  // expected-error {{invalid operands to binary expression}}
+}
+
+} //namespace ADL_GH68901
+
+namespace function_scope_operator_eqeq {
+// For non-members, we always lookup for matching operator!= in the namespace scope of
+// operator== (and not in the scope of operator==).
+struct X { operator int(); };
+namespace test1{
+bool h(X x) {
+  bool operator==(X, int); // expected-note {{reversed}}
+  return x == x; // expected-warning {{ambiguous}}
+}
+
+bool g(X x) {
+  bool operator==(X, int); // expected-note {{reversed}}
+  bool operator!=(X, int);
+  return x == x;  // expected-warning {{ambiguous}}
+}
+} // namespace test1
+
+namespace test2 {
+bool operator!=(X, int);
+
+bool h(X x) {
+  bool operator==(X, int);
+  return x == x;
+}
+
+bool i(X x) {
+  bool operator==(X, int);
+  bool operator!=(X, int);
+  return x == x;
+}
+} // namespace test2
+} // namespace function_scope_operator_eqeq
+
+namespace non_member_template_2 {
+struct P {};
+template<class S>
+bool operator==(const S&, const P&); // expected-note {{candidate}} \
+                                     // expected-note {{ambiguous candidate function with reversed arguments}}
+
+struct A : public P {};
+struct B : public P {};
+bool check(A a, B b) { return a == b; } // expected-warning {{use of overloaded operator '==' (with operand types 'A' and 'B') to be ambiguous}}
+}
+
 #else // NO_ERRORS
 
 namespace problem_cases {