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:
Eli Friedman 2012-09-18 21:52:24 +00:00
parent e115af2777
commit 14f082b69d
3 changed files with 40 additions and 26 deletions

View File

@ -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 =

View File

@ -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;
}

View File

@ -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;