[cfe-commits] r67889 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/StmtDumper.cpp lib/AST/StmtSerialization.cpp lib/Analysis/GRExprEngine.cpp lib/CodeGen/CGExprComplex.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp test/CodeGen/complex.c test/CodeGen/compound-type.c

Eli Friedman eli.friedman at gmail.com
Fri Mar 27 18:22:36 PDT 2009


Author: efriedma
Date: Fri Mar 27 20:22:36 2009
New Revision: 67889

URL: http://llvm.org/viewvc/llvm-project?rev=67889&view=rev
Log:
Change compound assignment operators to keep track of both the promoted 
LHS type and the computation result type; this encodes information into 
the AST which is otherwise non-obvious.  Fix Sema to always come up with the 
right answer for both of these types.  Fix IRGen and the analyzer to 
account for these changes.  This fixes PR2601.  The approach is inspired 
by PR2601 comment 2.

Note that this changes real *= complex in CodeGen from a silent 
miscompilation to an explicit error.

I'm not really sure that the analyzer changes are correct, or how to 
test them... someone more familiar with the analyzer should check those 
changes.


Added:
    cfe/trunk/test/CodeGen/compound-type.c
Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/StmtDumper.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CodeGen/complex.c

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Mar 27 20:22:36 2009
@@ -1324,18 +1324,25 @@
 /// place.  This captures the intermediate type which the computation is done
 /// in.
 class CompoundAssignOperator : public BinaryOperator {
-  QualType ComputationType;
+  QualType ComputationLHSType;
+  QualType ComputationResultType;
 public:
   CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc,
-                         QualType ResType, QualType CompType,
+                         QualType ResType, QualType CompLHSType,
+                         QualType CompResultType,
                          SourceLocation OpLoc)
     : BinaryOperator(lhs, rhs, opc, ResType, OpLoc, true),
-      ComputationType(CompType) {
+      ComputationLHSType(CompLHSType),
+      ComputationResultType(CompResultType) {
     assert(isCompoundAssignmentOp() && 
            "Only should be used for compound assignments");
   }
 
-  QualType getComputationType() const { return ComputationType; }
+  // The two computation types are the type the LHS is converted
+  // to for the computation and the type of the result; the two are
+  // distinct in a few cases (specifically, int+=ptr and ptr-=ptr).
+  QualType getComputationLHSType() const { return ComputationLHSType; }
+  QualType getComputationResultType() const { return ComputationResultType; }
   
   static bool classof(const CompoundAssignOperator *) { return true; }
   static bool classof(const Stmt *S) { 

Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Fri Mar 27 20:22:36 2009
@@ -405,9 +405,11 @@
 }
 void StmtDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
   DumpExpr(Node);
-  fprintf(F, " '%s' ComputeTy=",
+  fprintf(F, " '%s' ComputeLHSTy=",
           BinaryOperator::getOpcodeStr(Node->getOpcode()));
-  DumpType(Node->getComputationType());
+  DumpType(Node->getComputationLHSType());
+  fprintf(F, " ComputeResultTy=");
+  DumpType(Node->getComputationResultType());
 }
 
 // GNU extensions.

Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Fri Mar 27 20:22:36 2009
@@ -456,7 +456,8 @@
 
 void CompoundAssignOperator::EmitImpl(Serializer& S) const {
   S.Emit(getType());
-  S.Emit(ComputationType);
+  S.Emit(ComputationLHSType);
+  S.Emit(ComputationResultType);
   S.Emit(getOperatorLoc());
   S.EmitInt(getOpcode());
   S.BatchEmitOwnedPtrs(getLHS(),getRHS());
@@ -465,14 +466,15 @@
 CompoundAssignOperator* 
 CompoundAssignOperator::CreateImpl(Deserializer& D, ASTContext& C) {
   QualType t = QualType::ReadVal(D);
-  QualType c = QualType::ReadVal(D);
+  QualType cl = QualType::ReadVal(D);
+  QualType cr = QualType::ReadVal(D);
   SourceLocation L = SourceLocation::ReadVal(D);
   Opcode Opc = static_cast<Opcode>(D.ReadInt());
   Expr* LHS, *RHS;
   D.BatchReadOwnedPtrs(LHS, RHS, C);
   
   return new (C, llvm::alignof<CompoundAssignOperator>())
-    CompoundAssignOperator(LHS,RHS,Opc,t,c,L);
+    CompoundAssignOperator(LHS,RHS,Opc,t,cl,cr,L);
 }
 
 void CompoundLiteralExpr::EmitImpl(Serializer& S) const {

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Mar 27 20:22:36 2009
@@ -2810,16 +2810,18 @@
         //  The RHS is not Unknown.
         
         // Get the computation type.
-        QualType CTy = cast<CompoundAssignOperator>(B)->getComputationType();
+        QualType CTy = cast<CompoundAssignOperator>(B)->getComputationResultType();
         CTy = getContext().getCanonicalType(CTy);
-        
+
+        QualType CLHSTy = cast<CompoundAssignOperator>(B)->getComputationLHSType();
+        CLHSTy = getContext().getCanonicalType(CTy);
+
         QualType LTy = getContext().getCanonicalType(LHS->getType());
         QualType RTy = getContext().getCanonicalType(RHS->getType());
-          
-        // Perform promotions.
-        if (LTy != CTy) V = EvalCast(V, CTy);
-        if (RTy != CTy) RightV = EvalCast(RightV, CTy);
-          
+
+        // Promote LHS.
+        V = EvalCast(V, CLHSTy);
+
         // Evaluate operands and promote to result type.                    
         if (RightV.isUndef()) {            
           // Propagate undefined values (right-side).          

Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Fri Mar 27 20:22:36 2009
@@ -419,7 +419,7 @@
   LValue LHSLV = CGF.EmitLValue(E->getLHS());
 
   BinOpInfo OpInfo;
-  OpInfo.Ty = E->getComputationType();
+  OpInfo.Ty = E->getComputationResultType();
 
   // We know the LHS is a complex lvalue.
   OpInfo.LHS = EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified());

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Fri Mar 27 20:22:36 2009
@@ -768,76 +768,31 @@
 
   BinOpInfo OpInfo;
 
-  // Load the LHS and RHS operands.
-  LValue LHSLV = EmitLValue(E->getLHS());
-  OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
-
-  // Determine the computation type.  If the RHS is complex, then this is one of
-  // the add/sub/mul/div operators.  All of these operators can be computed in
-  // with just their real component even though the computation domain really is
-  // complex.
-  QualType ComputeType = E->getComputationType();
-  
-  // If the computation type is complex, then the RHS is complex.  Emit the RHS.
-  if (const ComplexType *CT = ComputeType->getAsComplexType()) {
-    ComputeType = CT->getElementType();
-    
-    // Emit the RHS, only keeping the real component.
-    OpInfo.RHS = CGF.EmitComplexExpr(E->getRHS()).first;
-    RHSTy = RHSTy->getAsComplexType()->getElementType();
-  } else {
-    // Otherwise the RHS is a simple scalar value.
-    OpInfo.RHS = Visit(E->getRHS());
-  }
-  
-  QualType LComputeTy, RComputeTy, ResultTy;
-
-  // Compound assignment does not contain enough information about all
-  // the types involved for pointer arithmetic cases. Figure it out
-  // here for now.
-  if (E->getLHS()->getType()->isPointerType()) {
-    // Pointer arithmetic cases: ptr +=,-= int and ptr -= ptr, 
-    assert((E->getOpcode() == BinaryOperator::AddAssign ||
-            E->getOpcode() == BinaryOperator::SubAssign) &&
-           "Invalid compound assignment operator on pointer type.");
-    LComputeTy = E->getLHS()->getType();
-    
-    if (E->getRHS()->getType()->isPointerType()) {    
-      // Degenerate case of (ptr -= ptr) allowed by GCC implicit cast
-      // extension, the conversion from the pointer difference back to
-      // the LHS type is handled at the end.
-      assert(E->getOpcode() == BinaryOperator::SubAssign &&
-             "Invalid compound assignment operator on pointer type.");
-      RComputeTy = E->getLHS()->getType();
-      ResultTy = CGF.getContext().getPointerDiffType();
-    } else {
-      RComputeTy = E->getRHS()->getType();
-      ResultTy = LComputeTy;
-    }
-  } else if (E->getRHS()->getType()->isPointerType()) {
-    // Degenerate case of (int += ptr) allowed by GCC implicit cast
-    // extension.
-    assert(E->getOpcode() == BinaryOperator::AddAssign &&
-           "Invalid compound assignment operator on pointer type.");
-    LComputeTy = E->getLHS()->getType();
-    RComputeTy = E->getRHS()->getType();
-    ResultTy = RComputeTy;
-  } else {
-    LComputeTy = RComputeTy = ResultTy = ComputeType;
+  if (E->getComputationResultType()->isAnyComplexType()) {
+    // FIXME: 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()));
   }
 
-  // Convert the LHS/RHS values to the computation type.
-  OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, LComputeTy);
-  OpInfo.RHS = EmitScalarConversion(OpInfo.RHS, RHSTy, RComputeTy);
-  OpInfo.Ty = ResultTy;
+  // Load/convert the LHS.
+  LValue LHSLV = EmitLValue(E->getLHS());
+  OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy);
+  OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy,
+                                    E->getComputationLHSType());
+  // Emit the RHS.
+  OpInfo.RHS = Visit(E->getRHS());
+  OpInfo.Ty = E->getComputationResultType();
   OpInfo.E = E;
   
   // Expand the binary operator.
   Value *Result = (this->*Func)(OpInfo);
   
   // Convert the result back to the LHS type.
-  Result = EmitScalarConversion(Result, ResultTy, LHSTy);
-  
+  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

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Mar 27 20:22:36 2009
@@ -2297,9 +2297,9 @@
   QualType CheckRemainderOperands( // C99 6.5.5
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   QualType CheckAdditionOperands( // C99 6.5.6
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
   QualType CheckSubtractionOperands( // C99 6.5.6
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0);
   QualType CheckShiftOperands( // C99 6.5.7
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   QualType CheckCompareOperands( // C99 6.5.8/9

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 27 20:22:36 2009
@@ -174,10 +174,10 @@
 /// GCC.
 QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
                                           bool isCompAssign) {
-  if (!isCompAssign) {
+  if (!isCompAssign)
     UsualUnaryConversions(lhsExpr);
-    UsualUnaryConversions(rhsExpr);
-  }
+
+  UsualUnaryConversions(rhsExpr);
 
   // For conversion purposes, we ignore any qualifiers. 
   // For example, "const float" and "float" are equivalent.
@@ -196,10 +196,9 @@
     return lhs;
 
   QualType destType = UsualArithmeticConversionsType(lhs, rhs);
-  if (!isCompAssign) {
+  if (!isCompAssign)
     ImpCastExprToType(lhsExpr, destType);
-    ImpCastExprToType(rhsExpr, destType);
-  }
+  ImpCastExprToType(rhsExpr, destType);
   return destType;
 }
 
@@ -3147,16 +3146,22 @@
 }
 
 inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
-  Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign)
+  Expr *&lex, Expr *&rex, SourceLocation Loc, QualType* CompLHSTy)
 {
-  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
-    return CheckVectorOperands(Loc, lex, rex);
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(Loc, lex, rex);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
 
-  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+  QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
 
   // handle the common case first (both operands are arithmetic).
-  if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+  if (lex->getType()->isArithmeticType() &&
+      rex->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
     return compType;
+  }
 
   // Put any potential pointer into PExp
   Expr* PExp = lex, *IExp = rex;
@@ -3193,6 +3198,12 @@
                                      lex->getType()))
         return QualType();
 
+      if (CompLHSTy) {
+        QualType LHSTy = lex->getType();
+        if (LHSTy->isPromotableIntegerType())
+          LHSTy = Context.IntTy;
+        *CompLHSTy = LHSTy;
+      }
       return PExp->getType();
     }
   }
@@ -3202,17 +3213,22 @@
 
 // C99 6.5.6
 QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
-                                        SourceLocation Loc, bool isCompAssign) {
-  if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
-    return CheckVectorOperands(Loc, lex, rex);
+                                        SourceLocation Loc, QualType* CompLHSTy) {
+  if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+    QualType compType = CheckVectorOperands(Loc, lex, rex);
+    if (CompLHSTy) *CompLHSTy = compType;
+    return compType;
+  }
 
-  QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
+  QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy);
 
   // Enforce type constraints: C99 6.5.6p3.
 
   // Handle the common case first (both operands are arithmetic).
-  if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
+  if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) {
+    if (CompLHSTy) *CompLHSTy = compType;
     return compType;
+  }
 
   // Either ptr - int   or   ptr - ptr.
   if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
@@ -3258,6 +3274,7 @@
           << ComplainAboutFunc->getType() 
           << ComplainAboutFunc->getSourceRange();
 
+      if (CompLHSTy) *CompLHSTy = lex->getType();
       return lex->getType();
     }
 
@@ -3310,7 +3327,8 @@
         Diag(Loc, diag::ext_gnu_ptr_func_arith)
           << ComplainAboutFunc->getType() 
           << ComplainAboutFunc->getSourceRange();
-        
+
+      if (CompLHSTy) *CompLHSTy = lex->getType();
       return Context.getPointerDiffType();
     }
   }
@@ -3327,12 +3345,18 @@
 
   // Shifts don't perform usual arithmetic conversions, they just do integer
   // promotions on each operand. C99 6.5.7p3
+  QualType LHSTy;
+  if (lex->getType()->isPromotableIntegerType())
+    LHSTy = Context.IntTy;
+  else
+    LHSTy = lex->getType();
   if (!isCompAssign)
-    UsualUnaryConversions(lex);
+    ImpCastExprToType(lex, LHSTy);
+
   UsualUnaryConversions(rex);
 
   // "The type of the result is that of the promoted left operand."
-  return lex->getType();
+  return LHSTy;
 }
 
 // C99 6.5.8
@@ -4049,9 +4073,11 @@
 Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
                                                   unsigned Op,
                                                   Expr *lhs, Expr *rhs) {
-  QualType ResultTy;  // Result type of the binary operator.
-  QualType CompTy;    // Computation type for compound assignments (e.g. '+=')
+  QualType ResultTy;     // Result type of the binary operator.
   BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op;
+  // The following two variables are used for compound assignment operators
+  QualType CompLHSTy;    // Type of LHS after promotions for computation
+  QualType CompResultTy; // Type of computation result
 
   switch (Opc) {
   case BinaryOperator::Assign:
@@ -4100,37 +4126,41 @@
     break;
   case BinaryOperator::MulAssign:
   case BinaryOperator::DivAssign:
-    CompTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::RemAssign:
-    CompTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::AddAssign:
-    CompTy = CheckAdditionOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::SubAssign:
-    CompTy = CheckSubtractionOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::ShlAssign:
   case BinaryOperator::ShrAssign:
-    CompTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::AndAssign:
   case BinaryOperator::XorAssign:
   case BinaryOperator::OrAssign:
-    CompTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
-    if (!CompTy.isNull())
-      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompTy);
+    CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
+    CompLHSTy = CompResultTy;
+    if (!CompResultTy.isNull())
+      ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
     break;
   case BinaryOperator::Comma:
     ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
@@ -4138,11 +4168,12 @@
   }
   if (ResultTy.isNull())
     return ExprError();
-  if (CompTy.isNull())
+  if (CompResultTy.isNull())
     return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc));
   else
     return Owned(new (Context) CompoundAssignOperator(lhs, rhs, Opc, ResultTy,
-                                                      CompTy, OpLoc));
+                                                      CompLHSTy, CompResultTy,
+                                                      OpLoc));
 }
 
 // Binary Operators.  'Tok' is the token for the operator.

Modified: cfe/trunk/test/CodeGen/complex.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/complex.c?rev=67889&r1=67888&r2=67889&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/complex.c (original)
+++ cfe/trunk/test/CodeGen/complex.c Fri Mar 27 20:22:36 2009
@@ -32,7 +32,8 @@
   double Gr = __real g1;
 
   cf += D;
-  D += cf;
+  // FIXME: Currently unsupported!
+  //D += cf;
   cf /= g1;
   g1 = g1 + D;
   g1 = D + g1;

Added: cfe/trunk/test/CodeGen/compound-type.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/compound-type.c?rev=67889&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/compound-type.c (added)
+++ cfe/trunk/test/CodeGen/compound-type.c Fri Mar 27 20:22:36 2009
@@ -0,0 +1,7 @@
+// RUN: clang-cc < %s -emit-llvm -triple i686-pc-linux-gnu > %t &&
+// RUN: grep "div i32" %t &&
+// RUN: grep "shl i32" %t
+
+unsigned char a,b;
+void c(void) {a <<= b;}
+void d(void) {a /= b;}





More information about the cfe-commits mailing list