-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Reapply Handle templated operators with reversed arguments #72213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -324,6 +324,124 @@ 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&) { return true; } // 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&) { return true; } // 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_class_template { | ||
template<class S> | ||
struct P { | ||
template <class T> | ||
friend bool operator==(const T&, const P&) { // expected-note 2 {{candidate}} | ||
return true; | ||
} | ||
}; | ||
struct A : public P<int> {}; | ||
struct B : public P<bool> {}; | ||
bool check(A a, B b) { return a == b; } // expected-warning {{ambiguous}} | ||
} | ||
|
||
namespace friend_template_fixme { | ||
// FIXME(GH70210): This should not rewrite operator== and definitely not a hard error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just wanted to point out that this bug is worrying as it might break some code that's not easy to rewrite. I don't think we should block on that, especially given that the issue you mention requires further progress from EWG and CWG. But I would keep a close eye for people complaining about this change. |
||
struct P { | ||
template <class T> | ||
friend bool operator==(const T &, const P &) { return true; } // expected-note 2 {{candidate}} | ||
template <class T> | ||
friend bool operator!=(const T &, const P &) { return true; } // expected-note {{candidate}} | ||
}; | ||
struct A : public P {}; | ||
struct B : public P {}; | ||
bool check(A a, B b) { return a != b; } // expected-error{{ambiguous}} | ||
} | ||
|
||
namespace member_template_1 { | ||
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 member_template | ||
|
||
namespace member_template_2{ | ||
template <typename T> | ||
class Foo { | ||
public: | ||
template <typename U = T> | ||
bool operator==(const Foo& other) const; | ||
}; | ||
bool x = Foo<int>{} == Foo<int>{}; | ||
} // namespace template_member_opeqeq | ||
|
||
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 non_member_template_1 | ||
|
||
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}} | ||
} // namespace non_member_template_2 | ||
|
||
namespace class_and_member_template { | ||
template <class T> | ||
struct S { | ||
template <typename OtherT> | ||
bool operator==(const OtherT &rhs); // expected-note {{candidate}} \ | ||
// expected-note {{reversed arguments}} | ||
}; | ||
struct A : S<int> {}; | ||
struct B : S<bool> {}; | ||
bool x = A{} == B{}; // expected-warning {{ambiguous}} | ||
} // namespace class_and_member_template | ||
|
||
namespace ambiguous_case { | ||
template <class T> | ||
struct Foo {}; | ||
template <class T, class U> bool operator==(Foo<U>, Foo<T*>); // expected-note{{candidate}} | ||
template <class T, class U> bool operator==(Foo<T*>, Foo<U>); // expected-note{{candidate}} | ||
|
||
void test() { | ||
Foo<int*>() == Foo<int*>(); // expected-error{{ambiguous}} | ||
} | ||
} // namespace ambiguous_case | ||
} // namespace | ||
namespace ADL_GH68901{ | ||
namespace test1 { | ||
namespace A { | ||
|
Uh oh!
There was an error while loading. Please reload this page.