[cfe-dev] Clang Static Analyzer - tracking object value

Gábor Kozár kozargabor at gmail.com
Tue Apr 30 06:13:10 PDT 2013


Update: apparently if I explicitly state in the TransactionWrapper ctor
that I want the MyTransaction object by rvalue reference, then it moves. I
was under the impression it would move anyway.

Also, it might be obvious, but the last MyTransaction object never actually
dies - the analyzer hangs instead. If I move the MyTransaction object, then
it doesn't die either (and no copy is created obviously).

None of my checker's callbacks are called while the analyzer is hanging, so
I suspect it's an internal issue? Note that I'm using Clang 3.2, so it
might be something that has been fixed since then.


2013/4/30 Gábor Kozár <kozargabor at gmail.com>

> Hi Jordan,
>
> Thank you very much for your help! I have no idea how I missed that. That
> was a totally derp question, sorry.
>
>
> > *...a lot of C++ objects are value objects, which means they get copied
> from place to place, and currently it's up to checker writers to determine
> when that copy happens. Anna actually started sketching out a C++ iterator
> checker and realized that this problem was nontrivial (though by no means
> insurmountable).
>
> *
> I have thought that's what checkBind() is for - but I haven't really
> looked into what is it that it exactly does. Although I imagine that
> wrapping an object inside another object would cause complications -
> because in that case you have to check how the copy ctor behaves in
> relation to the wrapped object (i.e. is it copied or is a new one created,
> or is it passed by reference/pointer?), and then track it accordingly.
> Hmm... yeah, I think can see why this is a non-trivial matter. :) I do find
> it interesting though - might be something I'll look into during the summer
> holiday.
>
>
> > *Aside: if the region is more important than the symbol, why did we
> choose to attach our stream information to the symbol in
> SimpleStreamChecker?*
>
> It makes sense: fopen() and the like are not ctors, so - as far as I know
> - the analyzer can't really reason about their return value, as it doesn't
> do any inter-procedural analysis. That means that it can't do better than
> just a create a symbol for their return value. My scenario is different,
> because in my case, transaction objects are created by their ctors, and so
> the analyzer has more information.
>
>
> > *This "usually" is another problem for you—if we're constructing an
> anonymous temporary object like 'MyHandler(this)', the expression may
> result in an rvalue, which means the value represents a collection of
> struct field bindings instead of an actual region in memory.
>
> *
> I did a quick test on this rvalue case, and discovered that the analyzer
> (when invoked with my checker) seems to hang indefinitely on this code:
>
> class MyTransaction {};
>
> class TransactionWrapper
> {
> public:
>     TransactionWrapper(MyTransaction tr) : m_tr(tr) {}
>
> private:
>     MyTransaction m_tr;
> };
>
> int main(int argc, char* argv[])
> {
>     auto trw = TransactionWrapper(MyTransaction());
>     return 0;
> }
>
> It reports the creation of the MyTransaction object (apparently
> represented by CXXTempObjectRegion in this case), then it also shows the
> copy (why isn't it getting moved?), and also shows that the original
> MyTransaction objects dies (at the end of the statement I imagine) - but
> then it just hangs. What could cause such behavior?
>
> Thanks again!
>
> Gabor
>
>
>
> 2013/4/30 Jordan Rose <jordan_rose at apple.com>
>
>> Aack, no, this is not how it works. :-)
>>
>> From a checker-writer's perspective, conjureSymbolVal() always creates a
>> *new* symbol. Now, that symbol isn't *really* unique, because it's
>> cheaper if we reuse symbols along multiple paths, but you really can't use
>> it to represent the same symbol that the analyzer core will create.
>>
>> Instead, what you want is a *post-*call check, where you can then use
>> getSVal on the constructor expression to get the return value (which is *
>> usually* the region that was just constructed*). Unfortunately...
>>
>> Next, my problem is with detecting when members of the transaction object
>> is called. I was trying to get the SymbolRef of the object whose member is
>> called:
>>
>> const CXXInstanceCall* instanceCall =
>> llvm::dyn_cast<CXXInstanceCall>(&call);
>> ...
>> SymbolRef transactionObjectSymbol =
>> instanceCall->getCXXThisVal().getAsSymbol();
>>
>> But I find that this SymbolRef is always NULL. Why is that?
>>
>>
>> ...not every C++ object has an associated symbol. As we describe in "Building
>> a Checker in 24 Hours <http://llvm.org/devmtg/2012-11/>", a symbol is
>> only used to represent a *value* that the analyzer can't reason about.
>> What you're interested in here is the *region,* which represents the
>> memory backing the abstract C++ object. Unfortunately...
>>
>> ...a lot of C++ objects are value objects, which means they get copied
>> from place to place, and currently it's up to checker writers to determine
>> when that copy happens. Anna actually started sketching out a C++ iterator
>> checker and realized that this problem was nontrivial (though by no means
>> insurmountable).
>>
>> (Aside: if the region is more important than the symbol, why did we
>> choose to attach our stream information to the symbol in
>> SimpleStreamChecker? Well, the type of a POSIX stream is FILE*, but the
>> pointer-ness of it is essentially an implementation detail. It's more
>> important to associate the state with the return *value* of
>> fopen(). Indeed, the same logic in SimpleStreamChecker could be used for
>> the raw file descriptors used by open(), write(), and close().)
>>
>> That's sort of where we stand today. I don't have a good answer for you
>> on how to deal with C++ value objects. Sorry!
>>
>> Jordan
>>
>> * This *"usually"* is another problem for you—if we're constructing an
>> anonymous temporary object like 'MyHandler(this)', the expression may
>> result in an rvalue, which means the value represents a collection of
>> struct field bindings instead of an actual region in memory. I would not
>> worry about this case so much right now, though.
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130430/213c2a84/attachment.html>


More information about the cfe-dev mailing list