Open Quuxplusone opened 10 years ago
Attached report-362487.html
(5899 bytes, text/html): scan-build error report demonstrating the bug
Attached test.cc
(420 bytes, text/plain): The C++ program (build with "clang test.cc -std=c++11 -lstdc++"). Identical to the "cat test.cc" output in the bug summary.
I'm not even sure how that's compiling, because 5.0 isn't an unsigned long long. But yes, the analyzer does not model std::vector right now, and it probably isn't modeling clzll either. The latter would be pretty easy to fix, though.
Jordan:
AIUI C++ does narrowing conversions automatically in many contexts. (This is a very questionable design decision but we have to live with it.) I'm not a language lawyer but I guess that clang is correct to allow this code. Anyway replacing "5.0" with the explicit cast "static_cast
It's OK for clang static analyzer to stay silent or give ambiguous warnings because it isn't modeling vector and clzll. It's not OK for it to give diagnostics that confidently state something, i.e. which branch of an 'if' is taken, that is incorrect.
The analyzer isn't actually running your program, so /everything/ it prints is based on its model. Each path note, including those for branches, is meant to explain the analyzer's assumptions at each point---the analyzer /is/ taking that branch, even though the real program can't.
I just looked at the FAQ and it looks like I misunderstood what the "Note:
Taking true branch" message means. I guessed that that message was warning me
that scan-build had proved that the false branch was never taken (i.e. dead
code). After seeing the example warnings in the FAQ it seems that message is
not an independent warning but rather an explanation of under what
circumstances it thinks the error about the "<<" being undefined may occur.
Therefore never mind what I said about the taking true branch note being wrong.
Instead make this bug about the error about the "<<" being undefined, which is
a false positive. I believe this false positive is caused by scan-build
(apparently) not modeling double to unsigned long long conversion (i.e. 5.0 to
5ull), so it can't rule out Log2Floor64 receiving n=0 and returning -1, which
in turn would make the left-shift undefined. My evidence for this is if you
replace the problematic line with the following three the error message stays
the same but uncommenting the assert makes it go away:
unsigned long long five = 5.0;
// assert(five>0); //uncommenting this line causes error report to go away
unsigned long long count = 1ull << Log2Floor64(five);
Now that I (mostly) understand the bug I have four suggestions. These
suggestions are mostly independent so you may want to make additional bugs for
one or more of them to keep them separate.
1. Model double to integral type conversion so this false positive goes away.
2. Please add a page to the "user manual" menu on the webpage describing how to
interpret the error reports, including the fact that the notes are statements
of the branches taken in the error report, not a statement that the value of
the tests can be determined statically. If a user receives multiple correct
error reports it's possible to deduce what the error reports mean but a single
error report, especially a false positive one, is ambiguous so documentation
would help.
3. The error message says that the result "is undefined", which can be
naturally interpreted as a statement that the analyzer has proven that
undefined behavior will definitely occur, which is wrong in this case. If the
analyzer is uncertain about whether or not undefined behavior is occurring it
should say the result "may be undefined". The same suggestion applies to all
error messages: make it clear whether the error message is for a certain error
or a possible error.
4. The error message would be a lot more useful if it were more specific about
the problem than just the left-shift being undefined. For example state that
scan-build deduced that the right-hand operand was bounded between -1 and 63
inclusive (or whatever scan-build actually deduced), which contains value(s)
below the allowed range 0 to 63 inclusive.
report-362487.html
(5899 bytes, text/html)test.cc
(420 bytes, text/plain)