While fix the lvalue-rvalue conversion issue in the AST seems to bring benefits in the long run, I suggest we fix these cases one by one in the CFG construction, until we see enough cases that warrants an overhaul.<br><br>
In this case, we can only mark the block-level expr in the unary operator as StatementAsLValue. This is a simple and local change.<br><br><div class="gmail_quote">2010/11/20 Zhanyong Wan (λx.x x) <span dir="ltr"><<a href="mailto:wan@google.com">wan@google.com</a>></span><br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Thanks for thinking through this and sharing your analysis, Ted!  I'm<br>
all for fixing this in a principled way.  However, the crash I<br>
reported is blocking some experiments I'm doing.  Therefore I'd really<br>
like to put in a fix for the symptom first to unblock me, and then we<br>
can take the time necessary to fix the whole thing the right way.<br>
Would you oppose to that?  Thanks,<br>
<div><div></div><div class="h5"><br>
On Fri, Nov 19, 2010 at 11:07 PM, Ted Kremenek <<a href="mailto:kremenek@apple.com">kremenek@apple.com</a>> wrote:<br>
> On Nov 19, 2010, at 5:24 PM, Zhanyong Wan (λx.x x) wrote:<br>
><br>
>> I'll document this in my new patch.  Also, how would you suggest to<br>
>> add a test to catch violation of #2?<br>
><br>
> Stepping back, I think we may need some extra design here, either in the ASTs or in the analyzer, to model lvalue-to-rvalue conversions correctly for C++.<br>
><br>
> With C, lvalue-to-rvalue conversions happen in specific cases, e.g.:<br>
><br>
> - Loading from a variable<br>
><br>
> - Dereferencing a pointer<br>
><br>
> Semantically such conversions result in a "load" of a value from a memory address.  This is what 'EvalLoad()' does in GRExprEngine.  Because the places where such conversions occur in C are fairly limited, up to now we have been able to model lvalue-to-rvalue conversions without much effort.<br>

><br>
> With C++ (especially with the use of references) there is a lot more cases to reason about.  It raises the question of whether we should try to recreate the logic in codegen in GRExprEngine to infer all of these cases, or to try and represent them explicitly in the AST.<br>

><br>
> There are advantages to representing such conversions explicitly in the AST.  For one, the distinction of an lvalue versus an rvalue in the CFG probably evaporates.  Any place where we see an lvalue-to-rvalue conversion simply means the subexpression was a pointer (or reference), and the conversion represents a load.  Moreover, different analyses (not just GRExprEngine) will be able to more adeptly reason about the semantics of analyzed code without having the burden to re-infer where all the lvalue-to-rvalue conversions take place.<br>

><br>
> The other advantage is that it takes care of discrepanancies between C and C++ like the following:<br>
><br>
> $ cat t.c<br>
> void foo() {<br>
>  int a = 0;<br>
>  ++(++a);<br>
> }<br>
><br>
> $ clang -fsyntax-only t.c<br>
> t.c:3:3: error: expression is not assignable<br>
>  ++(++a);<br>
>  ^ ~~~~~<br>
> 1 error generated.<br>
><br>
> $ clang -fsyntax-only -x c++ t.c<br>
> $<br>
><br>
> Here C and C++ differ on the semantics of '++'.  When the file is compiled as C code, we get an error because the expression '++a' evaluates to an rvalue.  When we compile the code as C++, however, the expression evaluate to an lvalue.  This difference isn't represented in the AST at all.<br>

><br>
> NOTE: This is also another reason why GRExprEngine might crash in some cases with '++' on C++ code, because it assumes the C semantics.<br>
><br>
> To explain the difference some more, consider:<br>
><br>
>  int a = 0;<br>
>  int b = ++a;<br>
><br>
> With C, the '++a' evaluates to an rvalue immediately, which is assigned to 'b'.  In C++, the expression '++a' first evaluates to an lvalue, and then there is an implicit lvalue-to-rvalue conversion that loads the new value.  Of course the compiler doesn't need to generate more IR to represent this at the execution level, but this is what is conceptually happening in the language.<br>

><br>
> So to summarize, these discrepancies of how lvalues and rvalues are reasoned about in C versus C++ is really something we need to solve systematically in the analyzer (and/or ASTs) with a cohesive solution.  That's why I think this individual case that you reported is only symptomatic of a bigger issue that needs a well-designed solution.<br>

><br>
> Cheers,<br>
> Ted<br>
<br>
<br>
<br>
</div></div>--<br>
<font color="#888888">Zhanyong<br>
</font><div><div></div><div class="h5"><br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br>