Refactor the way we handle operator overloading and template
instantiation for binary operators. This change moves most of the
operator-overloading code from the parser action ActOnBinOp to a new,
parser-independent semantic checking routine CreateOverloadedBinOp. 

Of particular importance is the fact that CreateOverloadedBinOp does
*not* perform any name lookup based on the current parsing context (it
doesn't take a Scope*), since it has to be usable during template
instantiation, when there is no scope information. Rather, it takes a
pre-computed set of functions that are visible from the context or via
argument-dependent lookup, and adds to that set any member operators
and built-in operator candidates. The set of functions is computed in
the parser action ActOnBinOp based on the current context (both
operator name lookup and argument-dependent lookup). Within a
template, the set computed by ActOnBinOp is saved within the
type-dependent AST node and is augmented with the results of
argument-dependent name lookup at instantiation time (see
TemplateExprInstantiator::VisitCXXOperatorCallExpr).

Sadly, we can't fully test this yet. I'll follow up with template
instantiation for sizeof so that the real fun can begin.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66923 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 53174b6..8650347 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -468,7 +468,7 @@
   Expr::isLvalueResult argIsLvalue = From->isLvalue(Context);
   if (argIsLvalue == Expr::LV_Valid && 
       !FromType->isFunctionType() && !FromType->isArrayType() &&
-      !FromType->isOverloadType()) {
+      Context.getCanonicalType(FromType) != Context.OverloadTy) {
     SCS.First = ICK_Lvalue_To_Rvalue;
 
     // If T is a non-class type, the type of the rvalue is the
@@ -2064,6 +2064,19 @@
   }
 }
 
+/// \brief Add all of the function declarations in the given function set to
+/// the overload canddiate set.
+void Sema::AddFunctionCandidates(const FunctionSet &Functions,
+                                 Expr **Args, unsigned NumArgs,
+                                 OverloadCandidateSet& CandidateSet,
+                                 bool SuppressUserConversions) {
+  for (FunctionSet::const_iterator F = Functions.begin(), 
+                                FEnd = Functions.end();
+       F != FEnd; ++F)
+    AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, 
+                         SuppressUserConversions);
+}
+
 /// AddMethodCandidate - Adds the given C++ member function to the set
 /// of candidate functions, using the given function call arguments
 /// and the object argument (@c Object). For example, in a call
@@ -2308,17 +2321,43 @@
   }
 }
 
-/// AddOperatorCandidates - Add the overloaded operator candidates for
-/// the operator Op that was used in an operator expression such as "x
-/// Op y". S is the scope in which the expression occurred (used for
-/// name lookup of the operator), Args/NumArgs provides the operator
-/// arguments, and CandidateSet will store the added overload
-/// candidates. (C++ [over.match.oper]).
-bool Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
+// FIXME: This will eventually be removed, once we've migrated all of
+// the operator overloading logic over to the scheme used by binary
+// operators, which works for template instantiation.
+void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
                                  SourceLocation OpLoc,
                                  Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet,
                                  SourceRange OpRange) {
+
+  FunctionSet Functions;
+
+  QualType T1 = Args[0]->getType();
+  QualType T2;
+  if (NumArgs > 1)
+    T2 = Args[1]->getType();
+
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+  LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
+  ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+  AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
+  AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
+  AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet);
+}
+
+/// \brief Add overload candidates for overloaded operators that are
+/// member functions.
+///
+/// Add the overloaded operator candidates that are member functions
+/// for the operator Op that was used in an operator expression such
+/// as "x Op y". , Args/NumArgs provides the operator arguments, and
+/// CandidateSet will store the added overload candidates. (C++
+/// [over.match.oper]).
+void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+                                       SourceLocation OpLoc,
+                                       Expr **Args, unsigned NumArgs,
+                                       OverloadCandidateSet& CandidateSet,
+                                       SourceRange OpRange) {
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
 
   // C++ [over.match.oper]p3:
@@ -2338,6 +2377,7 @@
   //        result of the qualified lookup of T1::operator@
   //        (13.3.1.1.1); otherwise, the set of member candidates is
   //        empty.
+  // FIXME: Lookup in base classes, too!
   if (const RecordType *T1Rec = T1->getAsRecordType()) {
     DeclContext::lookup_const_iterator Oper, OperEnd;
     for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(OpName);
@@ -2346,38 +2386,6 @@
                          Args+1, NumArgs - 1, CandidateSet,
                          /*SuppressUserConversions=*/false);
   }
-
-  FunctionSet Functions;
-
-  //     -- The set of non-member candidates is the result of the
-  //        unqualified lookup of operator@ in the context of the
-  //        expression according to the usual rules for name lookup in
-  //        unqualified function calls (3.4.2) except that all member
-  //        functions are ignored. However, if no operand has a class
-  //        type, only those non-member functions in the lookup set
-  //        that have a first parameter of type T1 or “reference to
-  //        (possibly cv-qualified) T1”, when T1 is an enumeration
-  //        type, or (if there is a right operand) a second parameter
-  //        of type T2 or “reference to (possibly cv-qualified) T2”,
-  //        when T2 is an enumeration type, are candidate functions.
-  LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
-
-  // Since the set of non-member candidates corresponds to
-  // *unqualified* lookup of the operator name, we also perform
-  // argument-dependent lookup (C++ [basic.lookup.argdep]).
-  ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
-
-  // Add all of the functions found via operator name lookup and
-  // argument-dependent lookup to the candidate set.
-  for (FunctionSet::iterator Func = Functions.begin(),
-                          FuncEnd = Functions.end();
-       Func != FuncEnd; ++Func)
-    AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
-
-  // Add builtin overload candidates (C++ [over.built]).
-  AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet);
-
-  return false;
 }
 
 /// AddBuiltinCandidate - Add a candidate for a built-in
@@ -3615,6 +3623,161 @@
   return 0;
 }
 
+/// \brief Create a binary operation that may resolve to an overloaded
+/// operator.
+///
+/// \param OpLoc The location of the operator itself (e.g., '+').
+///
+/// \param OpcIn The BinaryOperator::Opcode that describes this
+/// operator.
+///
+/// \param Functions The set of non-member functions that will be
+/// considered by overload resolution. The caller needs to build this
+/// set based on the context using, e.g.,
+/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This
+/// set should not contain any member functions; those will be added
+/// by CreateOverloadedBinOp().
+///
+/// \param LHS Left-hand argument.
+/// \param RHS Right-hand argument.
+Sema::OwningExprResult 
+Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
+                            unsigned OpcIn, 
+                            FunctionSet &Functions,
+                            Expr *LHS, Expr *RHS) {
+  OverloadCandidateSet CandidateSet;
+  Expr *Args[2] = { LHS, RHS };
+
+  BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
+  OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
+  DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+
+  // If either side is type-dependent, create an appropriate dependent
+  // expression.
+  if (LHS->isTypeDependent() || RHS->isTypeDependent()) {
+    // .* cannot be overloaded.
+    if (Opc == BinaryOperator::PtrMemD)
+      return Owned(new (Context) BinaryOperator(LHS, RHS, Opc,
+                                                Context.DependentTy, OpLoc));
+
+    OverloadedFunctionDecl *Overloads 
+      = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
+    for (FunctionSet::iterator Func = Functions.begin(), 
+                            FuncEnd = Functions.end();
+         Func != FuncEnd; ++Func)
+      Overloads->addOverload(*Func);
+
+    DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy,
+                                                OpLoc, false, false);
+    
+    return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
+                                                   Args, 2, 
+                                                   Context.DependentTy,
+                                                   OpLoc));
+  }
+
+  // If this is the .* operator, which is not overloadable, just
+  // create a built-in binary operator.
+  if (Opc == BinaryOperator::PtrMemD)
+    return CreateBuiltinBinOp(OpLoc, Opc, LHS, RHS);
+
+  // If this is one of the assignment operators, we only perform
+  // overload resolution if the left-hand side is a class or
+  // enumeration type (C++ [expr.ass]p3).
+  if (Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign &&
+      !LHS->getType()->isOverloadableType())
+    return CreateBuiltinBinOp(OpLoc, Opc, LHS, RHS);
+
+
+  // Add the candidates from the given function set.
+  AddFunctionCandidates(Functions, Args, 2, CandidateSet, false);
+
+  // Add operator candidates that are member functions.
+  AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
+
+  // Add builtin operator candidates.
+  AddBuiltinOperatorCandidates(Op, Args, 2, CandidateSet);
+
+  // Perform overload resolution.
+  OverloadCandidateSet::iterator Best;
+  switch (BestViableFunction(CandidateSet, Best)) {
+  case OR_Success: {
+      // We found a built-in operator or an overloaded operator.
+      FunctionDecl *FnDecl = Best->Function;
+
+      if (FnDecl) {
+        // We matched an overloaded operator. Build a call to that
+        // operator.
+
+        // Convert the arguments.
+        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
+          if (PerformObjectArgumentInitialization(LHS, Method) ||
+              PerformCopyInitialization(RHS, FnDecl->getParamDecl(0)->getType(),
+                                        "passing"))
+            return ExprError();
+        } else {
+          // Convert the arguments.
+          if (PerformCopyInitialization(LHS, FnDecl->getParamDecl(0)->getType(),
+                                        "passing") ||
+              PerformCopyInitialization(RHS, FnDecl->getParamDecl(1)->getType(),
+                                        "passing"))
+            return ExprError();
+        }
+
+        // Determine the result type
+        QualType ResultTy
+          = FnDecl->getType()->getAsFunctionType()->getResultType();
+        ResultTy = ResultTy.getNonReferenceType();
+
+        // Build the actual expression node.
+        Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(),
+                                                 SourceLocation());
+        UsualUnaryConversions(FnExpr);
+
+        return Owned(new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, 
+                                                       Args, 2, ResultTy, 
+                                                       OpLoc));
+      } else {
+        // We matched a built-in operator. Convert the arguments, then
+        // break out so that we will build the appropriate built-in
+        // operator node.
+        if (PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
+                                      Best->Conversions[0], "passing") ||
+            PerformImplicitConversion(RHS, Best->BuiltinTypes.ParamTypes[1],
+                                      Best->Conversions[1], "passing"))
+          return ExprError();
+
+        break;
+      }
+    }
+
+    case OR_No_Viable_Function:
+      // No viable function; fall through to handling this as a
+      // built-in operator, which will produce an error message for us.
+      break;
+
+    case OR_Ambiguous:
+      Diag(OpLoc,  diag::err_ovl_ambiguous_oper)
+          << BinaryOperator::getOpcodeStr(Opc)
+          << LHS->getSourceRange() << RHS->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+      return ExprError();
+
+    case OR_Deleted:
+      Diag(OpLoc, diag::err_ovl_deleted_oper)
+        << Best->Function->isDeleted()
+        << BinaryOperator::getOpcodeStr(Opc)
+        << LHS->getSourceRange() << RHS->getSourceRange();
+      PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+      return ExprError();
+    }
+
+  // Either we found no viable overloaded operator or we matched a
+  // built-in operator. In either case, try to build a built-in
+  // operation.
+  return CreateBuiltinBinOp(OpLoc, Opc, LHS, RHS);
+}
+
 /// BuildCallToMemberFunction - Build a call to a member
 /// function. MemExpr is the expression that refers to the member
 /// function (and includes the object parameter), Args/NumArgs are the
@@ -3870,8 +4033,8 @@
   // owned.
   QualType ResultTy = Method->getResultType().getNonReferenceType();
   ExprOwningPtr<CXXOperatorCallExpr> 
-    TheCall(this, new (Context) CXXOperatorCallExpr(Context, NewFn, MethodArgs,
-                                                    NumArgs + 1,
+    TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, 
+                                                    MethodArgs, NumArgs + 1,
                                                     ResultTy, RParenLoc));
   delete [] MethodArgs;
 
@@ -3989,7 +4152,7 @@
   Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(),
                                            SourceLocation());
   UsualUnaryConversions(FnExpr);
-  Base = new (Context) CXXOperatorCallExpr(Context, FnExpr, &Base, 1, 
+  Base = new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, &Base, 1, 
                                  Method->getResultType().getNonReferenceType(),
                                  OpLoc);
   return ActOnMemberReferenceExpr(S, ExprArg(*this, Base), OpLoc, tok::arrow,