Improve our handling of (C++) references within Clang. Specifically:
  - Do not allow expressions to ever have reference type
  - Extend Expr::isLvalue to handle more cases where having written a
    reference into the source implies that the expression is an lvalue
    (e.g., function calls, C++ casts).
  - Make GRExprEngine::VisitCall treat the call arguments as lvalues when
    they are being bound to a reference parameter.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58306 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 1380264..f330444 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -393,6 +393,20 @@
     break;
   case ParenExprClass: // C99 6.5.1p5
     return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
+  case CallExprClass: {
+    // C++ [expr.call]p10:
+    //   A function call is an lvalue if and only if the result type
+    //   is a reference.
+    QualType CalleeType 
+      = dyn_cast<CallExpr>(this)->getCallee()->IgnoreParens()->getType();
+    if (const PointerType *FnTypePtr = CalleeType->getAsPointerType())
+      if (const FunctionType *FnType
+            = FnTypePtr->getPointeeType()->getAsFunctionType())
+        if (FnType->getResultType()->isReferenceType())
+          return LV_Valid;
+    
+    break;
+  }
   case CompoundLiteralExprClass: // C99 6.5.2.5p5
     return LV_Valid;
   case ExtVectorElementExprClass:
@@ -407,10 +421,25 @@
     return (cast<PredefinedExpr>(this)->getIdentType()
                == PredefinedExpr::CXXThis
             ? LV_InvalidExpression : LV_Valid);
+  case VAArgExprClass:
+    return LV_Valid;
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
   case CXXConditionDeclExprClass:
     return LV_Valid;
+  case ExplicitCCastExprClass:
+  case CXXFunctionalCastExprClass:
+  case CXXStaticCastExprClass:
+  case CXXDynamicCastExprClass:
+  case CXXReinterpretCastExprClass:
+  case CXXConstCastExprClass:
+    // The result of an explicit cast is an lvalue if the type we are
+    // casting to is a reference type. See C++ [expr.cast]p1, 
+    // C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2,
+    // C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1.
+    if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isReferenceType())
+      return LV_Valid;
+    break;
   default:
     break;
   }