summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-01-22 20:27:48 +0000
committerTed Kremenek <kremenek@apple.com>2009-01-22 20:27:48 +0000
commit92d48a71f551093efbbbd53f402c4257cf91f8d3 (patch)
tree565a0f0e2b8b0c95fe6b9104a8ce2db253fcfa38 /clang
parent483e12e09e0d9016a754be6c45e967435f8d31e0 (diff)
downloadbcm5719-llvm-92d48a71f551093efbbbd53f402c4257cf91f8d3.tar.gz
bcm5719-llvm-92d48a71f551093efbbbd53f402c4257cf91f8d3.zip
Fix RegionStore::getLValueElement() to handle the case when the base region is not an ElementRegion (also do some cleanups of its core logic).
This gets array-struct.c to work with RegionStore. llvm-svn: 62781
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Analysis/RegionStore.cpp87
-rw-r--r--clang/test/Analysis/array-struct.c5
-rw-r--r--clang/test/Analysis/outofbound.c2
3 files changed, 54 insertions, 40 deletions
diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp
index 5a13a1dbc25..6f0ec1d0b73 100644
--- a/clang/lib/Analysis/RegionStore.cpp
+++ b/clang/lib/Analysis/RegionStore.cpp
@@ -327,49 +327,62 @@ SVal RegionStoreManager::getLValueElement(const GRState* St,
if (Base.isUnknownOrUndef() || isa<loc::SymbolVal>(Base))
return Base;
- loc::MemRegionVal& BaseL = cast<loc::MemRegionVal>(Base);
-
- // Pointer of any type can be cast and used as array base. We do not support
- // that case yet.
- if (!isa<ElementRegion>(BaseL.getRegion())) {
- // Record what we have seen in real code.
- assert(isa<FieldRegion>(BaseL.getRegion()));
+ // Only handle integer offsets... for now.
+ if (!isa<nonloc::ConcreteInt>(Offset))
return UnknownVal();
- }
-
- // We expect BaseR is an ElementRegion, not a base VarRegion.
-
- const ElementRegion* ElemR = cast<ElementRegion>(BaseL.getRegion());
-
- SVal Idx = ElemR->getIndex();
- nonloc::ConcreteInt *CI1, *CI2;
+ const TypedRegion *BaseRegion =
+ cast<TypedRegion>(cast<loc::MemRegionVal>(Base).getRegion());
- // Only handle integer indices for now.
- if ((CI1 = dyn_cast<nonloc::ConcreteInt>(&Idx)) &&
- (CI2 = dyn_cast<nonloc::ConcreteInt>(&Offset))) {
-
- // Temporary SVal to hold a potential signed and extended APSInt.
- SVal SignedInt;
-
- // Index might be unsigned. We have to convert it to signed. It might also
- // be less wide than the size. We have to extend it.
- if (CI2->getValue().isUnsigned() ||
- CI2->getValue().getBitWidth() < CI1->getValue().getBitWidth()) {
- llvm::APSInt SI = CI2->getValue();
- if (CI2->getValue().getBitWidth() < CI1->getValue().getBitWidth())
- SI.extend(CI1->getValue().getBitWidth());
- SI.setIsSigned(true);
- SignedInt = nonloc::ConcreteInt(getBasicVals().getValue(SI));
- CI2 = cast<nonloc::ConcreteInt>(&SignedInt);
- }
+ // Pointer of any type can be cast and used as array base.
+ const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion);
+
+ if (!ElemR) {
+ //
+ // If the base region is not an ElementRegion, create one.
+ // This can happen in the following example:
+ //
+ // char *p = __builtin_alloc(10);
+ // p[1] = 8;
+ //
+ // Observe that 'p' binds to an AnonTypedRegion<AllocaRegion>.
+ //
+ return loc::MemRegionVal(MRMgr.getElementRegion(Offset, BaseRegion));
+ }
+
+ SVal BaseIdx = ElemR->getIndex();
+
+ if (!isa<nonloc::ConcreteInt>(BaseIdx))
+ return UnknownVal();
+
+ const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
+ const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
+ assert(BaseIdxI.isSigned());
+
+ // FIXME: This appears to be the assumption of this code. We should review
+ // whether or not BaseIdxI.getBitWidth() < OffI.getBitWidth(). If it
+ // can't we need to put a comment here. If it can, we should handle it.
+ assert(BaseIdxI.getBitWidth() >= OffI.getBitWidth());
- SVal NewIdx = CI1->EvalBinOp(getBasicVals(), BinaryOperator::Add, *CI2);
- return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx,
- ElemR->getArrayRegion()));
+ const TypedRegion *ArrayR = ElemR->getArrayRegion();
+ SVal NewIdx;
+
+ if (OffI.isUnsigned() || OffI.getBitWidth() < BaseIdxI.getBitWidth()) {
+ // 'Offset' might be unsigned. We have to convert it to signed and
+ // possibly extend it.
+ llvm::APSInt Tmp = OffI;
+
+ if (OffI.getBitWidth() < BaseIdxI.getBitWidth())
+ Tmp.extend(BaseIdxI.getBitWidth());
+
+ Tmp.setIsSigned(true);
+ Tmp += BaseIdxI; // Compute the new offset.
+ NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(Tmp));
}
+ else
+ NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
- return UnknownVal();
+ return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx, ArrayR));
}
SVal RegionStoreManager::getSizeInElements(const GRState* St,
diff --git a/clang/test/Analysis/array-struct.c b/clang/test/Analysis/array-struct.c
index 1d5e9448e92..4257220f9bd 100644
--- a/clang/test/Analysis/array-struct.c
+++ b/clang/test/Analysis/array-struct.c
@@ -1,5 +1,6 @@
-// RUN: clang -analyze -checker-simple -verify %s
-// DISABLE: clang -analyze -checker-simple -analyzer-store-region -verify %s
+// RUN: clang -analyze -checker-simple -analyzer-store-basic -verify %s &&
+// RUN: clang -analyze -checker-cfref -analyzer-store-basic -verify %s &&
+// RUN: clang -analyze -checker-cfref -analyzer-store-region -verify %s
struct s {
int data;
diff --git a/clang/test/Analysis/outofbound.c b/clang/test/Analysis/outofbound.c
index ab9c0cfa4c8..b0c2db43862 100644
--- a/clang/test/Analysis/outofbound.c
+++ b/clang/test/Analysis/outofbound.c
@@ -2,5 +2,5 @@
char f1() {
char* s = "abcd";
- return s[5]; // expected-warning{{Load or store into an out-of-bound memory position.}}
+ return s[6]; // expected-warning{{Load or store into an out-of-bound memory position.}}
}
OpenPOWER on IntegriCloud