<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 30 March 2018 at 11:01, George Karpenkov via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<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;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div>On Mar 29, 2018, at 4:37 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br class="m_-3030390030240707049Apple-interchange-newline"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 29 March 2018 at 15:08, George Karpenkov via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Richard,<br>
<br>
Thanks for your reply!<br>
<span><br>
> Can you say more about why the static analyzer might want to map from a BindingDecl to a DecompositionDecl?<br>
<br>
</span>One thing I couldn’t figure out is how to figure out whether a given binding represents a global.<br>
But turns out that for my use case turns out that somehow was not required.</blockquote><div><br></div><div>I'm still not sure why you'd want to know that.</div></div></div></div></div></blockquote><div><br></div></span><div>Turns out I don’t actually need this for my specific use case.</div><div>But in general the analyzer often has different behavior for globals, as analysis runs on a single translation unit,</div><div>and has to assume that any other translation unit can do whatever it wants to the globals.</div></div></div></blockquote><div><br></div><div>OK, but a BindingDecl isn't a global (it's not even an object, just a symbolic name for an expression). It might represent an lvalue expression that denotes a global, but that global will be either a DecompositionDecl or an implicitly-introduced holding variable, both of which you can readily identify as being globals.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>
> BindingDecls should generally just be treated wrappers around some lvalue expression.<br>
<br>
</span>Right, yes, that unfortunately forces quite a lot of special-casing on us, as suddenly in many places where we expected only a VarDecl we know get a BindingDecl.</blockquote><div><br></div><div>What kind of places?</div></div></div></div></div></blockquote><div><br></div></span><div>Quite a few of them.</div><div>E.g. in <a href="https://reviews.llvm.org/D44956" target="_blank">https://reviews.llvm.org/<wbr>D44956</a> liveness analysis had to be re-done for binding declarations (if all BindingDecls had an underlying VarDecl the code change would have been around four lines instead).</div><div>The memory handling has to be extended to introduce a special class for dealing with binding declarations</div><div>(again, would have been avoided if they had an underlying VarDecl) [e.g. partial fix just to avoid the crash is in <a href="https://reviews.llvm.org/D44183" target="_blank">https://reviews.llvm.org/<wbr>D44183</a>]</div></div></div></blockquote><div><br></div><div>It seems to me that the problem here is actually that the CFG is mismodeling BindingDecls. If it expanded them to their expression, I don't think you'd need any special handling here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><div>In my understanding, clang itself has the same problem with strange special cases like not being able to capture a binding in a lambda.</div></div></div></blockquote><div><br></div><div>You can't capture a binding in a lambda because a binding is not a variable, per the C++ standard's rules. This is not a clang problem.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> The intended operational semantics are that when you see a DeclRefExpr naming a BindingDecl, you evaluate its associated subexpression.</div></div></div></div></div></blockquote><div><br></div></span><div>Right, but what we also need to do is to figure out what to do with a BindingDecl when we see it on its own.</div><div>Also to evaluate all its subexpressions we need to introduce special casing for BindingDecl’s, as they are not VarDecl’s anymore.</div></div></div></blockquote><div><br></div><div>I think you may be misunderstanding the semantic model we're using here. BindingDecls have nothing to do with VarDecls; they're a completely different kind of thing with completely different semantics, just like EnumConstantDecls are a completely different kind of thing with completely different evaluation semantics.<br></div><div><br></div><div>Simple example:</div><div><br></div><div>struct A { int x, y; };</div><div><br></div><div>void f(A a) {</div><div>  auto [v, w] = a;</div><div>  use(v, w);</div><div>}</div><div><br></div><div>This gives you a DecompositionDecl, which is a kind of VarDecl, of type A, initialized with 'a'. Let's call that 'e'.</div><div>It also gives you two BindingDecls, which are symbolic names for the expressions 'e.x' and 'e.y'.</div><div>So the evaluation semantics of the above function are as if you wrote:</div><div><br></div><div>void f(A a) {</div><div>  A e = a;</div><div>  use(e.x, e.y);</div><div>}</div><div><br></div><div>That's what the CFG for the above function should represent. The BindingDecls should not even show up, except as sugar so that clients who care can know that the 'e.x' expression was /written as/ 'v'.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><span class=""><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> I'd imagine this is best modeled by generating CFG nodes for the subexpression on each occurrence of such a DeclRefExpr, much like (IIRC) is done for CXXDefaultArgExpr and CXXDefaultInitExpr. That seems like it would not require too many special cases elsewhere.</div><div><br></div><div>(Perhaps the static analyzer needs more than that in order to produce more user-friendly diagnostics?)</div></div></div></div>
</div></blockquote><div><br></div></span>We are not even there yet for structured bindings, just trying to make the analyzer understand them.<br><br></div><div><br></div><br></div><br>______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div>