forked from OSchip/llvm-project
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
This commit is contained in:
parent
e46b52a35f
commit
4c43e31d21
|
@ -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) {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
|
||||
// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 8 ; <[2 x i8*]*> [#uses=0]
|
||||
|
||||
extern struct { unsigned char a, b; } g0[];
|
||||
void *g1[] = {g0 + -1, g0 + -23 };
|
||||
void *g2[] = {g0 - 1, g0 - 23 };
|
Loading…
Reference in New Issue