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/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7b88ec2..3e33172 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1382,11 +1382,6 @@
   if (CompoundLiteralExpr *e = dyn_cast<CompoundLiteralExpr>(Init))
     return CheckForConstantInitializer(e->getInitializer(), DclT);
 
-  if (Init->getType()->isReferenceType()) {
-    // FIXME: Work out how the heck references work.
-    return false;
-  }
-
   if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {
     unsigned numInits = Exp->getNumInits();
     for (unsigned i = 0; i < numInits; i++) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a73f0dd..42f9ec7 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -35,10 +35,6 @@
   QualType Ty = E->getType();
   assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
 
-  if (const ReferenceType *ref = Ty->getAsReferenceType()) {
-    ImpCastExprToType(E, ref->getPointeeType()); // C++ [expr]
-    Ty = E->getType();
-  }
   if (Ty->isFunctionType())
     ImpCastExprToType(E, Context.getPointerType(Ty));
   else if (Ty->isArrayType()) {
@@ -68,10 +64,6 @@
   QualType Ty = Expr->getType();
   assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
   
-  if (const ReferenceType *Ref = Ty->getAsReferenceType()) {
-    ImpCastExprToType(Expr, Ref->getPointeeType()); // C++ [expr]
-    Ty = Expr->getType();
-  }
   if (Ty->isPromotableIntegerType()) // C99 6.3.1.1p2
     ImpCastExprToType(Expr, Context.IntTy);
   else
@@ -442,11 +434,13 @@
   if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
     // The BlocksAttr indicates the variable is bound by-reference.
     if (VD->getAttr<BlocksAttr>())
-      return new BlockDeclRefExpr(VD, VD->getType(), Loc, true);
+      return new BlockDeclRefExpr(VD, VD->getType().getNonReferenceType(), 
+                                  Loc, true);
       
     // Variable will be bound by-copy, make it const within the closure.
     VD->getType().addConst();
-    return new BlockDeclRefExpr(VD, VD->getType(), Loc, false);
+    return new BlockDeclRefExpr(VD, VD->getType().getNonReferenceType(), 
+                                Loc, false);
   }
   // If this reference is not in a block or if the referenced variable is
   // within the block, create a normal DeclRefExpr.
@@ -1674,8 +1668,15 @@
   if (lhsType == rhsType)
     return Compatible; // Common case: fast path an exact match.
 
-  if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
-    if (Context.typesAreCompatible(lhsType, rhsType))
+  // If the left-hand side is a reference type, then we are in a
+  // (rare!) case where we've allowed the use of references in C,
+  // e.g., as a parameter type in a built-in function. In this case,
+  // just make sure that the type referenced is compatible with the
+  // right-hand side type. The caller is responsible for adjusting
+  // lhsType so that the resulting expression does not have reference
+  // type.
+  if (const ReferenceType *lhsTypeRef = lhsType->getAsReferenceType()) {
+    if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType))
       return Compatible;
     return Incompatible;
   }
@@ -1808,8 +1809,7 @@
   // DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary
   // expressions that surpress this implicit conversion (&, sizeof).
   //
-  // Suppress this for references: C++ 8.5.3p5.  FIXME: revisit when references
-  // are better understood.
+  // Suppress this for references: C++ 8.5.3p5.  
   if (!lhsType->isReferenceType())
     DefaultFunctionArrayConversion(rExpr);
 
@@ -1818,8 +1818,12 @@
   
   // C99 6.5.16.1p2: The value of the right operand is converted to the
   // type of the assignment expression.
+  // CheckAssignmentConstraints allows the left-hand side to be a reference,
+  // so that we can use references in built-in functions even in C.
+  // The getNonReferenceType() call makes sure that the resulting expression
+  // does not have reference type.
   if (rExpr->getType() != lhsType)
-    ImpCastExprToType(rExpr, lhsType);
+    ImpCastExprToType(rExpr, lhsType.getNonReferenceType());
   return result;
 }
 
@@ -2909,7 +2913,8 @@
     // FIXME: Verify that MemberDecl isn't a bitfield.
     // MemberDecl->getType() doesn't get the right qualifiers, but it doesn't
     // matter here.
-    Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd, MemberDecl->getType());
+    Res = new MemberExpr(Res, false, MemberDecl, OC.LocEnd, 
+                         MemberDecl->getType().getNonReferenceType());
   }
   
   return new UnaryOperator(Res, UnaryOperator::OffsetOf, Context.getSizeType(),
@@ -3121,7 +3126,8 @@
                     OE->getFn()->getSourceRange());
       // Remember our match, and continue processing the remaining arguments
       // to catch any errors.
-      OE = new OverloadExpr(Args, NumArgs, i, FnType->getResultType(),
+      OE = new OverloadExpr(Args, NumArgs, i, 
+                            FnType->getResultType().getNonReferenceType(),
                             BuiltinLoc, RParenLoc);
     }
   }
@@ -3168,7 +3174,7 @@
   
   // FIXME: Warn if a non-POD type is passed in.
   
-  return new VAArgExpr(BuiltinLoc, E, T, RPLoc);
+  return new VAArgExpr(BuiltinLoc, E, T.getNonReferenceType(), RPLoc);
 }
 
 bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 34eff25..7a5e2dd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -79,10 +79,6 @@
     // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
     //   [...] if a pointer to T1 can be [cast] to the type pointer to T2.
     DestType = Context.getPointerType(DestTypeTmp->getPointeeType());
-    if (const ReferenceType *SrcTypeTmp = SrcType->getAsReferenceType()) {
-      // FIXME: This shouldn't actually be possible, but right now it is.
-      SrcType = SrcTypeTmp->getPointeeType();
-    }
     SrcType = Context.getPointerType(SrcType);
   } else {
     // C++ 5.2.11p1: Otherwise, the result is an rvalue and the
@@ -177,10 +173,6 @@
     //   built-in & and * operators.
     // This code does this transformation for the checked types.
     DestType = Context.getPointerType(DestTypeTmp->getPointeeType());
-    if (const ReferenceType *SrcTypeTmp = SrcType->getAsReferenceType()) {
-      // FIXME: This shouldn't actually be possible, but right now it is.
-      SrcType = SrcTypeTmp->getPointeeType();
-    }
     SrcType = Context.getPointerType(SrcType);
   } else {
     // C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and