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}} + } +} _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits