Fix failure reported by Sebastian of test/Analysis/ptr-arith.c when the target
is 64-bit. I used his suggestion of doing a direct bitwidth/signedness conversion of the 'offset' instead of just changing the sign. For more information, see: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2009-March/004587.html llvm-svn: 66892
This commit is contained in:
parent
201217324a
commit
ec94f08dce
|
@ -76,16 +76,18 @@ public:
|
|||
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
|
||||
const llvm::APSInt& getValue(uint64_t X, QualType T);
|
||||
|
||||
const llvm::APSInt& ConvertSignedness(const llvm::APSInt& To,
|
||||
const llvm::APSInt& From) {
|
||||
assert(To.getBitWidth() == From.getBitWidth());
|
||||
|
||||
// Same sign? Just return.
|
||||
if (To.isUnsigned() == From.isUnsigned())
|
||||
/// Convert - Create a new persistent APSInt with the same value as 'From'
|
||||
/// but with the bitwidth and signeness of 'To'.
|
||||
const llvm::APSInt& Convert(const llvm::APSInt& To,
|
||||
const llvm::APSInt& From) {
|
||||
|
||||
if (To.isUnsigned() == From.isUnsigned() &&
|
||||
To.getBitWidth() == From.getBitWidth())
|
||||
return From;
|
||||
|
||||
// Convert!
|
||||
return getValue(llvm::APSInt((llvm::APInt&) From, To.isUnsigned()));
|
||||
return getValue(From.getSExtValue(),
|
||||
To.getBitWidth(),
|
||||
To.isUnsigned());
|
||||
}
|
||||
|
||||
const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
|
||||
|
|
|
@ -642,12 +642,13 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) {
|
|||
|
||||
// Only support concrete integer indexes for now.
|
||||
if (Base && Offset) {
|
||||
// For now, convert the signedness of offset in case it doesn't match.
|
||||
const llvm::APSInt &I =
|
||||
getBasicVals().ConvertSignedness(Base->getValue(), Offset->getValue());
|
||||
nonloc::ConcreteInt OffsetConverted(I);
|
||||
|
||||
SVal NewIdx = Base->EvalBinOp(getBasicVals(), Op, OffsetConverted);
|
||||
// FIXME: For now, convert the signedness and bitwidth of offset in case
|
||||
// they don't match. This can result from pointer arithmetic. In reality,
|
||||
// we should figure out what are the proper semantics and implement them.
|
||||
//
|
||||
nonloc::ConcreteInt OffConverted(getBasicVals().Convert(Base->getValue(),
|
||||
Offset->getValue()));
|
||||
SVal NewIdx = Base->EvalBinOp(getBasicVals(), Op, OffConverted);
|
||||
const MemRegion* NewER = MRMgr.getElementRegion(NewIdx,
|
||||
ER->getArrayRegion());
|
||||
return Loc::MakeVal(NewER);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// RUN: clang -analyze -checker-simple -analyzer-store=region -verify %s
|
||||
// RUN: clang -analyze -checker-simple -analyzer-store=region -verify %s &&
|
||||
// RUN: clang -analyze -checker-cfref -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s &&
|
||||
// RUN: clang -analyze -checker-cfref -analyzer-store=region -verify -triple i686-apple-darwin9 %s
|
||||
|
||||
void f1() {
|
||||
int a[10];
|
||||
|
|
Loading…
Reference in New Issue