From: Ted Kremenek Date: Thu, 17 Mar 2011 03:51:51 +0000 (+0000) Subject: Tweak RegionStore's handling of lazy compound values to use the 'Default' versus... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=613744181322b9680a4b3d59cce87d7e5e572c99;p=clang Tweak RegionStore's handling of lazy compound values to use the 'Default' versus 'Direct' binding key, thus allowing specific elements of an array/struct to be overwritten without invalidating the entire binding. Fixes PR 9455. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127796 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 96a9d4f5d3..0361595025 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -337,6 +337,9 @@ public: // Part of public interface to class. SVal RetrieveFieldOrElementCommon(Store store, const TypedRegion *R, QualType Ty, const MemRegion *superR); + + SVal RetrieveLazyBinding(const MemRegion *lazyBindingRegion, + Store lazyBindingStore); /// Retrieve the values in a struct and return a CompoundVal, used when doing /// struct copy: @@ -977,11 +980,6 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) { std::pair RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { - if (Optional OV = getDirectBinding(B, R)) - if (const nonloc::LazyCompoundVal *V = - dyn_cast(OV.getPointer())) - return std::make_pair(V->getStore(), V->getRegion()); - if (const ElementRegion *ER = dyn_cast(R)) { const std::pair &X = GetLazyBinding(B, ER->getSuperRegion()); @@ -1009,6 +1007,12 @@ RegionStoreManager::GetLazyBinding(RegionBindings B, const MemRegion *R) { return std::make_pair(X.first, MRMgr.getCXXBaseObjectRegionWithSuper(baseReg, X.second)); } + else if (Optional OV = getDefaultBinding(B, R)) { + if (const nonloc::LazyCompoundVal *V = + dyn_cast(OV.getPointer())) + return std::make_pair(V->getStore(), V->getRegion()); + } + // 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); @@ -1098,14 +1102,19 @@ RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, QualType Ty) { if (const Optional &D = getDefaultBinding(B, superR)) { - if (SymbolRef parentSym = D->getAsSymbol()) + const SVal &val = D.getValue(); + if (SymbolRef parentSym = val.getAsSymbol()) return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R); - if (D->isZeroConstant()) + if (val.isZeroConstant()) return svalBuilder.makeZeroVal(Ty); - if (D->isUnknownOrUndef()) - return *D; + if (val.isUnknownOrUndef()) + return val; + + // Lazy bindings are handled later. + if (isa(val)) + return Optional(); assert(0 && "Unknown default value"); } @@ -1113,6 +1122,15 @@ RegionStoreManager::RetrieveDerivedDefaultValue(RegionBindings B, return Optional(); } +SVal RegionStoreManager::RetrieveLazyBinding(const MemRegion *lazyBindingRegion, + Store lazyBindingStore) { + if (const ElementRegion *ER = dyn_cast(lazyBindingRegion)) + return RetrieveElement(lazyBindingStore, ER); + + return RetrieveField(lazyBindingStore, + cast(lazyBindingRegion)); +} + SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, const TypedRegion *R, QualType Ty, @@ -1142,12 +1160,8 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store, const MemRegion *lazyBindingRegion = NULL; llvm::tie(lazyBindingStore, lazyBindingRegion) = GetLazyBinding(B, R); - if (lazyBindingRegion) { - if (const ElementRegion *ER = dyn_cast(lazyBindingRegion)) - return RetrieveElement(lazyBindingStore, ER); - return RetrieveField(lazyBindingStore, - cast(lazyBindingRegion)); - } + if (lazyBindingRegion) + return RetrieveLazyBinding(lazyBindingRegion, lazyBindingStore); if (R->hasStackNonParametersStorage()) { if (const ElementRegion *ER = dyn_cast(R)) { @@ -1530,7 +1544,7 @@ StoreRef RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V, // Now copy the bindings. This amounts to just binding 'V' to 'R'. This // results in a zero-copy algorithm. - return StoreRef(addBinding(B, R, BindingKey::Direct, + return StoreRef(addBinding(B, R, BindingKey::Default, V).getRootWithoutRetain(), *this); } diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index caa8342acb..b365bea6cf 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -1253,4 +1253,24 @@ void Rdar_9103310_E(Rdar_9103310_A * x, struct Rdar_9103310_C * b) { // expected } } +// Test handling binding lazy compound values to a region and then have +// specific elements have other bindings. +int PR9455() { + char arr[4] = "000"; + arr[0] = '1'; + if (arr[1] == '0') + return 1; + int *p = 0; + *p = 0xDEADBEEF; // no-warning + return 1; +} +int PR9455_2() { + char arr[4] = "000"; + arr[0] = '1'; + if (arr[1] == '0') { + int *p = 0; + *p = 0xDEADBEEF; // expected-warning {{null}} + } + return 1; +}