Implement lvalue test for conditional expressions.
Add a few commented lines to the test case that point out things that don't work yet.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69354 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 083bf3b..83efc75 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -772,6 +772,32 @@
   case CXXTypeidExprClass:
     // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
     return LV_Valid;
+  case ConditionalOperatorClass: {
+    // Complicated handling is only for C++.
+    if (!Ctx.getLangOptions().CPlusPlus)
+      return LV_InvalidExpression;
+
+    // Sema should have taken care to ensure that a CXXTemporaryObjectExpr is
+    // everywhere there's an object converted to an rvalue. Also, any other
+    // casts should be wrapped by ImplicitCastExprs. There's just the special
+    // case involving throws to work out.
+    const ConditionalOperator *Cond = cast<ConditionalOperator>(this);
+    Expr *LHS = Cond->getLHS();
+    Expr *RHS = Cond->getRHS();
+    // C++0x 5.16p2
+    //   If either the second or the third operand has type (cv) void, [...]
+    //   the result [...] is an rvalue.
+    if (LHS->getType()->isVoidType() || RHS->getType()->isVoidType())
+      return LV_InvalidExpression;
+
+    // Both sides must be lvalues for the result to be an lvalue.
+    if (LHS->isLvalue(Ctx) != LV_Valid || RHS->isLvalue(Ctx) != LV_Valid)
+      return LV_InvalidExpression;
+
+    // That's it.
+    return LV_Valid;
+  }
+
   default:
     break;
   }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9fd6226..734b6ce 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2120,6 +2120,7 @@
       ICS->Standard.ReferenceBinding = true;
       ICS->Standard.DirectBinding = true;
       ICS->Standard.RRefBinding = false;
+      ICS->Standard.CopyConstructor = 0;
 
       // Nothing more to do: the inaccessibility/ambiguity check for
       // derived-to-base conversions is suppressed when we're
@@ -2273,6 +2274,7 @@
       ICS->Standard.ReferenceBinding = true;
       ICS->Standard.DirectBinding = false;
       ICS->Standard.RRefBinding = isRValRef;
+      ICS->Standard.CopyConstructor = 0;
     } else {
       // FIXME: Binding to a subobject of the rvalue is going to require
       // more AST annotation than this.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 8f41c00..0539caa 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1137,6 +1137,35 @@
   return true;
 }
 
+/// \brief Perform an "extended" implicit conversion as returned by
+/// TryClassUnification.
+///
+/// TryClassUnification generates ICSs that include reference bindings.
+/// PerformImplicitConversion is not suitable for this; it chokes if the
+/// second part of a standard conversion is ICK_DerivedToBase. This function
+/// handles the reference binding specially.
+static bool ConvertForConditional(Sema &Self, Expr *&E,
+                                  const ImplicitConversionSequence &ICS)
+{
+  if (ICS.ConversionKind == ImplicitConversionSequence::StandardConversion &&
+      ICS.Standard.ReferenceBinding) {
+    assert(ICS.Standard.DirectBinding &&
+           "TryClassUnification should never generate indirect ref bindings");
+    Self.ImpCastExprToType(E, TargetType(ICS), true);
+    return false;
+  }
+  if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion &&
+      ICS.UserDefined.After.ReferenceBinding) {
+    assert(ICS.UserDefined.After.DirectBinding &&
+           "TryClassUnification should never generate indirect ref bindings");
+    Self.ImpCastExprToType(E, TargetType(ICS), true);
+    return false;
+  }
+  if (Self.PerformImplicitConversion(E, TargetType(ICS), ICS, "converting"))
+    return true;
+  return false;
+}
+
 /// \brief Check the operands of ?: under C++ semantics.
 ///
 /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
@@ -1223,13 +1252,11 @@
     //   the chosen operand and the converted operands are used in place of the
     //   original operands for the remainder of this section.
     if (HaveL2R) {
-      if (PerformImplicitConversion(LHS, TargetType(ICSLeftToRight),
-                                    ICSLeftToRight, "converting"))
+      if (ConvertForConditional(*this, LHS, ICSLeftToRight))
         return QualType();
       LTy = LHS->getType();
     } else if (HaveR2L) {
-      if (PerformImplicitConversion(RHS, TargetType(ICSRightToLeft),
-                                    ICSRightToLeft, "converting"))
+      if (ConvertForConditional(*this, RHS, ICSRightToLeft))
         return QualType();
       RTy = RHS->getType();
     }