[cfe-dev] [Patch] add KillStruct() to RegionStore

Zhongxing Xu xuzhongxing at gmail.com
Mon Jan 12 17:13:58 PST 2009


On Tue, Jan 13, 2009 at 7:23 AM, Ted Kremenek <kremenek at apple.com> wrote:

> This looks great!  Two comments:
> +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<RegionKills>(R);
> +
> +  // Set the default value of the struct region to "unknown".
> +  St = state.set<RegionDefaultValue>(R, UnknownVal());
> +
> +  // Remove the struct region from the RegionViews. It could only be a
> "view" of
> +  // its super region.
> +  St = RemoveRegionView(St, R, R->getSuperRegion());
>
> Hmm.  I'm looking at this again, I guess removing the view of 'R' from its
> super region doesn't make sense.  It's just the values bound to 'R' that
> change, not the fact that 'R' is a view of its super region.
>

Yes, that was my initial thought. :-)


>
> +
> +  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<SubRegion>(r))
> +      if (sr->isSubRegionOf(R))
> +        store = Remove(store, Loc::MakeVal(sr));
>
> I am wondering if we also need to remove bindings for views of 'sr'.  That
> is, iterate over the views of 'sr' and remove any bindings from state.  What
> do you think?  I guess it depends on how we decide to bind values in weird
> cases where people abuse the type system.
>

I am afraid the cost would be too high, and the logic be too complex for an
initial implementation. After all we are doing an approximate simulation,
not an exhaustive one. I suggest we leave a FIXME here and fix it when we
see a real bug caused by this simplification.


>
> +  }
> +
> +  return StateMgr.MakeStateWithStore(St, store);
> +}
> +
>
>
>
> On Jan 10, 2009, at 3:12 AM, Zhongxing Xu wrote:
>
>
>
> On Sat, Jan 10, 2009 at 3:46 PM, Ted Kremenek <kremenek at apple.com> wrote:
>
>> On Jan 8, 2009, at 5:36 PM, Zhongxing Xu wrote:
>>
>>  Index: lib/Analysis/RegionStore.cpp
>>> ===================================================================
>>> --- lib/Analysis/RegionStore.cpp        (版本 61900)
>>>
>>>
>>> +  if (V.isUnknown())
>>> +    return KillStruct(St, R);
>>> +
>>>
>>> When precisely can V.isUnknown() be true when the value is a struct?
>>>  (test case please).
>>>
>>> We already have that test case. It is the f5() in
>>> test/Analysis/array-struct.c.
>>>
>>
>> Great!  We should add a comment to that test case the says what part of
>> the analyzer/region store is getting tested.
>
>
> Done.
>
>
>>
>>
>>  +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?
>>>
>>> I think we still need killset. The regions in killset are ones we query
>>> its binding directly. The regions in RegionDefaultValue are ones whose
>>> subregions we query bindings for. I haven't had a way to combine them.
>>>
>>
>> I believe I might be confused about some basic concepts.  Here is how I
>> interpreted things.
>>
>> The "killset" is part of the state, and represents those regions whose
>> values have been changed (via direct assignment) after the entry to the
>> analyzed function.  This way we don't need to explicitly bind initial values
>> to regions and instead lazily infer their bindings.
>>
>> According to comments in RegionStore, the "default value" map
>> (RegionDefaultValue) is used to track "what regions have a default value of
>> 0 if they have no bound value and have not been killed."
>>
>> From the patch I see 'KillStruct' being used in the following way:
>>
>> const GRState*
>> RegionStoreManager::BindStruct(const GRState* St, const TypedRegion* R,
>> SVal V){
>>  // FIXME: Verify that we should use getRValueType or getLValueType.
>>  QualType T = R->getRValueType(getContext());
>>  assert(T->isStructureType());
>>
>>  RecordType* RT = cast<RecordType>(T.getTypePtr());
>>  RecordDecl* RD = RT->getDecl();
>>  assert(RD->isDefinition());
>>
>>  if (V.isUnknown())
>>    return KillStruct(St, R)
>>  ...
>>
>> Two things occur to me:
>>
>> (1) We should always be adding any region directly assigned to the
>> killset.  Doesn't that include structs?
>
>
> Yes. I thought we would never query a struct region's binding like we never
> do it to an array region. But later I realized I was wrong. I've done this
> step in the new patch.
>
> And, I think we should add a region to the killset *only* when it is
> assigned "unknown" directly. Because if it is assigned other value, we would
> have its binding in the region bindings. It is redundant to add it to the
> killset.
>
>
>>
>>
>> (2) After assigning the value "unknown" to the struct, the values of its
>> fields should not be 0 (as indicated by the comments for
>> RegionDefaultValue).  That doesn't make sense to me.  Shouldn't they just be
>> "unknown"?
>>
>> In other words, regardless of whether V.isUnknown() == true (in the above
>> code snippet) we should always do (1) and then just remove any bindings to
>> struct and it's fields.  Adding entries to RegionDefaultValue (i.e., (2))
>> doesn't make sense to me, so I think I'm just missing something and don't
>> really understand the overall design.
>
>
> RegionDefaultValue was originally designed to include regions which have
> default values of 0. But later I find we could have default values other
> than 0. This is just a case that we need it, since we would query the
> bindings of the subregions of the struct region that is killed (assigned
> "unknown"). If we don't set the struct region's default value, we would have
> to add all subregions of the struct region to the killset. Now that we set
> the struct region's default value, we can just remove the subregions of the
> struct region from RegionBindings.
>
>
>>
>>
>>  Ah, I forgot that point. Is this also known as persistent data structure?
>>>
>>
>> Yes it is.  The term "purely functional data structures" comes from the
>> functional programming mindset.  Okasaki has an excellent book on that
>> topic:
>>
>>
>> http://books.google.com/books?id=SxPzSTcTalAC&dq=purely+functional+data+structures&printsec=frontcover&source=bn&hl=en&sa=X&oi=book_result&resnum=4&ct=result
>
>
> Thanks.
>
>
>>
>> <http://books.google.com/books?id=SxPzSTcTalAC&dq=purely+functional+data+structures&printsec=frontcover&source=bn&hl=en&sa=X&oi=book_result&resnum=4&ct=result>
>>
>>
>>> Do we also need to remove region views for the regions that are killed,
>>> or should we dispense with that GDM entry entirely?
>>>
>>> I think region views are orthogonal to this one. Region views are used to
>>> cast region back and forth between typed and untyped ones. Here we only
>>> handle the region bindings.
>>>
>>
>> "Views" are just a specific type of subregions (whose bindings are all
>> getting nuked by KillStruct).  The GDM entry "RegionViews" is just a
>> back-mapping from a region to its subregions.  If we remove all of those
>> bindings why do we need to keep that backmapping around since none of them
>> bind to any value?  Removing stale data from the state allows better
>> caching.
>
>
> Yes, I've done this in the new patch.
>
>
>>
>>
>> As a meta comment, it would probably be good to add comments to the top of
>> RegionStore that documents the overall design. More specifically, we should
>> mention how the different GDM pieces are used, what's the overall
>> abstraction of how regions bind to values, how we model "views" of regions
>> (i.e., what they are and what purpose they serve) and so forth.  I feel that
>> some of my confusion is stemming from not completely understanding the
>> design as well as I thought I did.
>
>
> Yes. I should have done that. But I didn't do it because I feel some
> designs are not fixed.
> <killstruct2.patch>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20090113/bb73dc99/attachment.html>


More information about the cfe-dev mailing list