I only found one actual bug. While I was happy to get that fixed, the overall result was disappointing.
My conclusion that the best path forward was to design a language where a static analysis tool would add no value.
I only found one actual bug. While I was happy to get that fixed, the overall result was disappointing.
My conclusion that the best path forward was to design a language where a static analysis tool would add no value.
The only static analyzers that I am allowed to say have stood out to me are:
* Clang's static analyzer
* GCC's static analyzer with -Wno-analyzer-malloc-leak -Wno-analyzer-use-of-uninitialized-value -Wno-analyzer-null-dereference because those three checks are uniquely buggy. `-Wanalyzer-null-dereference` fails to understand assertions. `-Wanalyzer-use-of-uninitialized-value` fails to recognize initialization from pass by pointer. `-Wanalyzer-malloc-leak` is so buggy that out of the 32 reports it made, only 1 was real, but it was right before an `exit()` call in a test suite, so it was not a particularly interesting report. Unfortunately, I do not have notes describing why that check is buggy.
Note that I am restricted by Coverity's Scan User Agreement from saying anything involving Coverity that could constitute a comparison. I suggest that you look at the public information about its use by myself and draw your own conclusions. Keep in mind, your conclusions are not things that I said.
I once told the Coverity staff that the purpose of D was to put Coverity out of business (!)
That was probably a bad choice. John Carmack did not rate it very highly:
http://www.sevangelatos.com/john-carmack-on-static-code-anal...
https://analysis-tools.dev/tag/cpp
The only one I know to exist absent from that list is Microsoft’s /analyze.
That said, I am surprised that D only has 1 tool listed:
https://learn.microsoft.com/en-us/cpp/build/reference/analyz...
The only reason I know about it is that John Carmack rated it highly:
http://www.sevangelatos.com/john-carmack-on-static-code-anal...
How does this work?
(This is all in functions annotated with `@safe`.)
Try it and see for yourself.
There's a long list of things like this D does. For another example, it won't allow reading from uninitialized variables. It will check your printf/scanf format string against the arguments. (This last one was a big win.)
Clang and GCC are able to do this on C/C++ code via the format function attribute:
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attribute...
I agree about it being a big win. I have been dragging my feet on retrofitting the OpenZFS source code to use it since I have just not had much time to revise my pull request doing it after code review asked me to use `(u_longlong_t)` instead of PRId64 and friends and the initial attempt to retrofit the OpenZFS codebase using it did not find anything I considered to be a real bug. That might be because a number of real bugs in this area had already been identified and fixed thanks to static analyzers.
That said, there is this annoying oscillation that both GCC and Clang have where they complain that my type is long long and I should use %lld when I use %ld for uint64_t, only to complain that my type is long and I should use %ld when I use %lld for uint64_t. Using `PRId64` from stdint.h weirdly suppresses that behavior. Using a typecast to `(u_longlong_t)` also suppresses it.
Think of all the stupid problems arising in C from `long` not having a defined size. I can't believe all the time I've lost dealing with that. In D, a `long` is 64 bits. Period. Problems just vanish into the ether.