[cfe-commits] r59232 - /cfe/trunk/lib/Analysis/GRExprEngine.cpp
Ted Kremenek
kremenek at apple.com
Fri Nov 14 09:49:50 PST 2008
On Nov 14, 2008, at 3:46 AM, Zhongxing Xu wrote:
> Hi Ted,
>
> I rewrite the code with an AnonTypedRegion created to attach type
> information to. Please review it.
>
This looks pretty good so far! First I'll mentioned a couple
thoughts, then a few specific comments on the code.
Thoughts:
(1) We might want GRExprEngine::VisitCast to do the delegation of
pointer -> pointer casts to StoreManager. I'm not certain if this is
the right approach, but it would give more flexibility to the
particular implementation of StoreManager of how to handle such
things. Basically:
if (isa<loc::MemRegionVal>(V)) {
assert (Loc::isLocType(CastE->getType());
assert (Loc::isLocType(Ex->getType());
// Delegate to store manager.
SVal VNew = StateManager.getStoreManager().CastRegion(CastE-
>getType()->getCanonicalType(), ..., V);
// update the state, etc.
}
Here "CastRegion" would do the actual region conversion, creating
AnonTypedRegionm etc. The advantage of this is that it allows
different StoreManagers to handle arbitrary region to region casts
differently and removes these details from GRExprEngine.
(2) The conversion from AllocaRegion to an AnonTypedRegion probably
applies to all regions that are not typed, not just AllocaRegion.
(3) The interesting issues really come into play in how we query
things in the store. For example, how do we handle games like:
void* p = alloca(...);
char* q = (char*) p;
p = (void*) q;
On the last line we should probably get back the original region
returned from calling "alloca". This is important if you consider a
slightly different example:
void* p = alloca(...);
char *q = (char*) p;
void* r = (void*) q;
assert (r == p && "r and q should be the same!");
Basically, my original concept of AnonTypedRegion was to layer some
context on to an existing region, and then strip it away when it no
longer applies. This is really the design point we need to iterte
on. Is this the right approach? etc.
Also consider:
void* p = alloca(...);
...
char *q = (char*) p;
*q = 'c';
...
double *d = (double*) p;
*d = 1.0;
...
char ch = *q; // we should be able to flag this as an error, since
that chunk of memory now binds to 'd'
Another horrible case:
void* p = alloca(...);
...
char *q = (char*) p;
*q = 'c';
...
double *d = ((double*) p) + 1;
*d = 1.0;
...
char ch = *q; // whether or not this is an error is subjective.
It also gets down the point of what is the "extent" of AnonTypedRegion.
I don't think we need to solve these problems all at once, but I think
it's important to keep these design points in mind. I'd like to
converge to a clean and flexible design that allows us to model such
things if we should so choose (as opposed to not allowing us to model
such things at all).
That said, I only have a couple additional comments on your patch:
+ if (isa<loc::MemRegionVal>(V)) {
+ if (const AllocaRegion* AR =
+
dyn_cast<AllocaRegion>(cast<loc::MemRegionVal>(V).getRegion())) {
+
+ MemRegionManager& RM = getStateManager().getRegionManager();
+
+ // Create a new region to attach type information to it.
+ const AnonTypedRegion* TR = RM.getAnonTypedRegion(T, AR);
+
+ // Get the pointer to the first element.
+ // FIXME: get the pointer width from the target information.
+ llvm::APSInt Zero(llvm::APInt::getNullValue(32), false);
+ SVal
ZeroIdx(nonloc::ConcreteInt(getBasicVals().getValue(Zero)));
Just use BasicValueFactory::getZeroWithPtrWidth(). i.e.:
SVal ZeroIdx(getBasicVals().getZeroWithPtrWidth());
+ const ElementRegion* ER = RM.getElementRegion(ZeroIdx, TR);
Move this (and probably the majority of this chunk of code) into the
StoreManager classes. This use of ElementRegion seems pretty tied to
how RegionStore reasons about things. BasicStore can probably just
return the original region.
+
+ MakeNode(Dst, CastE, N, BindExpr(St, CastE,
loc::MemRegionVal(ER)));
+ continue;
+ }
+ }
+
More information about the cfe-commits
mailing list