123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- .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
|