Added
This commit is contained in:
294
doc/lint/chap3
Normal file
294
doc/lint/chap3
Normal file
@@ -0,0 +1,294 @@
|
||||
.NH
|
||||
What lint checks
|
||||
.NH 2
|
||||
Set, used and unused variables
|
||||
.PP
|
||||
We make a distinction between two classes of variables:
|
||||
the class of automatic variables (including register variables)
|
||||
and the other variables.
|
||||
The other variables, global variables, static variables, formal
|
||||
parameters et cetera, are assumed to have a defined value.
|
||||
Global variables e.g., are initialized by the compiled code at
|
||||
zeros; formal parameters have a value which is equal to the value
|
||||
of the corresponding actual parameter.
|
||||
These variables can be used without explicitly initializing them.
|
||||
The initial value of automatic variables is undefined (if they are
|
||||
not initialized at declaration).
|
||||
These variables should be set before they are used.
|
||||
A variable is set by
|
||||
.IP
|
||||
.RS
|
||||
.IP 1.
|
||||
an assignment (including an initialization)
|
||||
.IP 2.
|
||||
taking the address
|
||||
.RE
|
||||
.PP
|
||||
The first case is clear. The second case is plausible.
|
||||
It would take to much effort (if at all possible) to check
|
||||
if a variable is set through one of its aliases.
|
||||
Because
|
||||
.I lint
|
||||
should not warn about correct constructs, it does this conservative
|
||||
approach.
|
||||
Structures (and unions) can also be set by setting at
|
||||
least one member.
|
||||
Again a conservative approach.
|
||||
An array can be set by using its name (e.g. as actual parameter
|
||||
of a function call).
|
||||
.I Lint
|
||||
warns for usage as
|
||||
.I rvalue
|
||||
of automatic variables which are not set.
|
||||
.PP
|
||||
A variable is used if
|
||||
.IP
|
||||
.RS
|
||||
.IP 1.
|
||||
it is used as a
|
||||
.I rvalue
|
||||
.IP 2
|
||||
its address is taken
|
||||
.IP
|
||||
Arrays and structures (and unions) are also used if one entry
|
||||
or one member respectively is used.
|
||||
.RE
|
||||
.PP
|
||||
When a variable is never used in the part of the program where it is
|
||||
visible, a warning is given.
|
||||
For variables declared at the beginning of a compound statement,
|
||||
a check is made at the end of this statement.
|
||||
For formal parameters a check is made at the end of the function
|
||||
definition.
|
||||
At the end of a file this is done for global static definitions.
|
||||
For external variables a warning can be given when all the files
|
||||
are parsed.
|
||||
.NH 2
|
||||
Flow of control
|
||||
.PP
|
||||
The way
|
||||
.I lint
|
||||
keeps track of the flow of control is best explained by means of
|
||||
an example.
|
||||
See the program of figure 1.
|
||||
.KF
|
||||
.DS B
|
||||
.ft CW
|
||||
if (cond)
|
||||
/* a statement which is executed if cond is true,
|
||||
* the if-part
|
||||
*/
|
||||
else
|
||||
/* the else-part */
|
||||
.DE
|
||||
.br
|
||||
.ce
|
||||
.I
|
||||
figure\ 1.
|
||||
.R
|
||||
.KE
|
||||
.PP
|
||||
After evaluation of \f(CWcond\fP, two things can happen.
|
||||
The if-part is executed or the else-part is executed (but not both).
|
||||
Variables which are set in the if-part but not in the else-part,
|
||||
need not be set after the if statement, and vice versa.
|
||||
.I Lint
|
||||
detects this and assumes these variables after the if statement to
|
||||
be \fImaybe set\fR.
|
||||
(See figure 2.)
|
||||
.KF
|
||||
.DS B
|
||||
.ft CW
|
||||
int cond;
|
||||
|
||||
main()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (cond) {
|
||||
i = 0;
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
use(i); /* i may be used before set */
|
||||
use(j); /* maybe j used before set */
|
||||
}
|
||||
.DE
|
||||
.br
|
||||
.ce
|
||||
.I
|
||||
figure 2.
|
||||
.R
|
||||
.KE
|
||||
.PP
|
||||
If both the if-part and the else-part are never left (i.e. they
|
||||
contain an endless loop or a return statement),
|
||||
.I lint
|
||||
knows that the if statement is never left too.
|
||||
Besides the if statement,
|
||||
.I lint
|
||||
knows the possible flows of control in while, do, for and
|
||||
switch statements.
|
||||
It also detects some endless loops like \f(CWwhile(1)\fP,
|
||||
\f(CWdo ... while (1)\fP, \f(CWfor (;;)\fP.
|
||||
.NH 2
|
||||
Functions
|
||||
.PP
|
||||
Most C compilers will not complain if a function is called with actual
|
||||
parameters of a different type than the function expects.
|
||||
Using a function in one file as a function of
|
||||
type
|
||||
.I A
|
||||
while defining it in another file as a function of type
|
||||
.I B
|
||||
is also allowed by most compilers.
|
||||
It needs no explanation that this can lead to serious trouble.
|
||||
.PP
|
||||
.I Lint
|
||||
checks if functions are called with the correct number of arguments,
|
||||
if the types of the actual parameters correspond with the types of
|
||||
the formal parameters and if function values are used in a way
|
||||
consistently with their declaration.
|
||||
When the result of a function is used, a check is made to see if
|
||||
the function returns a value.
|
||||
When a function returns a value,
|
||||
.I lint
|
||||
checks if the values of all calls of this function are used.
|
||||
.NH 2
|
||||
Undefined evaluation order
|
||||
.PP
|
||||
The semantics of C do not define evaluation orders for some
|
||||
constructs, which, at first sight, seem well defined.
|
||||
The evaluation order of the expression
|
||||
.ft CW
|
||||
a[i]\ =\ i++;
|
||||
.R
|
||||
e.g., is undefined.
|
||||
It can be translated to something with the semantics of
|
||||
.ft CW
|
||||
a[i]\ =\ i; i++;
|
||||
.R
|
||||
which is what probably was meant, or
|
||||
.ft CW
|
||||
a[i+1]\ =\ i; i++;.
|
||||
.R
|
||||
An easier example to explain why, is
|
||||
.ft CW
|
||||
j\ =\ a[i]\ +\ i++;.
|
||||
.R
|
||||
`\f(CW+\fR' Is a so called
|
||||
.I commutative
|
||||
operator (with respect to the evaluation order) , as is `\f(CW=\fR'.
|
||||
This allows the compiler to choose which term to evaluate first.
|
||||
It is easy to see, that it makes a difference for the value of
|
||||
.ft CW
|
||||
j,
|
||||
.R
|
||||
which order is chosen.
|
||||
The expression
|
||||
.ft CW
|
||||
i++
|
||||
.R
|
||||
is said to have
|
||||
.I
|
||||
side effects.
|
||||
.R
|
||||
It affects the value of
|
||||
.ft CW
|
||||
i.
|
||||
.R
|
||||
Because this value is used in the other term, this gives a conflict.
|
||||
.PP
|
||||
A function call with reference to a variable as argument can have
|
||||
side effects to.
|
||||
Therefor, the evaluation order of
|
||||
.ft CW
|
||||
i
|
||||
.R
|
||||
in the expression
|
||||
.ft CW
|
||||
f(&i)\ +\ i
|
||||
.R
|
||||
is undefined.
|
||||
When a function is called with an array as argument, this array
|
||||
can be affected by the function, because only the address of the
|
||||
array is passed to the function.
|
||||
(In Pascal a copy of the array is passed to the function if the
|
||||
formal parameter is not declared \fIvar\fP.)
|
||||
So the evaluation order of
|
||||
.ft CW
|
||||
a
|
||||
.R
|
||||
in the expression
|
||||
.ft CW
|
||||
f(a)\ +\ a[0]
|
||||
.R
|
||||
is undefined.
|
||||
This one is not yet detected by
|
||||
.I lint.
|
||||
.PP
|
||||
Global variables can still cause trouble.
|
||||
If function
|
||||
.ft CW
|
||||
f
|
||||
.R
|
||||
affects the global variable
|
||||
.ft CW
|
||||
i,
|
||||
.R
|
||||
the value of the expression
|
||||
.ft CW
|
||||
f()\ +\ i
|
||||
.R
|
||||
is undefined, because the evaluation order of \f(CWi\fP is undefined.
|
||||
.PP
|
||||
The evaluation order of the arguments of a function is not
|
||||
defined, so the expression
|
||||
.ft CW
|
||||
f(i,\ i++)
|
||||
.R
|
||||
gives a warning
|
||||
.ft CW
|
||||
i evaluation order undefined.
|
||||
.R
|
||||
.NH 2
|
||||
Pointer alignment problems
|
||||
.PP
|
||||
For pointers to objects of different types there are different
|
||||
alignment restrictions.
|
||||
On some machines pointers to type char can have both odd and even
|
||||
values, whereas pointers to type int should contain an even address.
|
||||
.I Lint
|
||||
could warn for all pointer conversions.
|
||||
This is not what
|
||||
.I lint
|
||||
does.
|
||||
.I Lint
|
||||
assumes that some pointers are more restricted than others, and
|
||||
that pointers of some types can safely be converted to a pointer
|
||||
of a less restrictive type.
|
||||
The order of restriction is as follows (`\(<=' means
|
||||
`is not more restricted than') :
|
||||
.PP
|
||||
.ce
|
||||
char \(<= short \(<= int \(<= long
|
||||
.ce
|
||||
float \(<= double
|
||||
.NH 2
|
||||
Libraries
|
||||
.PP
|
||||
C is a small language.
|
||||
As a matter of fact it has no i/o routines.
|
||||
To make it a useful language, C is supported by libraries.
|
||||
These libraries contain functions and variables that can be used by any
|
||||
C program.
|
||||
.I Lint
|
||||
knows some libraries too.
|
||||
At this moment it knows the `-\fIlc\fR', `-\fIlm\fR' and
|
||||
`-\fIlcurses\fR' libraries.
|
||||
The `-\fIlc\fR' library, containing definitions for functions from
|
||||
chapter two and three of the \s-2UNIX\s+2 programmers manual, is default.
|
||||
.I Lint
|
||||
warns for definitions of functions or global variables with the
|
||||
same name as a function definition in a library.
|
||||
.bp
|
||||
Reference in New Issue
Block a user