Support compound complex operations as l-values in C++.  Add a test
case based on CodeGen/volatile-1.c which tests the current C++
semantics, and note the many, many places we fall short of them.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119402 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 0c24bf5..6bfafca 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1981,19 +1981,27 @@
   if (E->getOpcode() == BO_PtrMemD ||
       E->getOpcode() == BO_PtrMemI)
     return EmitPointerToDataMemberBinaryExpr(E);
-  
-  // Can only get l-value for binary operator expressions which are a
-  // simple assignment of aggregate type.
-  if (E->getOpcode() != BO_Assign)
-    return EmitUnsupportedLValue(E, "binary l-value expression");
 
+  assert(E->isAssignmentOp() && "unexpected binary l-value");
+  
   if (!hasAggregateLLVMType(E->getType())) {
+    if (E->isCompoundAssignmentOp())
+      return EmitCompoundAssignOperatorLValue(cast<CompoundAssignOperator>(E));
+
+    assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
+
     // Emit the LHS as an l-value.
     LValue LV = EmitLValue(E->getLHS());
     // Store the value through the l-value.
     EmitStoreThroughLValue(EmitAnyExpr(E->getRHS()), LV, E->getType());
     return LV;
   }
+
+  if (E->getType()->isAnyComplexType())
+    return EmitComplexAssignmentLValue(E);
+
+  // The compound assignment operators are not used for aggregates.
+  assert(E->getOpcode() == BO_Assign && "aggregate compound assignment?");
   
   return EmitAggExprToLValue(E);
 }
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index df65d5a..26bda79 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -760,3 +760,26 @@
                                                    bool SrcIsVolatile) {
   return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile);
 }
+
+LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) {
+  ComplexPairTy Val; // ignored
+
+  ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &);
+
+  switch (E->getOpcode()) {
+  case BO_Assign:
+    return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val);
+
+  case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break;
+  case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break;
+  case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break;
+  case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break;
+
+  default:
+    llvm_unreachable("unexpected complex compound assignment");
+    Op = 0;
+  }
+
+  return ComplexExprEmitter(*this).EmitCompoundAssignLValue(
+                                   cast<CompoundAssignOperator>(E), Op, Val);
+}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index a3e1eac..560675e 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1404,6 +1404,9 @@
   void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, QualType Ty,
                                       llvm::Value **Result=0);
 
+  /// Emit an l-value for an assignment (simple or compound) of complex type.
+  LValue EmitComplexAssignmentLValue(const BinaryOperator *E);
+
   // Note: only availabe for agg return types
   LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
   LValue EmitCompoundAssignOperatorLValue(const CompoundAssignOperator *E);