[cfe-commits] r61147 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis/uninit-vals-ps.c

Zhongxing Xu xuzhongxing at gmail.com
Tue Mar 10 21:31:37 PDT 2009

This scheme looks great to me! Two points:

a. Symbolic regions may have types. For example: void foo(char* buf) {...}.
'buf' => SymbolicRegion with type char*

b. Applying the scheme to your test case:

// <rdar://problem/6451816>
typedef unsigned char Boolean;
typedef const struct __CFNumber * CFNumberRef;
typedef signed long CFIndex;
typedef CFIndex CFNumberType;
typedef unsigned long UInt32;
typedef UInt32 CFStringEncoding;
typedef const struct __CFString * CFStringRef;
extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType,
void *valuePtr);
extern CFStringRef CFStringConvertEncodingToIANACarSetName(CFStringEncoding

CFStringRef rdar_6451816(CFNumberRef nr) {
  CFStringEncoding encoding;
  // &encoding is casted to void*.  This test case tests whether or not
  // we properly invalidate the value of 'encoding'.
  CFNumberGetValue(nr, 9, &encoding);
  return CFStringConvertEncodingToIANACharSetName(encoding); // no-warning

We would have to invalidate a TypedViewRegion(void*, VarRegion('encoding')).
Then StoreManager should canonicalize it to VarRegion('encoding').
Does that mean we have a new rule for canonicalization of discarding void*
typed view besides discarding typedefs? That is, void* typed view is another
kind of 'sugar' like typedefs?

On Wed, Mar 11, 2009 at 5:08 AM, Ted Kremenek <kremenek at apple.com> wrote:

> On Mar 10, 2009, at 12:40 AM, Zhongxing Xu wrote:
>> I see your point. But how can we recognize which casts are semantic
>> changes and which are sugar typed?
>> I doubt there is a consistent rule for this.
> I'm fairly certain there is a consistent rule for this.  Actually, it is
> very simple: semantic changes due to type views on regions occur when the
> view would result in the chunk of memory being interpreted differently.  In
> the case of typedefs, they are just sugar for the underlying type, and don't
> change the semantics.
> I've worked out a simple example to explain a proposal I have for possibly
> dealing with this issue.  The basic rules are as follows:
> (a) Symbolic regions potentially don't have types other than "void*".  That
> is, they are just chunks of memory.
> (b) We "canonicalize" regions when performing bindings to them, but don't
> need to canonicalize regions when they are used as values for expressions
> (see example below).
> (c) We strip away type views when performing pointer comparisons.  The
> type-checking in the frontend will tell us whether or not a pointer
> comparison is legal.
> Here is my example.  There are other cases to consider, such as how to
> handle Objective-C and C++ objects, but I think this is a good starting
> point:
> typedef struct s* MyPointer;
> void* foo(void);
>   void bar(void) {
> 1.   MyPointer q = foo();
> 2.   void *r = q;
> 3.   struct s* p = r;
> 4.   if (p == q)
> 5.      q->f = 10;
> 6.   if (q->f == 10)
>        ...
> 7.   if (p->f == 10)
>   }
> What happens:
> (a) On line 1 'foo()' evaluates to SymbolicRegion(Sym0).
> (b) On line 1 the value of (a) is then casted to
>    TypedViewRegion(MyPointer, SymbolicRegion(Sym0)).
> (c) On line 1 that value is bound to 'q'.  Internally it is stored as
>    'q' => TypedViewRegion(MyPointer, SymbolicRegion(Sym0)).  Observe that
> the
>    typedef is retained as it is used as a value in the binding and not the
> key.
>    Note that the syntax:
>     'q' => some value
>    is shorthand for
>      VarRegion('q') => some value
> (d) On line 2 we perform a load from 'q' (i.e., VarRegion('q')) to get the
> value
>    TypedViewRegion(MyPointer, SymbolicRegion(Sym0)).
> (e) On line 2 we cast (d) to void*.  This results
>    in stripping the 'TypedViewRegion' and getting 'SymbolicRegion(Sym0)'.
>  This
>    value is directly bound to 'r' to get the binding
>   'r' => SymbolicRegion(Sym0).
> (f) On line 3 we load from 'r' to get SymbolicRegion(Sym0).
> (g) On line 3 we cast (f) to 'struct s*', leaving us with the region
>    TypedViewRegion(struct s*, SymbolicRegion(Sym0)).
> (h) On line 3 we bound the value of (g) to 'p'.  This leaves us with the
>    binding 'p' => TypedViewRegion(struct s*, SymbolicRegion(Sym0)).
> (i) On line 4 we load both p and q, getting the values
>     TypedViewRegion(struct s*, SymbolicRegion(Sym0)) (for 'p') and
>     TypedViewRegion(MyPointer, SymbolicRegion(Sym0)) (for 'q').
>   We then do a pointer comparison by erasing their "views" and see if they
>   refer to the same memory object.  This means getting the first "non-view"
>   ancestor region.  In this case, the ancestor region is
> SymbolicRegion(Sym0)
>   in both cases.  This causes 'p == q' to evaluate to true.
>   The rationale behind this view-stripping is that we are just comparing
>   pointer addresses at this point, and "views" reason about the
> interpretation
>   of the bytes within a region but not the address of the region itself.
>   The "base region" doesn't have to be a SymbolicRegion. For example it
> could
>   be a VarRegion.
> (j) On line 5 we evaluate the l-value of 'q->f'.  This value is
>    FieldRegion('f',TypedViewRegion(MyPointer, SymbolicRegion(Sym0))).
> (k) On line 5 we ask the store manager to store '10' to the l-value
> computed
>    at (j).  Internally, within the StoreManager, we translate:
>      FieldRegion('f',TypedViewRegion(MyPointer, SymbolicRegion(Sym0))).
>    to:
>      FieldRegion('f',TypedViewRegion(struct s*, SymbolicRegion(Sym0))).
>    and then bind '10' to the latter.
>    Here we have "de-sugared" the TypedViewRegion so that all typedefs are
>    translated to the underlying type.
>    The rationale for this de-sugaring is that we want to "canonicalize" the
> key
>    (and *not* the value) in the binding. This makes retrievals from the
> store
>    easy in the presence of typedefs (which don't change the semantics of
> how a
>    region is interpreted).
> (l) One line 6 we compute the l-value of 'q->f' to be
>    FieldRegion('f',TypedViewRegion(MyPointer,SymbolicRegion(0))) and then
> ask
>    the store manager to load from that region.
>    Within the StoreManager, the key is again canonicalized to
>    FieldRegion('f',TypedViewRegion(struct s*, SymbolicRegion(0))).
>    The retrieval from the store then uses this key, getting the value 10.
> (m) Similarly, on line 7 we compute the l-value of 'p->f' to be
>    FieldRegion('f',TypedViewRegion(struct s*, SymbolicRegion(0))) and then
> ask
>    the store manager to load from that region.
>    Within the StoreManager that key is also canonicalized, but since it is
>    already canonical we just do the load.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20090311/e9a753cc/attachment.html>

More information about the cfe-commits mailing list