]> granicus.if.org Git - clang/commitdiff
Apply the special enum restrictions from [over.match.oper]p3b2 in argument-dependent...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 23 Oct 2009 19:23:15 +0000 (19:23 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 23 Oct 2009 19:23:15 +0000 (19:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84963 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/TreeTransform.h
test/SemaCXX/overloaded-operator.cpp

index 6dd081bdc25e37314c30a2f4a27e3573d8eb9db4..7f3c49acc8be100ff888bfa727bd83ab1d8e51ab 100644 (file)
@@ -1377,7 +1377,7 @@ public:
                                     QualType T1, QualType T2,
                                     FunctionSet &Functions);
 
-  void ArgumentDependentLookup(DeclarationName Name,
+  void ArgumentDependentLookup(DeclarationName Name, bool Operator,
                                Expr **Args, unsigned NumArgs,
                                FunctionSet &Functions);
 
index accdc7e5c85b1843b82668ed811a3a6479981d46..490c73896ed13a81d1db21a63039fb39e3c32ae9 100644 (file)
@@ -5435,7 +5435,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
       Expr *Args[2] = { lhs, rhs };
       DeclarationName OpName
         = Context.DeclarationNames.getCXXOperatorName(OverOp);
-      ArgumentDependentLookup(OpName, Args, 2, Functions);
+      ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
     }
 
     // Build the (potentially-overloaded, potentially-dependent)
@@ -5553,7 +5553,7 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
                                    Functions);
       DeclarationName OpName
         = Context.DeclarationNames.getCXXOperatorName(OverOp);
-      ArgumentDependentLookup(OpName, &Input, 1, Functions);
+      ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
     }
 
     return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
index dd877c16fba79c89573d2c0c22e2c359e65552c8..abed5d4d1703e9c322c23d77ffa1182a0bcfa41f 100644 (file)
@@ -1561,7 +1561,7 @@ static void CollectFunctionDecl(Sema::FunctionSet &Functions,
     Functions.insert(FunTmpl);
 }
 
-void Sema::ArgumentDependentLookup(DeclarationName Name,
+void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
                                    Expr **Args, unsigned NumArgs,
                                    FunctionSet &Functions) {
   // Find all of the associated namespaces and classes based on the
@@ -1572,6 +1572,13 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
                                      AssociatedNamespaces,
                                      AssociatedClasses);
 
+  QualType T1, T2;
+  if (Operator) {
+    T1 = Args[0]->getType();
+    if (NumArgs >= 2)
+      T2 = Args[1]->getType();
+  }
+
   // C++ [basic.lookup.argdep]p3:
   //   Let X be the lookup set produced by unqualified lookup (3.4.1)
   //   and let Y be the lookup set produced by argument dependent
@@ -1608,7 +1615,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
           continue;
       }
 
-      CollectFunctionDecl(Functions, D);
+      FunctionDecl *Fn;
+      if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
+          IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
+        CollectFunctionDecl(Functions, D);
     }
   }
 }
index 9e79b999e7f58b68bea55eaa31e576c1cfd03736..5e946eb762131aea65cd0c9c949754a2437aebe0 100644 (file)
@@ -2761,7 +2761,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
   if (S)
     LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
-  ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+  ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions);
   AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
   AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
   AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
@@ -3908,7 +3908,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
     }
 
   // FIXME: Pass in the explicit template arguments?
-  ArgumentDependentLookup(Name, Args, NumArgs, Functions);
+  ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions);
 
   // Erase all of the candidates we already knew about.
   // FIXME: This is suboptimal. Is there a better way?
index 94a0e11ec8e16de94b10630265311cd91d500f91..872b3c0189b26af75816833ee4652c54b6e0557a 100644 (file)
@@ -5107,7 +5107,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
   unsigned NumArgs = 1 + (SecondExpr != 0);
   DeclarationName OpName
     = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
-  SemaRef.ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+  SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs,
+                                  Functions);
 
   // Create the overloaded operator invocation for unary operators.
   if (NumArgs == 1 || isPostIncDec) {
index 10b0f5a76804fd396fbb889531c4e01f04e22a8c..0f723ad206b9bf44e3caebb689d3695be8968046 100644 (file)
@@ -70,6 +70,34 @@ void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2) {
   float &f4 = (enum1 == enum2);  // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type 'bool'}}
 }
 
+// PR5244 - Argument-dependent lookup would include the two operators below,
+// which would break later assumptions and lead to a crash.
+class pr5244_foo
+{
+  pr5244_foo(int);
+  pr5244_foo(char);
+};
+
+bool operator==(const pr5244_foo& s1, const pr5244_foo& s2);
+bool operator==(char c, const pr5244_foo& s);
+
+enum pr5244_bar
+{
+    pr5244_BAR
+};
+
+class pr5244_baz
+{
+    pr5244_bar quux;
+};
+
+void pr5244_barbaz()
+{
+  pr5244_baz quuux;
+  (void)(pr5244_BAR == quuux.quux);
+}
+
+
 
 struct PostInc {
   PostInc operator++(int);