[cfe-dev] [Patch] add KillStruct() to RegionStore
Ted Kremenek
kremenek at apple.com
Thu Jan 8 17:02:03 PST 2009
On Jan 8, 2009, at 9:21 PM, Zhongxing Xu wrote:
> This patch adds KillStruct() to region store. When we assign
> UnknownVal to a struct, we set the region's default value to
> Unknown, and remove bindings for all subregions of the struct region.
Hi Zhongxing,
This is nice. Could you include a test case that would trigger
KillStruct? More comments below:
Index: lib/Analysis/RegionStore.cpp
===================================================================
--- lib/Analysis/RegionStore.cpp (版本 61900)
+++ lib/Analysis/RegionStore.cpp (工作副本)
@@ -234,6 +234,9 @@
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(); }
@@ -910,6 +913,9 @@
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
+ if (V.isUnknown())
+ return KillStruct(St, R);
+
When precisely can V.isUnknown() be true when the value is a struct?
(test case please).
+const GRState* RegionStoreManager::KillStruct(const GRState* St,
+ const TypedRegion* R){
+ GRStateRef state(St, StateMgr);
+ // Set the default value of the struct region to UnknownVal.
+ St = state.set<RegionDefaultValue>(R, UnknownVal());
Interesting. Do we need the killset anymore, or are we going to model
"killed values" in this way?
+
+ Store store = St->getStore();
+ RegionBindingsTy B = GetRegionBindings(store);
+
+ std::vector<const MemRegion*> ToBeKilled;
In general, please use a llvm::SmallVector<> so that we can optimize
for the case when the number of items fits on the stack. Using
std::vector forces us to malloc() memory every time this method is
called (which is slow). My comment below, however, illustrates why we
don't need to use either in this case.
+
+ // 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<SubRegion>(r))
+ if (sr->isSubRegionOf(R))
+ ToBeKilled.push_back(R);
I think the region to be killed is 'r', not 'R' (since we just bound a
value to it up above).
+ }
+
+ for (std::vector<const MemRegion*>::iterator I = ToBeKilled.begin(),
+ E = ToBeKilled.end(); I != E; ++I)
+ store = Remove(store, Loc::MakeVal(*I));
You don't need to build a vector of killed regions and then iterate
through vector because 'B' is a purely functional data structure.
That is, removing entries from store just creates a new store, and 'B'
will continue have the same values and the iterator won't be
invalidated. The following will do just fine:
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E;
++I) {
const MemRegion* r = I.getKey();
if (const SubRegion* sr = dyn_cast<SubRegion>(r))
if (sr->isSubRegionOf(R))
store = Remove(store, Loc::MakeVal(r));
+ return StateMgr.MakeStateWithStore(St, store);
Do we also need to remove region views for the regions that are
killed, or should we dispense with that GDM entry entirely?
+}
+
More information about the cfe-dev
mailing list