diff options
| author | Daniel Dunbar <daniel@zuster.org> | 2010-03-20 05:53:45 +0000 |
|---|---|---|
| committer | Daniel Dunbar <daniel@zuster.org> | 2010-03-20 05:53:45 +0000 |
| commit | 4c43e31d21f9921c3d4d7c1e3aa9cf5b41f71da8 (patch) | |
| tree | 4fe438692d0ab282818393d2098b05f0222cb5af /clang/lib/AST/ExprConstant.cpp | |
| parent | e46b52a35f066bed7b20692a53606e483abc862e (diff) | |
| download | bcm5719-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.cpp | 27 |
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) { |

