diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/RegionStore.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 59 |
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, |