From 805726b5386d79ec387312afb6489739697eeb57 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 23 Sep 2014 20:31:39 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218330 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 2 +- lib/Sema/SemaOverload.cpp | 11 +++++++---- test/CXX/drs/dr2xx.cpp | 8 ++++---- test/SemaCXX/overloaded-operator.cpp | 12 ++++++++++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 50bc4d2ac8..5edabc03b6 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9704,7 +9704,7 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc, 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); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ea3e63fe34..b7089ef35e 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11031,10 +11031,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // 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); diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index 78078b9c07..dd56b17bd9 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -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; } } diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index feb7c716ff..369e9eb802 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -519,3 +519,15 @@ namespace ConversionVersusTemplateOrdering { int x = a; int y = b; } + +namespace NoADLForMemberOnlyOperators { + template struct A { typename T::error e; }; // expected-error {{type 'char' cannot be used prior to '::'}} + template struct B { int n; }; + + void f(B > b1, B > b2, B > b3) { + b1 = b1; // ok, does not instantiate A. + (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}} + } +} -- 2.40.0