Maybe I missed this in the D newsgroups, "The D language comes to
help" by Andrey Karpov, Walter Bright. Andrey Karpov takes the
ten most common bugs found by his static analysis tool, and asks
Walter how D faces each one of those ten classes of problems. The
resulting text is interesting:
http://www.viva64.com/en/b/0182/
Below some comments about the text.
------------------------
V547/V560:
The unsigned<0 is usually a bug when it appears in top level
code. However, it can legitimately appear as a boundary case
inside of generic code.<
Then maybe it's possible to warn/error only about those
comparisons that are _not_ inside a template.
It can also be used in code that tests if a type is unsigned, as
in -(T)1<0. So I'm a bit uncomfortable in declaring it as always
wrong.<
I think the idiomatic way to do that in D is isSigned!T.
I think making that "-(T)1<0" useless is a small price to pay. (I
have found some signedness-related bugs in my D code converting
pieces of it to C and compiling it with GCC with its
signed-unsigned mixing warnings).
- - - - - - - - - -
V595:
I can't think of a case where this might be done legitimately.
But it does take some decent data flow analysis to be sure there
are no intervening modifications of buf.<
Is it worth doing that in D? Maybe the answer is positive.
(Rust (and other recent languages) avoids this problem in another
way, using not nullabile pointers and introducing pattern
matching).
- - - - - - - - - -
V501: it's a common bug. But I agree it's not easy to avoid it
reliably in a compiler. That's why static analysis tools often
return probabilities of errors, instead of just bad/good.
- - - - - - - - - -
V512/V579 and V557: some languages are able to avoid most of such
problems using very refined type systems (dependent typing), but
this adds a significant amount of complexity to both the language
and to the programming. Maybe "liquid typing" is (will be) able
to do it without an excessive amount of work for the programmer.
- - - - - - - - - -
V567/V610: I think there is some work left to do on this in D,
but it's going to be fixed. Maybe there is no entry on that in
Bugzilla.
- - - - - - - - - -
V597: this shows an example where a buffer is zeroed for security
reasons, despite it's never used again by the user code (because
it risks being used by external code).
Being able to remove dead assignments is a very important
compiler optimization. They come up when instantiating generic
code and inlining functions, and as the consequence of
performing other optimizations. In C you should be able to force
the dead assignment to happen by declaring the target to be
volatile. The only way to force a dead assignment in D to happen
is to write it using inline assembler.<
Using assembly to clear a buffer is possible, but it's not so
elegant. Maybe it's possible to add an annotation to D, like
@keep, to stop the optimizer from removing something that is
desired. Maybe this is not too much hard to implement.
- - - - - - - - - -
V519:
Double assignment is a form of dead assignment, and my comment
on it is the same as for (7).<
This case is very different from case V597. This is more similar
to V501. This is a matter of spotting duplicated assignments,
because they are sometimes bugs.
- - - - - - - - - -
V576: D has enough features to avoid this kind of bug, but
currently it's not doing it: I think Phobos should add functions
like writecfln!"%d %f(10, 5.5), to catch at compile-time a wrong
formatting string. Someone has already partially implemented
those functions in D.
- - - - - - - - - -
V530:
D does not have anything specific saying that a function's
return value must be used. In my experience, return values that
get ignored are often error codes, and D encourages the use of
exceptions to indicate errors rather than error codes.<
GCC-C has a function attribute to warn against not using a
function result. Adding a @use_result to D is an option, and
maybe it's not too much hard to implement. But I agree it's not a
very common need in D.
In one case I have written:
arr.delete(5);
Instead of the correct:
arr = arr.delete(5);
Here not using the result of std.algorithm.delete is often a bug.
But maybe it's not always a bug.
------------------------
On the other hand a significant part of the computing world seems
to go in the opposite direction, embracing JavaScript more and
more, and (despite TypeScript) mostly ignoring all the care about
the enforcement of static correctness:
http://developers.slashdot.org/story/13/02/04/1819231/gnome-goes-javascript
Bye,
bearophile