<div dir="ltr">Update: sorry, please ignore my previous e-mail - it turns out that the issue was in my code.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/30 Gábor Kozár <span dir="ltr"><<a href="mailto:kozargabor@gmail.com" target="_blank">kozargabor@gmail.com</a>></span><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>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.<br>


<br></div>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).<br>


<br></div>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.<br>


</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/30 Gábor Kozár <span dir="ltr"><<a href="mailto:kozargabor@gmail.com" target="_blank">kozargabor@gmail.com</a>></span><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div><div>Hi Jordan,<br><br>Thank you very much for your help! I have no idea how I missed that. That was a totally derp question, sorry.<div><br><br>> <i>...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).<br><br></i></div></div>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.<div>


<br>
<br>> <i>Aside: if the region is more important than the symbol, why did we 
choose to attach our stream information to the symbol in 
SimpleStreamChecker?</i><br><br></div></div><div>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.<div>


<br>
<br>> <i>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.<br><br></i></div></div><div>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:<br>



<br>class MyTransaction {};<br><br>class TransactionWrapper<br>{<br>public:<br>    TransactionWrapper(MyTransaction tr) : m_tr(tr) {}<br>    <br>private:<br>    MyTransaction m_tr;<br>};<br><br>int main(int argc, char* argv[])<br>



{<br>    auto trw = TransactionWrapper(MyTransaction());<br>    return 0;<br>}<br><br></div><div>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?<br>



<br></div><div>Thanks again!<br><br>Gabor<br></div><div><br></div></div><div><div><div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/30 Jordan Rose <span dir="ltr"><<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</a>></span><br>



<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Aack, no, this is not how it works. :-)</div><div><br></div><div>From a checker-writer's perspective, conjureSymbolVal() always creates a <i>new</i> symbol. Now, that symbol isn't <i>really</i> 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.</div>



<div><br></div><div>Instead, what you want is a <i>post-</i>call check, where you can then use getSVal on the constructor expression to get the return value (which is <i>usually</i> the region that was just constructed*). Unfortunately...</div>



<div><br></div><div><div><blockquote type="cite"><div dir="ltr"><div><div><div><div><div><div><div>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:</div>



</div></div><br>const CXXInstanceCall* instanceCall = llvm::dyn_cast<CXXInstanceCall>(&call);<br>

...<br>SymbolRef transactionObjectSymbol = instanceCall->getCXXThisVal().getAsSymbol();<br><br></div>But I find that this SymbolRef is always NULL. Why is that?<br></div></div></div></div></blockquote><div><br></div></div>



...not every C++ object has an associated symbol. As we describe in "<a href="http://llvm.org/devmtg/2012-11/" target="_blank">Building a Checker in 24 Hours</a>", a symbol is only used to represent a <i>value</i> that the analyzer can't reason about. What you're interested in here is the <i>region,</i> which represents the memory backing the abstract C++ object. Unfortunately...</div>



<div><br></div><div>...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).</div>



<div><br></div><div>(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 <i>value</i> of fopen(). Indeed, the same logic in SimpleStreamChecker could be used for the raw file descriptors used by open(), write(), and close().)</div>



<div><br></div><div>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!</div><div><br></div><div>Jordan</div><div><br></div><div>* This <i>"usually"</i> 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.</div>



</div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>