aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/BasicValueFactory.h18
-rw-r--r--lib/Analysis/RegionStore.cpp13
-rw-r--r--test/Analysis/ptr-arith.c4
3 files changed, 20 insertions, 15 deletions
diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
index 18ae1d88e4..c0a28c3fd1 100644
--- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h
+++ b/include/clang/Analysis/PathSensitive/BasicValueFactory.h
@@ -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) {
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index fbaa302d31..5f1c39c2b6 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -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);
diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c
index 11c8708dcf..87c3eb8dfe 100644
--- a/test/Analysis/ptr-arith.c
+++ b/test/Analysis/ptr-arith.c
@@ -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];