summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-03-20 05:53:45 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-03-20 05:53:45 +0000
commit4c43e31d21f9921c3d4d7c1e3aa9cf5b41f71da8 (patch)
tree4fe438692d0ab282818393d2098b05f0222cb5af /clang/lib/AST/ExprConstant.cpp
parente46b52a35f066bed7b20692a53606e483abc862e (diff)
downloadbcm5719-llvm-4c43e31d21f9921c3d4d7c1e3aa9cf5b41f71da8.tar.gz
bcm5719-llvm-4c43e31d21f9921c3d4d7c1e3aa9cf5b41f71da8.zip
Evaluate: Fix a subtle bug in the pointer evaluator in which we would do an
expression computation in the wrong bit-width, and end up generating a totally bogus array reference (_g0+8589934546). - This showed up on Prolangs/cdecl. llvm-svn: 99042
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp27
1 files changed, 17 insertions, 10 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e03669246e8..eeeeb5c836b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -406,27 +406,34 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (!EvaluatePointer(PExp, ResultLValue, Info))
return APValue();
- llvm::APSInt AdditionalOffset(32);
+ llvm::APSInt AdditionalOffset;
if (!EvaluateInteger(IExp, AdditionalOffset, Info))
return APValue();
- QualType PointeeType = PExp->getType()->getAs<PointerType>()->getPointeeType();
- CharUnits SizeOfPointee;
+ // Compute the new offset in the appropriate width.
+
+ QualType PointeeType =
+ PExp->getType()->getAs<PointerType>()->getPointeeType();
+ llvm::APSInt SizeOfPointee(AdditionalOffset);
// Explicitly handle GNU void* and function pointer arithmetic extensions.
if (PointeeType->isVoidType() || PointeeType->isFunctionType())
- SizeOfPointee = CharUnits::One();
+ SizeOfPointee = 1;
else
- SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
-
- CharUnits Offset = ResultLValue.getLValueOffset();
+ SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType).getQuantity();
+ llvm::APSInt Offset(AdditionalOffset);
+ Offset = ResultLValue.getLValueOffset().getQuantity();
if (E->getOpcode() == BinaryOperator::Add)
- Offset += AdditionalOffset.getLimitedValue() * SizeOfPointee;
+ Offset += AdditionalOffset * SizeOfPointee;
else
- Offset -= AdditionalOffset.getLimitedValue() * SizeOfPointee;
+ Offset -= AdditionalOffset * SizeOfPointee;
- return APValue(ResultLValue.getLValueBase(), Offset);
+ // Sign extend prior to converting back to a char unit.
+ if (Offset.getBitWidth() < 64)
+ Offset.extend(64);
+ return APValue(ResultLValue.getLValueBase(),
+ CharUnits::fromQuantity(Offset.getLimitedValue()));
}
APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
OpenPOWER on IntegriCloud