]> granicus.if.org Git - clang/commitdiff
Handle compound assignment expressions (i += j) as lvalues, which is
authorDouglas Gregor <dgregor@apple.com>
Fri, 23 Apr 2010 04:16:32 +0000 (04:16 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 23 Apr 2010 04:16:32 +0000 (04:16 +0000)
permitted in C++ but not in C. Fixes PR6900. Clang can now handle all
of Boost.Lambda's regression tests.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102170 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprScalar.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/assign-operator.cpp

index 085113edf57b340bcd7552445b45f5f0c8b9f75b..76ad40b2fc76c61e4b807d143b6e21e0c7a1b921 100644 (file)
@@ -478,6 +478,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
     return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
   case Expr::BinaryOperatorClass:
     return EmitBinaryOperatorLValue(cast<BinaryOperator>(E));
+  case Expr::CompoundAssignOperatorClass:
+    return EmitCompoundAssignOperatorLValue(cast<CompoundAssignOperator>(E));
   case Expr::CallExprClass:
   case Expr::CXXMemberCallExprClass:
   case Expr::CXXOperatorCallExprClass:
index d1c0f8dc3d7382d96f5766c6a273dc8c6d91dfe7..e1e22cef5631429c2d9819c06ae811799d601fa7 100644 (file)
@@ -314,6 +314,10 @@ public:
   }
 
   BinOpInfo EmitBinOps(const BinaryOperator *E);
+  LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E,
+                            Value *(ScalarExprEmitter::*F)(const BinOpInfo &),
+                                  Value *&BitFieldResult);
+
   Value *EmitCompoundAssign(const CompoundAssignOperator *E,
                             Value *(ScalarExprEmitter::*F)(const BinOpInfo &));
 
@@ -1103,22 +1107,24 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) {
   return Result;
 }
 
-Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
-                      Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
-  bool Ignore = TestAndClearIgnoreResultAssign();
+LValue ScalarExprEmitter::EmitCompoundAssignLValue(
+                                              const CompoundAssignOperator *E,
+                        Value *(ScalarExprEmitter::*Func)(const BinOpInfo &),
+                                                   Value *&BitFieldResult) {
   QualType LHSTy = E->getLHS()->getType();
-
+  BitFieldResult = 0;
   BinOpInfo OpInfo;
-
+  
   if (E->getComputationResultType()->isAnyComplexType()) {
     // This needs to go through the complex expression emitter, but it's a tad
     // complicated to do that... I'm leaving it out for now.  (Note that we do
     // actually need the imaginary part of the RHS for multiplication and
     // division.)
     CGF.ErrorUnsupported(E, "complex compound assignment");
-    return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
+    llvm::UndefValue::get(CGF.ConvertType(E->getType()));
+    return LValue();
   }
-
+  
   // Emit the RHS first.  __block variables need to have the rhs evaluated
   // first, plus this should improve codegen a little.
   OpInfo.RHS = Visit(E->getRHS());
@@ -1129,13 +1135,13 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
   OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
   OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
                                     E->getComputationLHSType());
-
+  
   // Expand the binary operator.
   Value *Result = (this->*Func)(OpInfo);
-
+  
   // Convert the result back to the LHS type.
   Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy);
-
+  
   // Store the result value into the LHS lvalue. Bit-fields are handled
   // specially because the result is altered by the store, i.e., [C99 6.5.16p1]
   // 'An assignment expression has the value of the left operand after the
@@ -1144,11 +1150,23 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
     if (!LHSLV.isVolatileQualified()) {
       CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy,
                                          &Result);
-      return Result;
+      BitFieldResult = Result;
+      return LHSLV;
     } else
       CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy);
   } else
     CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, LHSTy);
+  return LHSLV;
+}
+
+Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
+                      Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) {
+  bool Ignore = TestAndClearIgnoreResultAssign();
+  Value *BitFieldResult;
+  LValue LHSLV = EmitCompoundAssignLValue(E, Func, BitFieldResult);
+  if (BitFieldResult)
+    return BitFieldResult;
+  
   if (Ignore)
     return 0;
   return EmitLoadOfLValue(LHSLV, E->getType());
@@ -1914,3 +1932,53 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
   return LV;
 }
 
+
+LValue CodeGenFunction::EmitCompoundAssignOperatorLValue(
+                                            const CompoundAssignOperator *E) {
+  ScalarExprEmitter Scalar(*this);
+  Value *BitFieldResult = 0;
+  switch (E->getOpcode()) {
+#define COMPOUND_OP(Op)                                                       \
+    case BinaryOperator::Op##Assign:                                          \
+      return Scalar.EmitCompoundAssignLValue(E, &ScalarExprEmitter::Emit##Op, \
+                                             BitFieldResult)
+  COMPOUND_OP(Mul);
+  COMPOUND_OP(Div);
+  COMPOUND_OP(Rem);
+  COMPOUND_OP(Add);
+  COMPOUND_OP(Sub);
+  COMPOUND_OP(Shl);
+  COMPOUND_OP(Shr);
+  COMPOUND_OP(And);
+  COMPOUND_OP(Xor);
+  COMPOUND_OP(Or);
+#undef COMPOUND_OP
+      
+  case BinaryOperator::PtrMemD:
+  case BinaryOperator::PtrMemI:
+  case BinaryOperator::Mul:
+  case BinaryOperator::Div:
+  case BinaryOperator::Rem:
+  case BinaryOperator::Add:
+  case BinaryOperator::Sub:
+  case BinaryOperator::Shl:
+  case BinaryOperator::Shr:
+  case BinaryOperator::LT:
+  case BinaryOperator::GT:
+  case BinaryOperator::LE:
+  case BinaryOperator::GE:
+  case BinaryOperator::EQ:
+  case BinaryOperator::NE:
+  case BinaryOperator::And:
+  case BinaryOperator::Xor:
+  case BinaryOperator::Or:
+  case BinaryOperator::LAnd:
+  case BinaryOperator::LOr:
+  case BinaryOperator::Assign:
+  case BinaryOperator::Comma:
+    assert(false && "Not valid compound assignment operators");
+    break;
+  }
+   
+  llvm_unreachable("Unhandled compound assignment operator");
+}
index 302f9abd23508b4ad1eb7d3513e78669a9659a88..b421a38371ea3b9af2f10558cd5a98f020ce6eeb 100644 (file)
@@ -1043,6 +1043,7 @@ public:
 
   // Note: only availabe for agg return types
   LValue EmitBinaryOperatorLValue(const BinaryOperator *E);
+  LValue EmitCompoundAssignOperatorLValue(const CompoundAssignOperator *E);
   // Note: only available for agg return types
   LValue EmitCallExprLValue(const CallExpr *E);
   // Note: only available for agg return types
index 805fe8df698874f60ddb78258cd534d3b6f89c5a..c4b64e6e51addf1154436bc1977cf1c2feb579f1 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm-only -verify
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -verify -o - |FileCheck %s
 
 class x {
 public: int operator=(int);
@@ -7,3 +7,13 @@ void a() {
   x a;
   a = 1u;
 }
+
+void f(int i, int j) {
+  // CHECK: load i32
+  // CHECK: load i32
+  // CHECK: add nsw i32
+  // CHECK: store i32
+  // CHECK: store i32 17, i32
+  // CHECK: ret
+  (i += j) = 17;
+}