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). llvm-svn: 156580
This commit is contained in:
parent
4fe10a5d9a
commit
77cbb8481b
|
|
@ -302,6 +302,9 @@ public: // Part of public interface to class.
|
||||||
/// BindStruct - Bind a compound value to a structure.
|
/// BindStruct - Bind a compound value to a structure.
|
||||||
StoreRef BindStruct(Store store, const TypedValueRegion* R, SVal V);
|
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);
|
StoreRef BindArray(Store store, const TypedValueRegion* R, SVal V);
|
||||||
|
|
||||||
/// KillStruct - Set the entire struct to unknown.
|
/// KillStruct - Set the entire struct to unknown.
|
||||||
|
|
@ -372,7 +375,8 @@ public: // Part of public interface to class.
|
||||||
/// Get the state and region whose binding this region R corresponds to.
|
/// Get the state and region whose binding this region R corresponds to.
|
||||||
std::pair<Store, const MemRegion*>
|
std::pair<Store, const MemRegion*>
|
||||||
GetLazyBinding(RegionBindings B, const MemRegion *R,
|
GetLazyBinding(RegionBindings B, const MemRegion *R,
|
||||||
const MemRegion *originalRegion);
|
const MemRegion *originalRegion,
|
||||||
|
bool includeSuffix = false);
|
||||||
|
|
||||||
StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store,
|
StoreRef CopyLazyBindings(nonloc::LazyCompoundVal V, Store store,
|
||||||
const TypedRegion *R);
|
const TypedRegion *R);
|
||||||
|
|
@ -1108,7 +1112,8 @@ SVal RegionStoreManager::getBinding(Store store, Loc L, QualType T) {
|
||||||
|
|
||||||
std::pair<Store, const MemRegion *>
|
std::pair<Store, const MemRegion *>
|
||||||
RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
|
RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
|
||||||
const MemRegion *originalRegion) {
|
const MemRegion *originalRegion,
|
||||||
|
bool includeSuffix) {
|
||||||
|
|
||||||
if (originalRegion != R) {
|
if (originalRegion != R) {
|
||||||
if (Optional<SVal> OV = getDefaultBinding(B, R)) {
|
if (Optional<SVal> OV = getDefaultBinding(B, R)) {
|
||||||
|
|
@ -1130,9 +1135,13 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
|
||||||
const std::pair<Store, const MemRegion *> &X =
|
const std::pair<Store, const MemRegion *> &X =
|
||||||
GetLazyBinding(B, FR->getSuperRegion(), originalRegion);
|
GetLazyBinding(B, FR->getSuperRegion(), originalRegion);
|
||||||
|
|
||||||
if (X.second)
|
if (X.second) {
|
||||||
return std::make_pair(X.first,
|
if (includeSuffix)
|
||||||
MRMgr.getFieldRegionWithSuper(FR, X.second));
|
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
|
// 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.
|
// through to look for lazy compound value. It is like a field region.
|
||||||
|
|
@ -1141,9 +1150,13 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R,
|
||||||
const std::pair<Store, const MemRegion *> &X =
|
const std::pair<Store, const MemRegion *> &X =
|
||||||
GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion);
|
GetLazyBinding(B, baseReg->getSuperRegion(), originalRegion);
|
||||||
|
|
||||||
if (X.second)
|
if (X.second) {
|
||||||
return std::make_pair(X.first,
|
if (includeSuffix)
|
||||||
MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second));
|
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
|
// The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
|
||||||
|
|
@ -1492,9 +1505,13 @@ StoreRef RegionStoreManager::Bind(Store store, Loc L, SVal V) {
|
||||||
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
|
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
|
||||||
|
|
||||||
// Check if the region is a struct region.
|
// Check if the region is a struct region.
|
||||||
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R))
|
if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
|
||||||
if (TR->getValueType()->isStructureOrClassType())
|
QualType Ty = TR->getValueType();
|
||||||
|
if (Ty->isStructureOrClassType())
|
||||||
return BindStruct(store, TR, V);
|
return BindStruct(store, TR, V);
|
||||||
|
if (Ty->isVectorType())
|
||||||
|
return BindVector(store, TR, V);
|
||||||
|
}
|
||||||
|
|
||||||
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
|
||||||
if (ER->getIndex().isZeroConstant()) {
|
if (ER->getIndex().isZeroConstant()) {
|
||||||
|
|
@ -1638,6 +1655,47 @@ StoreRef RegionStoreManager::BindArray(Store store, const TypedValueRegion* R,
|
||||||
return newStore;
|
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,
|
StoreRef RegionStoreManager::BindStruct(Store store, const TypedValueRegion* R,
|
||||||
SVal V) {
|
SVal V) {
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue