diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-02-01 19:49:57 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-02-01 19:49:57 +0000 |
commit | 978aeac1a90020b2a0ae6c7eb7fe65aa8226f74a (patch) | |
tree | 2319e9286563634cb20b20615e5968a3e6a1751e /lib/StaticAnalyzer/Core/RegionStore.cpp | |
parent | 0a0f93c90fd397a1aa9f97283c55f8ba0062bf55 (diff) |
[analyzer] Reuse a LazyCompoundVal if its type matches the new region.
This allows us to keep from chaining LazyCompoundVals in cases like this:
CGRect r = CGRectMake(0, 0, 640, 480);
CGRect r2 = r;
CGRect r3 = r2;
Previously we only made this optimization if the struct did not begin with
an aggregate member, to make sure that we weren't picking up an LCV for
the first field of the struct. But since LazyCompoundVals are typed, we can
make that inference directly by comparing types.
This is a pure optimization; the test changes are to guard against possible
future regressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174211 91177308-0d34-0410-b5e6-96231b3b80d8
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, |