It took quite a while to get to the correct interpretation of this small
piece of code and to draw the right conclusions from it. Now the bug is
finally ready to be fixed, as already announced in the test.
This reduces the visual clutter. There is no reason for anyone to
modify the code around the CALL operator, therefore the assertion is not
expected to fail anytime soon.
The node was dereferenced before the null check. GCC 5.5 didn't warn
about this obvious bug, not even with -Wall -Wextra -O2. Such a case
didn't occur though in the few tests that this function was used in.
The indentation for the nested nodes only needs to be set for a few
lines of code, make this region as small as possible.
There are nodes that use both tn_left and tn_right, even though they are
not defined as binary operators. An example is CALL, for which tn_left
is the address of the function name and tn_right, which are the
arguments, linked via PUSH nodes. CALL is not a binary operator since
it doesn't do any calculations with its arguments.
It now resides right below dumpnode, which implements the same idea but
uses a fixed-size output buffer and prints everything in a single line,
which quickly gets hard to read. Maybe that's the reason why it had
been commented out since it got added in 2014.
From the code alone, it is too difficult to see how the various internal
operators are combined and what properties they have. A simple tree
visualization helps to see all the details.
This is used to track down the typo in check_precedence_confusion, to
see whether it could have possibly had any influence at all.
Anonymous structs and unions have been introduced in C11. The code of
make is supposed to be compatible with C90 though.
The additional members were intended to be used during an interactive
debugging session only and were thus not relevant to running the actual
code.
From the previous short names, it was no obvious that these functions
create a new tree node.
The function named funccall in lint2 has been left as-is, since it has a
completely different prototype.
Most of the code that deals with control statements is only interested
in the innermost control statement, and not if that is a stack or not.
Therefore, emphasize that part in the variable name.
The member c_next was confusing since the "direction" of this "next
element" was ambiguous. In a sequence of if statements, the "next"
element could have equally been the following one, not the surrounding
one.
It's shorter, and the other flags of the type or declaration also don't
have "is" in their names. Except for t_isenum, but that's because there
is a macro named t_enum that would interfere with that name.
Since several years GCC validates printf-style strings, and there is no
reason not to let GCC do that work. This prevents bugs like the
segmentation fault that was fixed in tree.c 1.109 from 2021-01-01.
By default, lint is compiled with DEBUG off, but it's easy enough to
compile it in debug mode once in a while.
The return value was only used in a single case. Duplicating the
condition for printing a message is ok in that case, since it makes all
other places in the code simpler.
The occasional "(void)" or "msg = " before the function call had hidden
the calls from check-msgs.lua, which didn't check the message texts in
such cases.
Even though this results in more lines of code, the benefit is that the
message text in the comment is verified by check-msgs.lua. The code is
also easier to read, the parentheses and asterisk were not needed.