aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/RegionStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp64
1 files changed, 43 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 6559e11327..f75ab0280b 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -497,8 +497,11 @@ public: // Part of public interface to class.
const TypedValueRegion *R,
QualType Ty);
- /// Get the state and region whose binding this region R corresponds to.
- std::pair<Store, const MemRegion*>
+ /// Get the state and region whose binding this region \p R corresponds to.
+ ///
+ /// If there is no lazy binding for \p R, the returned value will have a null
+ /// \c second. Note that a null pointer can represents a valid Store.
+ std::pair<Store, const MemRegion *>
getLazyBinding(RegionBindingsConstRef B, const MemRegion *R,
const MemRegion *originalRegion);
@@ -1256,49 +1259,68 @@ std::pair<Store, const MemRegion *>
RegionStoreManager::getLazyBinding(RegionBindingsConstRef B,
const MemRegion *R,
const MemRegion *originalRegion) {
+ typedef std::pair<Store, const MemRegion *> StoreRegionPair;
+
if (originalRegion != R) {
if (Optional<SVal> OV = B.getDefaultBinding(R)) {
if (const nonloc::LazyCompoundVal *V =
- dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
+ dyn_cast<nonloc::LazyCompoundVal>(OV.getPointer()))
return std::make_pair(V->getStore(), V->getRegion());
}
}
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
- const std::pair<Store, const MemRegion *> &X =
- getLazyBinding(B, ER->getSuperRegion(), originalRegion);
+ StoreRegionPair X = getLazyBinding(B, ER->getSuperRegion(), originalRegion);
if (X.second)
return std::make_pair(X.first,
MRMgr.getElementRegionWithSuper(ER, X.second));
}
else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
- const std::pair<Store, const MemRegion *> &X =
- getLazyBinding(B, FR->getSuperRegion(), originalRegion);
+ StoreRegionPair X = getLazyBinding(B, FR->getSuperRegion(), originalRegion);
if (X.second) {
return std::make_pair(X.first,
MRMgr.getFieldRegionWithSuper(FR, X.second));
}
- }
- // 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.
- else if (const CXXBaseObjectRegion *baseReg =
- dyn_cast<CXXBaseObjectRegion>(R)) {
- const std::pair<Store, const MemRegion *> &X =
- getLazyBinding(B, baseReg->getSuperRegion(), originalRegion);
+ } else if (const CXXBaseObjectRegion *BaseReg =
+ dyn_cast<CXXBaseObjectRegion>(R)) {
+ // 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.
+ StoreRegionPair Result = getLazyBinding(B, BaseReg->getSuperRegion(),
+ originalRegion);
- if (X.second) {
- return std::make_pair(X.first,
- MRMgr.getCXXBaseObjectRegionWithSuper(baseReg,
- X.second));
+ if (Result.second) {
+ // Make sure the types match up.
+ const CXXRecordDecl *LazyD = 0;
+ if (const TypedValueRegion *LazyR =
+ dyn_cast<TypedValueRegion>(Result.second)) {
+ LazyD = LazyR->getValueType()->getAsCXXRecordDecl();
+ if (LazyD)
+ LazyD = LazyD->getCanonicalDecl();
+ }
+
+ typedef SmallVector<const CXXBaseObjectRegion *, 4> BaseListTy;
+ BaseListTy BaseRegions;
+ do {
+ BaseRegions.push_back(BaseReg);
+ BaseReg = dyn_cast<CXXBaseObjectRegion>(BaseReg->getSuperRegion());
+ } while (BaseReg && LazyD != BaseReg->getDecl()->getCanonicalDecl());
+
+ // Layer the base regions on the result in least-to-most derived order.
+ for (BaseListTy::const_reverse_iterator I = BaseRegions.rbegin(),
+ E = BaseRegions.rend();
+ I != E; ++I) {
+ Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(*I,
+ Result.second);
+ }
}
+
+ return Result;
}
- // The NULL MemRegion indicates an non-existent lazy binding. A NULL Store is
- // possible for a valid lazy binding.
- return std::make_pair((Store) 0, (const MemRegion *) 0);
+ return StoreRegionPair();
}
SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,