]> granicus.if.org Git - clang/commitdiff
Don't perform ADL when looking up operator=; there is no non-member form of
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 23 Sep 2014 20:31:39 +0000 (20:31 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 23 Sep 2014 20:31:39 +0000 (20:31 +0000)
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
lib/Sema/SemaOverload.cpp
test/CXX/drs/dr2xx.cpp
test/SemaCXX/overloaded-operator.cpp

index 50bc4d2ac8bb015dcf03929ae4eefb0a25bc6e69..5edabc03b691a95845bf48da4265fe9aebd5d206 100644 (file)
@@ -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);
 
index ea3e63fe34aaf6155955ba544eeb0eef53053b92..b7089ef35e882aae4e2ae758cd25fda00a9a04a5 100644 (file)
@@ -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);
index 78078b9c072903a38453c2705df58b223dab2f72..dd56b17bd9d0c091152f93470c95a6e06ce1028f 100644 (file)
@@ -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;
   }
 }
index feb7c716ff00836b15c8d44159f26e28ea261c96..369e9eb802a59f9b802b45300946a8a5f768e8f5 100644 (file)
@@ -519,3 +519,15 @@ namespace ConversionVersusTemplateOrdering {
   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}}
+  }
+}