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.cpp59
1 files changed, 25 insertions, 34 deletions
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 06218664f7..61518e6116 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -475,9 +475,9 @@ public: // Part of public interface to class.
/// struct s x, y;
/// x = y;
/// y's value is retrieved by this method.
- SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion* R);
-
- SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion* R);
+ SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R);
+ SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion *R);
+ NonLoc createLazyBinding(RegionBindingsConstRef B, const TypedValueRegion *R);
/// Used to lazily generate derived symbols for bindings that are defined
/// implicitly by default bindings in a super region.
@@ -1551,48 +1551,39 @@ SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
return svalBuilder.getRegionValueSymbolVal(R);
}
-static bool mayHaveLazyBinding(QualType Ty) {
- return Ty->isArrayType() || Ty->isStructureOrClassType();
+NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
+ const TypedValueRegion *R) {
+ // If we already have a lazy binding, and it's for the whole structure,
+ // don't create a new lazy binding.
+ if (Optional<SVal> V = B.getDefaultBinding(R)) {
+ const nonloc::LazyCompoundVal *LCV =
+ dyn_cast<nonloc::LazyCompoundVal>(V.getPointer());
+ if (LCV) {
+ QualType RegionTy = R->getValueType();
+ QualType SourceRegionTy = LCV->getRegion()->getValueType();
+ if (RegionTy.getCanonicalType() == SourceRegionTy.getCanonicalType())
+ return *LCV;
+ }
+ }
+
+ return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
}
SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
- const TypedValueRegion* R) {
+ const TypedValueRegion *R) {
const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl();
if (RD->field_empty())
return UnknownVal();
- // If we already have a lazy binding, don't create a new one,
- // unless the first field might have a lazy binding of its own.
- // (Right now we can't tell the difference.)
- QualType FirstFieldType = RD->field_begin()->getType();
- if (!mayHaveLazyBinding(FirstFieldType)) {
- BindingKey K = BindingKey::Make(R, BindingKey::Default);
- if (const nonloc::LazyCompoundVal *V =
- dyn_cast_or_null<nonloc::LazyCompoundVal>(B.lookup(K))) {
- return *V;
- }
- }
-
- return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
+ return createLazyBinding(B, R);
}
SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
- const TypedValueRegion * R) {
- const ConstantArrayType *Ty = Ctx.getAsConstantArrayType(R->getValueType());
- assert(Ty && "Only constant array types can have compound bindings.");
+ const TypedValueRegion *R) {
+ assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
+ "Only constant array types can have compound bindings.");
- // If we already have a lazy binding, don't create a new one,
- // unless the first element might have a lazy binding of its own.
- // (Right now we can't tell the difference.)
- if (!mayHaveLazyBinding(Ty->getElementType())) {
- BindingKey K = BindingKey::Make(R, BindingKey::Default);
- if (const nonloc::LazyCompoundVal *V =
- dyn_cast_or_null<nonloc::LazyCompoundVal>(B.lookup(K))) {
- return *V;
- }
- }
-
- return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
+ return createLazyBinding(B, R);
}
bool RegionStoreManager::includedInBindings(Store store,