[cfe-commits] r156580 - /cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
Ted Kremenek
kremenek at apple.com
Thu May 10 15:02:39 PDT 2012
Author: kremenek
Date: Thu May 10 17:02:39 2012
New Revision: 156580
URL: http://llvm.org/viewvc/llvm-project?rev=156580&view=rev
Log:
Fix insidious RegionStore bug where we (a) didn't handle vector types and (b) had
a horrible bug in GetLazyBindings where we falsely appended a field suffix when traversing 3 or more
layers of lazy bindings. I don't have a reduced test case yet; but I have added the original source
to an internal regression test suite. I'll see about coming up with a reduced test case.
Fixes <rdar://problem/11405978> (for real).
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=156580&r1=156579&r2=156580&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Thu May 10 17:02:39 2012
@@ -302,6 +302,9 @@
/// BindStruct - Bind a compound value to a structure.
StoreRef BindStruct(Store store, const TypedValueRegion* R, SVal V);
+ /// BindVector - Bind a compound value to a vector.
+ StoreRef BindVector(Store store, const TypedValueRegion* R, SVal V);
+
StoreRef BindArray(Store store, const TypedValueRegion* R, SVal V);
/// KillStruct - Set the entire struct to unknown.
@@ -372,7 +375,8 @@
/// Get the state and region whose binding this region R corresponds to.
std::pair<Store, const MemRegion*>
GetLazyBinding(RegionBindings B, const MemRegion *R,
- const MemRegion *originalRegion);
+ const MemRegion *originalRegion,
+ bool includeSuffix = false);
StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store,
const TypedRegion *R);
@@ -1108,7 +1112,8 @@
std::pair<Store, const MemRegion *>
RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
- const MemRegion *originalRegion) {
+ const MemRegion *originalRegion,
+ bool includeSuffix) {
if (originalRegion != R) {
if (Optional<SVal> OV = getDefaultBinding(B, R)) {
@@ -1130,9 +1135,13 @@
const std::pair<Store, const MemRegion *> &X =
GetLazyBinding(B, FR->getSuperRegion(), originalRegion);
- if (X.second)
- return std::make_pair(X.first,
- MRMgr.getFieldRegionWithSuper(FR, X.second));
+ if (X.second) {
+ if (includeSuffix)
+ return std::make_pair(X.first,
+ MRMgr.getFieldRegionWithSuper(FR, X.second));
+ return X;
+ }
+
}
// C++ base object region is another kind of region that we should blast
// through to look for lazy compound value. It is like a field region.
@@ -1141,9 +1150,13 @@
const std::pair<Store, const MemRegion *> &X =
GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion);
- if (X.second)
- return std::make_pair(X.first,
- MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second));
+ if (X.second) {
+ if (includeSuffix)
+ return std::make_pair(X.first,
+ MRMgr.getCXXBaseObjectRegionWithSuper(baseReg,
+ X.second));
+ return X;
+ }
}
// The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
@@ -1492,9 +1505,13 @@
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
// Check if the region is a struct region.
- if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R))
- if (TR->getValueType()->isStructureOrClassType())
+ if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
+ QualType Ty = TR->getValueType();
+ if (Ty->isStructureOrClassType())
return BindStruct(store, TR, V);
+ if (Ty->isVectorType())
+ return BindVector(store, TR, V);
+ }
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
if (ER->getIndex().isZeroConstant()) {
@@ -1638,6 +1655,47 @@
return newStore;
}
+StoreRef RegionStoreManager::BindVector(Store store, const TypedValueRegion* R,
+ SVal V) {
+ QualType T = R->getValueType();
+ assert(T->isVectorType());
+ const VectorType *VT = T->getAs<VectorType>(); // Use getAs for typedefs.
+
+ // Handle lazy compound values.
+ if (nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&V))
+ return CopyLazyBindings(*LCV, store, R);
+
+ // We may get non-CompoundVal accidentally due to imprecise cast logic or
+ // that we are binding symbolic struct value. Kill the field values, and if
+ // the value is symbolic go and bind it as a "default" binding.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
+ SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
+ return KillStruct(store, R, SV);
+ }
+
+ QualType ElemType = VT->getElementType();
+ nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
+ nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
+ unsigned index = 0, numElements = VT->getNumElements();
+ StoreRef newStore(store, *this);
+
+ for ( ; index != numElements ; ++index) {
+ if (VI == VE)
+ break;
+
+ NonLoc Idx = svalBuilder.makeArrayIndex(index);
+ const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
+
+ if (ElemType->isArrayType())
+ newStore = BindArray(newStore.getStore(), ER, *VI);
+ else if (ElemType->isStructureOrClassType())
+ newStore = BindStruct(newStore.getStore(), ER, *VI);
+ else
+ newStore = Bind(newStore.getStore(), svalBuilder.makeLoc(ER), *VI);
+ }
+ return newStore;
+}
+
StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R,
SVal V) {
More information about the cfe-commits
mailing list