From 14f082b69d7309ddc2abb5bc6a6207ce9b1c2c11 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 18 Sep 2012 21:52:24 +0000 Subject: [PATCH] Fix a small bug in the way we handle builtin candidates for relational operators of enumeration type. From the gcc testsuite. llvm-svn: 164171 --- clang/lib/Sema/SemaOverload.cpp | 22 +++++++++-------- clang/test/CXX/over/over.built/p1.cpp | 16 ------------- .../over.match.funcs/over.match.oper/p3.cpp | 28 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 26 deletions(-) delete mode 100644 clang/test/CXX/over/over.built/p1.cpp create mode 100644 clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 14f8db6..1dec1ff 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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 > @@ -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 = diff --git a/clang/test/CXX/over/over.built/p1.cpp b/clang/test/CXX/over/over.built/p1.cpp deleted file mode 100644 index 6000f5b..0000000 --- a/clang/test/CXX/over/over.built/p1.cpp +++ /dev/null @@ -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; -} diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp new file mode 100644 index 0000000..c8b07e5 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp @@ -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 A operator <= (E1, T); +extern bool test2; +extern decltype(a <= a) test2; + +extern A test3; +extern decltype(a <= b) test3; \ No newline at end of file -- 2.7.4