That message is only supposed to warn about compatibility to traditional
C, in case the function should ever be compiled without its prototype
being in effect. All other type checks are supposed to be in another
function, as documented, but that type check misses to report a few
error-prone type combinations (long to char, long to int).
30 years after the introduction of prototypes with C90, almost all
existing code uses prototypes. The warning has thus lost most of its
usefulness and can rather be confusing since a conversion from 'char' to
'long' is not problematic with prototypes in action, and the probability
of the code being backported to a pre-C90 compiler is diminishingly
small.
The words "due to prototype" now serve as a hint again. The proper fix
could be to suppress this warning in C99 mode since that's far enough
from traditional C.
The lint tests do not focus on the whitespace since that is the most
boring part of code style. Therefore, format the tests to be readable
by following share/misc/style as close as possible.
For those tests that didn't use GCC-style line markers such as "# 2",
the line numbers of the diagnostics stay the same. This is purely
conincidental. Before, the 3 lines came from lint's built-in
definitions (see 'builtins' in main1.c), and line number counting
continued as if nothing had happened, making the first line of the
actual file line 4. These 3 built-in lines are now replaced with 3
lines of file header.
The words "due to prototype" are an anachronism from the 1990s.
Nowadays every function is defined using a prototype, which makes these
words redundant.
For every conversion it is useful to know both the source and the target
type since these are not always obvious from the code.
The only surprise is the warning in d_gcc_extension. The conversion
there is from 'double' to 'long double', which is a lossless conversion.
This may be a bug in lint.
If one of the nested subexpressions is parenthesized, the author
probably knew how these expressions are evaluated. Therefore don't warn
in such a situation.
Maybe the original author once made a typo and tried to initialize
variables but instead compared them, like this:
int a, b, c;
a == b == c;
This would explain the text of the message, which still sounds strange.
At least it doesn't show up as often anymore.
Message 189 would have applied to traditional C and was supposed to
detect assignments between struct and union types. The corresponding
check had never been implemented though.
Traditional C has been superseded for 30 years now, therefore there is no
point in adding this check retroactively.
Since rt is an alias for rn->tn_type->t_tspec, it cannot be PTR and VOID
at the same time. This makes the condition unsatisfiable. Removing
that part of the code didn't show any change in behavior, as expected.
It may even be that fixing this obvious bug doesn't show any change in
behavior since that function is only used in a single place and
check_pointer_comparison performs its own checks before issuing any
warning.
At least the test cases added to msg_124.c all run as expected.
There are 2 remaining expressions:
In line 244, !(kw->kw_deco & deco) is a bitwise and. This is already
allowed for enums, it needs to be allowed for arbitrary integer
expressions as well. This covers the many places where plain integers
are used for bit fields, together with #define. This pattern is not as
typesafe as using enums, still it is common practice.
In line 769, the expression !finite(f) is a legitimate use of a function
that has return type int for traditional reasons. It's the same as for
ferror.
There are several other functions like unlink, open or strcmp that have
return type int as well, but with a different meaning. It is not yet
clear what the best way is to handle these different meanings. Having
to write finite(f) == 0 in strict bool mode doesn't look idiomatic, on
the other hand, !strcmp(s1, s2) is exactly the pattern that strict bool
mode wants to avoid.
In strict mode, allowing 1 as bool constant expression is probably not
needed in practice since most comparisons are != 0 instead of == 0.
Furthermore, in the expression (flags & 0x0002) == true, comparing with
true is misleading since the '==' operator can never evaluate to true in
this case.
The strict bool mode gets complicated because for system headers the
rules need to be relaxed since they cannot be changed easily, often not at all.
Still, if lint validates a program in strict bool mode, that program
must run with equal behavior regarding boolean expressions even on a
pre-C99 platform.
Seen in usr.bin/make/meta.c:1670: FD_ZERO(&readfds). These macros
cannot be fixed since system headers must not include <stdbool.h>.
Therefore INT constants should be accepted as controlling expressions as
well.