[cfe-commits] [PATCH] RegionStore
Ted Kremenek
kremenek at apple.com
Mon Oct 20 21:32:10 PDT 2008
On Oct 20, 2008, at 3:31 AM, Zhongxing Xu wrote:
> Some more comments:
>
> int a[10];
> int (*p)[10];
>
> Per C99 6.3.2p3, 'a' and '*p' is not lvalue when they are placed in
> a[1] or (*p)[1]. So in fact we cannot do lvalue evaluation of them.
I'm looking at the section, and I'm not seeing the actual clause that
your are referencing. Is there a particular sentence or paragraph you
are referring to? I think this is the phrase:
"Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue."
This conversion is handled by the ImplicitCastExpr. It seems fairly
straightforward to me to have VisitCast() call VisitLValue() on its
child expression when doing an array to pointer conversion.
> But this is inconsistent with the usual case in VisitDeclRefExpr and
> VisitUnaryExpr. But 'a' and '*p' do have lvalue sometimes.
Perhaps, but arrays really are a special case, both in the language
syntax and the C type system. It's not surprising to me that we need
to handle them specifically.
> And special handling of these non-lvalue cases in the GRExprEngine
> is ugly.
I agree it isn't pleasant, but the ugliness is highly localized. I
believe it's much better to put this ugliness in one place (the core
analysis engine) rather than require all implementations of Store to
get it right. GRExprEngine already takes care of lots of details like
this.
> On the other hand, a simple trick in the Store will do us the favor.
> If we are passed loc::MemRegionVal(some array's region) in the
> store, we do not go through the binding, but simply return
> loc::MemRegionVal(some array's region) as the loaded value. Then we
> can do the usual thing for all cases in GRExprEngine's Visitors: get
> the lvalue of the Decl, ask Store what its rvalue is.
Understood. Three comments.
First, having the Store do this means that *every* implementation of
Store will have to specially implement this corner case. By doing it
outside of Store (i.e., in GRExprEngine), we might need to work hard
to get it right, but once we do it will be right for all
implementations of Store. It's not an obvious thing for a Store to
do, which means people will likely get it wrong.
Second, after our long thread a week ago, my feeling is that the Store
has no notion of lvalues or rvalues, only locations and the values
that are binded to those locations. In this regards, I believe that
GetSVal() should only return the value that is bound to a region. The
implementation of GetSVal() should not have to guess of whether it is
called to return an lvalue or an rvalue given the type of a region.
That just doesn't seem very clean to me, and violates the separation
of concerns between handling all the nastiness of C's syntax in
GRExprEngine and handling the semantics of value bindings in Store.
Third, what regions a Store returns to callers (via getLValueXXX) and
the meaning of those regions is entirely up to the Store. To me it
makes no sense to call GetSval() on a VarRegion for an array variable
because the operation of "loading from an array" doesn't make sense,
i.e., there is no C syntax that allows one to "load array" (or "get
binding"); we can load an element of an array, but not the array
itself. The only way for GetSVal() to make sense in this context is
for it to return an lvalue, but that really isn't the binding.
Perhaps you have a different interpretation of GetSVal(), but to me
just keeping it to mean "fetch the value bound to this location" keeps
things clean and simple.
Although it's more wordy, perhaps we should rename GetSVal() to
GetBinding() just to make the meaning of this method more clear.
More information about the cfe-commits
mailing list