<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 11, 2015 at 6:05 PM, Jordan Rose <span dir="ltr"><<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</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"><div>David has it correct. A good heuristic might be to say that if the switch has a default case, then we should assume values outside the enum cases are possible, but we don't currently do this.</div></div></blockquote><div><br>Not sure whether you're suggesting a heuristic instead of having both optimistic and pessimistic edges on the CFG. I don't think a heuristic would be sufficient in any case - there are several places (uninit variables, dead code, etc) where pessimistic edges are desired and the rest/ones we already have that prefer optimistic. (or whichever way around that goes)<br><br>- Dave</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"><div>Different codebases have different opinions on this, which is why Clang has both -Wswitch and -Wswitch-enum. The analyzer currently does not let you make such a decision.<br></div><span><font color="#888888"><div><br></div><div>Jordan</div></font></span><div><div><div><br></div><br><div><blockquote type="cite"><div>On Sep 11, 2015, at 8:08 , David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><div dir="ltr">(Jordan - just cc'ing you because I don't know who's most active on the Static Analyzer these days)<br><br>Yep - the Clang CFG used to make only one decision about edges, and mostly it made them conservatively to avoid one kind of false positive (eg: avoid diagnosing an uninitialized variable when a switch had a case for each enum value and each of those initialized the variable). But this conservative assumption has problems in the other direction as you noticed.<br><br>After "goto fail; goto fail;" happened, Ted Kremenek improved the CFG somewhat to have optional/conditional extra edges in some way, and covered a few cases of this disparity, but the work is far from complete as demonstrated by cases like this.<br><br>Not sure if anyone's looking/interested at the moment.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 11, 2015 at 4:46 AM, Stephan Bergmann 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">For a <a href="http://test.cc" target="_blank">test.cc</a> input of<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
enum E1 { E1_0, E1_1 };<br>
enum E2 { E2_0, E2_1, E2_2 };<br>
enum class E3 { E3_0, E3_1 };<br>
int x;<br>
int f(E1 e1, E2 e2, E3 e3) {<br>
    int n1 = x;<br>
    switch (e1) {<br>
    case E1_0: n1 = 0; break;<br>
    case E1_1: n1 = 1; break;<br>
    }<br>
    int n2 = x;<br>
    switch (e2) {<br>
    case E2_0: n2 = 0; break;<br>
    case E2_1: n2 = 1; break;<br>
    case E2_2: n2 = 2; break;<br>
    }<br>
    int n3 = x;<br>
    switch (e3) {<br>
    case E3::E3_0: n3 = 0; break;<br>
    case E3::E3_1: n3 = 1; break;<br>
    }<br>
    return n1 + n2 + n3;<br>
}<br>
</blockquote>
<br>
(where x is needed to work around heuristics in clang-tidy when not to warn about redundant initializations), calling (at least for a recent Clang trunk build)<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
clang-tidy -checks=clang-analyzer-deadcode.DeadStores <a href="http://test.cc" target="_blank">test.cc</a> -- -std=c++11<br>
</blockquote>
<br>
causes clang-analyzer-deadcode.DeadStores warnings about the initializations of all three of n1, n2, n3.  Apparently on the grounds that each switch statement is exhaustive.<br>
<br>
But from my understanding of the C++ standard, the ranges of enumeration values for E2, E3 are such that f can legally be called with values for e2, e3 that are not covered by the case branches of the respective switches, e.g. as<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
f(E1_0, E2(3), E3(std::numeric_limits<int>::max()));<br>
</blockquote>
<br>
Is this analysis deliberately unsound, on the assumption that objects of enumeration type take only enumerator values?  If yes, is it deliberate to do so for both scoped and unscoped enumerations?<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">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/mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div>
</div></blockquote></div><br></div></div></div></blockquote></div><br></div></div>