r218330 - Don't perform ADL when looking up operator=; there is no non-member form of
Richard Smith
richard-llvm at metafoo.co.uk
Tue Sep 23 13:31:39 PDT 2014
Author: rsmith
Date: Tue Sep 23 15:31:39 2014
New Revision: 218330
URL: http://llvm.org/viewvc/llvm-project?rev=218330&view=rev
Log:
Don't perform ADL when looking up operator=; there is no non-member form of
that function, and apart from being slow, this is unnecessary: ADL can trigger
instantiations that are not permitted here. The standard isn't *completely*
clear here, but this seems like the intent, and in any case this approach is
permitted by [temp.inst]p7.
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/CXX/drs/dr2xx.cpp
cfe/trunk/test/SemaCXX/overloaded-operator.cpp
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=218330&r1=218329&r2=218330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Sep 23 15:31:39 2014
@@ -9704,7 +9704,7 @@ static ExprResult BuildOverloadedBinOp(S
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp
= BinaryOperator::getOverloadedOperator(Opc);
- if (Sc && OverOp != OO_None)
+ if (Sc && OverOp != OO_None && OverOp != OO_Equal)
S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
RHS->getType(), Functions);
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=218330&r1=218329&r2=218330&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Sep 23 15:31:39 2014
@@ -11031,10 +11031,13 @@ Sema::CreateOverloadedBinOp(SourceLocati
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
- // Add candidates from ADL.
- AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
+ // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
+ // performed for an assignment operator (nor for operator[] nor operator->,
+ // which don't get here).
+ if (Opc != BO_Assign)
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
Modified: cfe/trunk/test/CXX/drs/dr2xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr2xx.cpp?rev=218330&r1=218329&r2=218330&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr2xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr2xx.cpp Tue Sep 23 15:31:39 2014
@@ -195,8 +195,8 @@ namespace dr218 { // dr218: yes
// dr220: na
namespace dr221 { // dr221: yes
- struct A {
- A &operator=(int&);
+ struct A { // expected-note 2-4{{candidate}}
+ A &operator=(int&); // expected-note 2{{candidate}}
A &operator+=(int&);
static A &operator=(A&, double&); // expected-error {{cannot be a static member}}
static A &operator+=(A&, double&); // expected-error {{cannot be a static member}}
@@ -209,9 +209,9 @@ namespace dr221 { // dr221: yes
void test(A a, int n, char c, float f) {
a = n;
a += n;
- a = c;
+ a = c; // expected-error {{no viable}}
a += c;
- a = f;
+ a = f; // expected-error {{no viable}}
a += f;
}
}
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=218330&r1=218329&r2=218330&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Tue Sep 23 15:31:39 2014
@@ -519,3 +519,15 @@ namespace ConversionVersusTemplateOrderi
int x = a;
int y = b;
}
+
+namespace NoADLForMemberOnlyOperators {
+ template<typename T> struct A { typename T::error e; }; // expected-error {{type 'char' cannot be used prior to '::'}}
+ template<typename T> struct B { int n; };
+
+ void f(B<A<void> > b1, B<A<int> > b2, B<A<char> > b3) {
+ b1 = b1; // ok, does not instantiate A<void>.
+ (void)b1->n; // expected-error {{is not a pointer}}
+ b2[3]; // expected-error {{does not provide a subscript}}
+ b3 / 0; // expected-note {{in instantiation of}} expected-error {{invalid operands to}}
+ }
+}
More information about the cfe-commits
mailing list