summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprScalar.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-03-28 01:22:36 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-03-28 01:22:36 +0000
commit8b7b1b1aee8685c34130f7e4a8457a52558af034 (patch)
tree997b1bd6718354cc991f5ff9ef94c6a397e51c69 /clang/lib/CodeGen/CGExprScalar.cpp
parent0cb4cc106c263e9d5ae3253a4c08a552f6766b80 (diff)
downloadbcm5719-llvm-8b7b1b1aee8685c34130f7e4a8457a52558af034.tar.gz
bcm5719-llvm-8b7b1b1aee8685c34130f7e4a8457a52558af034.zip
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. llvm-svn: 67889
Diffstat (limited to 'clang/lib/CodeGen/CGExprScalar.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp79
1 files changed, 17 insertions, 62 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 89f28bea6d3..4f2371c4a18 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -768,76 +768,31 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
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
OpenPOWER on IntegriCloud