Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin

  bool operator==(int const*, int const*)

can be used for the expression "x1 == x2" given:

  struct X {
    operator int const*();
  } x1, x2;

The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it. 

There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.

Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.

As part of this change, ImplicitCastExpr can now be an lvalue.





git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index fbb2256..c54fc40 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -389,8 +389,28 @@
         cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Extension)
       return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(Ctx);  // GNU.
     break;
+  case ImplicitCastExprClass:
+    return cast<ImplicitCastExpr>(this)->isLvalueCast()? LV_Valid 
+                                                       : LV_InvalidExpression;
   case ParenExprClass: // C99 6.5.1p5
     return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
+  case BinaryOperatorClass:
+  case CompoundAssignOperatorClass: {
+    const BinaryOperator *BinOp = cast<BinaryOperator>(this);
+    if (BinOp->isAssignmentOp()) {
+      if (Ctx.getLangOptions().CPlusPlus)
+        // C++ [expr.ass]p1: 
+        //   The result of an assignment operation [...] is an lvalue.
+        return LV_Valid;
+      else 
+        // C99 6.5.16:
+        //   An assignment expression [...] is not an lvalue.
+        return LV_InvalidExpression;
+    } else
+      return LV_InvalidExpression;
+
+    break;
+  }
   case CallExprClass: {
     // C++ [expr.call]p10:
     //   A function call is an lvalue if and only if the result type
diff --git a/lib/AST/StmtSerialization.cpp b/lib/AST/StmtSerialization.cpp
index f71b88b..667f597 100644
--- a/lib/AST/StmtSerialization.cpp
+++ b/lib/AST/StmtSerialization.cpp
@@ -662,12 +662,14 @@
 void ImplicitCastExpr::EmitImpl(Serializer& S) const {
   S.Emit(getType());
   S.EmitOwnedPtr(getSubExpr());
+  S.Emit(LvalueCast);
 }
 
 ImplicitCastExpr* ImplicitCastExpr::CreateImpl(Deserializer& D, ASTContext& C) {
   QualType t = QualType::ReadVal(D);
   Expr* Op = D.ReadOwnedPtr<Expr>(C);
-  return new ImplicitCastExpr(t,Op);
+  bool isLvalue = D.ReadBool();
+  return new ImplicitCastExpr(t,Op,isLvalue);
 }
 
 void IndirectGotoStmt::EmitImpl(Serializer& S) const {