mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 18:16:04 +00:00
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. llvm-svn: 102170
This commit is contained in:
parent
11373b5277
commit
914af2182b
@ -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:
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user