From cff637a568540d3847ae037b2a5279d043b17080 Mon Sep 17 00:00:00 2001 From: Zhongxing Xu Date: Tue, 13 Jan 2009 01:49:57 +0000 Subject: [PATCH] Add KillStruct to region store. - put the killed region in the kill set. - set its default value to unknown. - removes all bindings for its subregions. llvm-svn: 62138 --- clang/lib/Analysis/RegionStore.cpp | 72 +++++++++++++++++++++++++----- clang/test/Analysis/array-struct.c | 1 + 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 9041930a84c9..2d71117b2869 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -36,7 +36,7 @@ typedef llvm::ImmutableMap RegionBindingsTy; // MemRegions can be layered on top of each other. This GDM entry tracks // what are the MemRegions that layer a given MemRegion. // -typedef llvm::ImmutableList RegionViews; +typedef llvm::ImmutableSet RegionViews; namespace { class VISIBILITY_HIDDEN RegionViewMap {}; } static int RegionViewMapIndex = 0; namespace clang { @@ -68,10 +68,11 @@ namespace clang { // Region "killsets". //===----------------------------------------------------------------------===// // -// RegionStore lazily adds value bindings to regions when the analyzer -// handles assignment statements. Killsets track which default values have -// been killed, thus distinguishing between "unknown" values and default -// values. +// RegionStore lazily adds value bindings to regions when the analyzer handles +// assignment statements. Killsets track which default values have been +// killed, thus distinguishing between "unknown" values and default +// values. Regions are added to killset only when they are assigned "unknown" +// directly, otherwise we should have their value in the region bindings. // namespace { class VISIBILITY_HIDDEN RegionKills {}; } static int RegionKillsIndex = 0; @@ -83,11 +84,11 @@ namespace clang { } //===----------------------------------------------------------------------===// -// Regions with default values of '0'. +// Regions with default values. //===----------------------------------------------------------------------===// // -// This GDM entry tracks what regions have a default value of 0 if they -// have no bound value and have not been killed. +// This GDM entry tracks what regions have a default value if they have no bound +// value and have not been killed. // namespace { class VISIBILITY_HIDDEN RegionDefaultValue {}; } static int RegionDefaultValueIndex = 0; @@ -234,6 +235,9 @@ private: const GRState* BindStruct(const GRState* St, const TypedRegion* R, SVal V); + /// KillStruct - Set the entire struct to unknown. + const GRState* KillStruct(const GRState* St, const TypedRegion* R); + // Utility methods. BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); } ASTContext& getContext() { return StateMgr.getContext(); } @@ -241,6 +245,8 @@ private: const GRState* AddRegionView(const GRState* St, const MemRegion* View, const MemRegion* Base); + const GRState* RemoveRegionView(const GRState* St, + const MemRegion* View, const MemRegion* Base); }; } // end anonymous namespace @@ -910,6 +916,9 @@ RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){ RecordDecl* RD = RT->getDecl(); assert(RD->isDefinition()); + if (V.isUnknown()) + return KillStruct(St, R); + nonloc::CompoundVal& CV = cast(V); nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end(); RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end(); @@ -941,6 +950,30 @@ RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R, SVal V){ return St; } +const GRState* RegionStoreManager::KillStruct(const GRState* St, + const TypedRegion* R){ + GRStateRef state(St, StateMgr); + + // Kill the struct region because it is assigned "unknown". + St = state.add(R); + + // Set the default value of the struct region to "unknown". + St = state.set(R, UnknownVal()); + + Store store = St->getStore(); + RegionBindingsTy B = GetRegionBindings(store); + + // Remove all bindings for the subregions of the struct. + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { + const MemRegion* r = I.getKey(); + if (const SubRegion* sr = dyn_cast(r)) + if (sr->isSubRegionOf(R)) + store = Remove(store, Loc::MakeVal(sr)); + } + + return StateMgr.MakeStateWithStore(St, store); +} + const GRState* RegionStoreManager::AddRegionView(const GRState* St, const MemRegion* View, const MemRegion* Base) { @@ -948,11 +981,30 @@ const GRState* RegionStoreManager::AddRegionView(const GRState* St, // First, retrieve the region view of the base region. const RegionViews* d = state.get(Base); - RegionViews L = d ? *d : RVFactory.GetEmptyList(); + RegionViews L = d ? *d : RVFactory.GetEmptySet(); // Now add View to the region view. - L = RVFactory.Add(View, L); + L = RVFactory.Add(L, View); // Create a new state with the new region view. return state.set(Base, L); } + +const GRState* RegionStoreManager::RemoveRegionView(const GRState* St, + const MemRegion* View, + const MemRegion* Base) { + GRStateRef state(St, StateMgr); + + // Retrieve the region view of the base region. + const RegionViews* d = state.get(Base); + + // If the base region has no view, return. + if (!d) + return St; + + // Remove the view. + RegionViews V = *d; + V = RVFactory.Remove(V, View); + + return state.set(Base, V); +} diff --git a/clang/test/Analysis/array-struct.c b/clang/test/Analysis/array-struct.c index dd43a6d704be..8f4bb044ba87 100644 --- a/clang/test/Analysis/array-struct.c +++ b/clang/test/Analysis/array-struct.c @@ -46,6 +46,7 @@ void f4() { } // Struct variable in lvalue context. +// Assign UnknownVal to the whole struct. void f5() { struct s data; g1(&data);