forked from OSchip/llvm-project
Fix a small bug in the way we handle builtin candidates for
relational operators of enumeration type. From the gcc testsuite. llvm-svn: 164171
This commit is contained in:
parent
e115af2777
commit
14f082b69d
|
@ -6790,17 +6790,16 @@ public:
|
|||
// bool operator==(T, T);
|
||||
// bool operator!=(T, T);
|
||||
void addRelationalPointerOrEnumeralOverloads() {
|
||||
// C++ [over.built]p1:
|
||||
// If there is a user-written candidate with the same name and parameter
|
||||
// types as a built-in candidate operator function, the built-in operator
|
||||
// function is hidden and is not included in the set of candidate
|
||||
// functions.
|
||||
// C++ [over.match.oper]p3:
|
||||
// [...]the built-in candidates include all of the candidate operator
|
||||
// functions defined in 13.6 that, compared to the given operator, [...]
|
||||
// do not have the same parameter-type-list as any non-template non-member
|
||||
// candidate.
|
||||
//
|
||||
// The text is actually in a note, but if we don't implement it then we end
|
||||
// up with ambiguities when the user provides an overloaded operator for
|
||||
// an enumeration type. Note that only enumeration types have this problem,
|
||||
// so we track which enumeration types we've seen operators for. Also, the
|
||||
// only other overloaded operator with enumeration argumenst, operator=,
|
||||
// Note that in practice, this only affects enumeration types because there
|
||||
// aren't any built-in candidates of record type, and a user-defined operator
|
||||
// must have an operand of record or enumeration type. Also, the only other
|
||||
// overloaded operator with enumeration arguments, operator=,
|
||||
// cannot be overloaded for enumeration types, so this is the only place
|
||||
// where we must suppress candidates like this.
|
||||
llvm::DenseSet<std::pair<CanQualType, CanQualType> >
|
||||
|
@ -6815,6 +6814,9 @@ public:
|
|||
if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
|
||||
continue;
|
||||
|
||||
if (C->Function->isFunctionTemplateSpecialization())
|
||||
continue;
|
||||
|
||||
QualType FirstParamType =
|
||||
C->Function->getParamDecl(0)->getType().getUnqualifiedType();
|
||||
QualType SecondParamType =
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
enum E1 { one };
|
||||
enum E2 { two };
|
||||
|
||||
bool operator >= (E1, E1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator >= (E1, const E2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool test(E1 a, E1 b, E2 c) {
|
||||
return a >= b || a >= c;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
||||
|
||||
// This is specifically testing the bullet:
|
||||
// "do not have the same parameter-type-list as any non-template
|
||||
// non-member candidate."
|
||||
// The rest is sort of hard to test separately.
|
||||
|
||||
enum E1 { one };
|
||||
enum E2 { two };
|
||||
|
||||
struct A;
|
||||
|
||||
A operator >= (E1, E1);
|
||||
A operator >= (E1, const E2);
|
||||
|
||||
E1 a;
|
||||
E2 b;
|
||||
|
||||
extern A test1;
|
||||
extern decltype(a >= a) test1;
|
||||
extern decltype(a >= b) test1;
|
||||
|
||||
template <typename T> A operator <= (E1, T);
|
||||
extern bool test2;
|
||||
extern decltype(a <= a) test2;
|
||||
|
||||
extern A test3;
|
||||
extern decltype(a <= b) test3;
|
Loading…
Reference in New Issue