[cfe-commits] r102170 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenCXX/assign-operator.cpp

Douglas Gregor dgregor at apple.com
Thu Apr 22 21:16:32 PDT 2010


Author: dgregor
Date: Thu Apr 22 23:16:32 2010
New Revision: 102170

URL: http://llvm.org/viewvc/llvm-project?rev=102170&view=rev
Log:
Handle compound assignment expressions (i += j) as lvalues, which is
permitted in C++ but not in C. Fixes PR6900. Clang can now handle all
of Boost.Lambda's regression tests.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/assign-operator.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=102170&r1=102169&r2=102170&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Apr 22 23:16:32 2010
@@ -478,6 +478,8 @@
     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:

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=102170&r1=102169&r2=102170&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Apr 22 23:16:32 2010
@@ -314,6 +314,10 @@
   }
 
   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 @@
   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 @@
   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 @@
     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 @@
   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");
+}

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=102170&r1=102169&r2=102170&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Apr 22 23:16:32 2010
@@ -1043,6 +1043,7 @@
 
   // 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

Modified: cfe/trunk/test/CodeGenCXX/assign-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/assign-operator.cpp?rev=102170&r1=102169&r2=102170&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/assign-operator.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/assign-operator.cpp Thu Apr 22 23:16:32 2010
@@ -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 @@
   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;
+}





More information about the cfe-commits mailing list