home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlint1_0.zip
/
tlint1_0
/
doc
/
lnt10man.txt
< prev
next >
Wrap
Text File
|
1996-02-05
|
63KB
|
2,168 lines
LLIINNTT RReeffeerreennccee MMaannuuaall
by
J. A. Gardner
Thinkage Ltd.
85 McIntyre Drive
Kitchener, Ontario
Canada N2R 1H6
Copyright 1995 by Thinkage Ltd.
Thinkage Ltd. LINT Reference Manual
TTaabbllee ooff CCoonntteennttss
11.. IInnttrroodduuccttiioonn........................................................................................22
22.. LLIINNTT DDiirreeccttiivveess..................................................................................33
33.. LLIINNTT OOuuttppuutt..........................................................................................44
Message Classes........................................4
Output Grouping........................................6
Type Information.......................................7
44.. LLIINNTT CCoonnvveennttiioonnss................................................................................99
55.. UUnnuusseedd DDeeffiinniittiioonnss aanndd DDeeccllaarraattiioonnss........................................1100
Marking Symbols As Used...............................10
66.. UUnnddeeffiinneedd oorr UUnnddeeccllaarreedd DDaattaa OObbjjeeccttss......................................1111
77.. UUnnrreeaacchhaabbllee CCooddee..............................................................................1122
Marking Unreachable Code..............................12
88.. FFuunnccttiioonn RReettuurrnn VVaalluueess..................................................................1133
Ignoring Return Values................................14
99.. TTyyppee CChheecckkiinngg....................................................................................1155
1100.. FFuunnccttiioonn DDeeccllaarraattiioonnss..................................................................1177
The #pragma varargs Directive.........................18
The #pragma argsused Directive........................19
1111.. AAlltteerrnnaattee FFoorrmmss..............................................................................2211
1122.. MMiisscceellllaanneeoouuss NNootteess......................................................................2233
1133.. EExxttrraa CCoommppiilleerr WWaarrnniinnggss..............................................................2244
Alignment Problems....................................24
1144.. TThhee LLIINNTT CCoommmmaanndd LLiinnee..................................................................2266
Abbreviating Options:.................................30
Other Ways to Use LINT................................30
Summary Files.........................................30
LINT Libraries........................................31
Review of Inputs and Outputs..........................32
Multiple Definitions..................................32
Configuration Files...................................33
November, 1995 Page i
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 11
IInnttrroodduuccttiioonn
LINT is a program that examines C source code and makes
note of "irregularities" in the code. When LINT was first
implemented, its primary function was locating bugs and
inefficiencies. However, as the C programming language
spread to a variety of machines and systems, LINT was
enhanced to locate deviations from the strict definition of
C.
The ANSI standard for C now provides the "official"
definition of C. However, the ANSI standard does not
entirely describe the behavior of C implementations, because
the standard allows certain operations to be performed in a
system-dependent way. If a program is written in
conformance with the ANSI standard, avoiding such system-
dependent features, we say that the program is written in
_S_t_r_i_c_t_ _C.
Ideally, all programs should be written in Strict C,
since these programs are maximally portable. One of the
major functions of LINT is to detect code constructs which
do not conform with Strict C. Such constructs are often
valid and can be used in working programs, but they are not
truly portable and may be indications of loose programming
style. LINT shows where you have written non-portable code;
for portability, you should try to remove such code.
Before we begin, we should note that it is inevitable
that LINT will miss some problems and will also complain
about code that turns out to be valid. The designers have
tried to chart a course between too much laxness (which may
miss significant irregularities) and too much nit-picking
(which produces quantities of irrelevant output that you
will likely ignore). Thus we have designed this version of
LINT to report situations that are _u_s_u_a_l_l_y signs of errors.
While odd constructions and unusual programming style can
confuse LINT from time to time, the majority of material
that LINT locates should deserve the programmer's attention.
Page 2 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 22
LLIINNTT DDiirreeccttiivveess
LINT understands all the usual C preprocessing
directives (e.g. ##iinncclluuddee,, ##ddeeffiinnee,, etc.). In addition,
LINT recognizes a number of other directives that have the
same sort of format:
#pragma aligned
#pragma argsused
#pragma notreached
#pragma optresult
#pragma used
#pragma varargs
These directives tell LINT about special features of your
source code and allow LINT to provide more meaningful
diagnostic messages. The usage of each LINT directive is
explained later in the manual.
ANSI C compilers should not reject these special LINT
directives; the ANSI standard says that C compilers are
supposed to ignore any ##pprraaggmmaa directives they do not
understand. However, non-ANSI C compilers may issue
diagnostic messages for these ##pprraaggmmaa directives, and even
some ANSI C compilers may issue warnings about unrecognized
##pprraaggmmaas.
November, 1995 Page 3
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 33
LLIINNTT OOuuttppuutt
LINT generally produces quite a lot of output. By
default the output is written to the terminal, but it can be
redirected to a file using the standard output redirection
constructions on the LINT command line.
The first lines of output from LINT are diagnostic
messages comparable to those that might be produced by a C
compiler. These diagnostics describe easily detected things
like syntax errors.
Following this comes output that is unique to LINT.
Most lines in the output have the form
filename,lineno: class: text
where filename is the name of one of the source files that
LINT is scanning and lineno is a line number within that
file. The class field tells the type of problem found; see
"Message Classes" below for more information. The text part
of the message provides specific information about the
problem.
Some lines may have the form
libname: class: text
where libname is the name of a LINT Library. For more
information on LINT libraries, see the last section of this
manual.
MMeessssaaggee CCllaasssseess
Each message produced by LINT is labelled with a string
indicating what kind of problem the message describes. The
following message classes are recognized:
Error:
Same as error messages produced by the compiler: code
so incorrect that there is no way to generate any sort
of object code.
Warning:
Marks a construct that is invalid but a compiler could
still generate some kind of object code. For example,
the ANSI standard does not allow assignments between
pointers of different types, but most compilers can
Page 4 November, 1995
Thinkage Ltd. LINT Reference Manual
still generate sensible object code for such an
operation.
Unusual:
Marks a construct which is valid, but which is not
often seen in C programs. For example,
i=i;
is valid but suspicious, possibly indicating some
problem in your code.
Note:
Marks a construct which is invalid but always works
properly on the current machine. For example,
printf("%ld",1);
is invalid since %ld requires a lloonngg argument but 1 is
just iinntt. However, this always works properly on
machines where lloonngg and iinntt are the same size.
MachDepd:
Marks a valid construct whose behavior is machine-
dependent. For example, the result of (-7/2) is
machine-dependent, since the ANSI standard allows this
kind of division to truncate either towards or away
from zero.
Extension:
Marks a construct that is an extension to the ANSI
standard.
Efficiency:
Marks code that has been written in a particularly
inefficient way, or using constructs that are likely to
execute slowly.
NotMinimal:
Marks a construct which is valid ANSI C but may not be
accepted by older C compilers (e.g. vvooiidd ** pointers).
Info:
Provides cross-reference information while using LINT.
IntrnErr:
An internal error in LINT itself (for example, a table
overflow).
November, 1995 Page 5
LINT Reference Manual Thinkage Ltd.
OOuuttppuutt GGrroouuppiinngg
LINT output is grouped according to the functions of the
source code.
The first line of a group of messages gives the name of
a function or an external variable. After that come all the
messages pertaining to that function or variable. The
messages end with a blank line, followed by the group of
messages for the next function or variable.
Groups are sorted in alphabetical order according to the
name of the function or variable.
The first line of every function group gives the name of
the function and the type of value that the function
returns. If LINT has found a definition for the function,
the first line of the function group is
Function "NAME" returns "TYPE".
where NAME is the name of the function and TYPE is the type
of value that the function returns.
If LINT can't find a definition for the function, LINT
looks at the first _r_e_f_e_r_e_n_c_e to the function that appears in
the source code and prints
Function "NAME" is assumed to return "TYPE".
where TYPE is the type suggested by the way in which the
function is used. In keeping with the rules of C, LINT
assumes that a function returns iinntt if the function is not
explicitly declared to have a different type. If the first
reference to the function does not use a return value from
the function, the message is
Function "NAME" assumed to return no value.
If LINT scans a function definition and finds that there
are no rreettuurrnn statements that return a value, LINT outputs
the message
Function "NAME" returns no value.
You should distinguish between this message and
Function "NAME" returns void.
Page 6 November, 1995
Thinkage Ltd. LINT Reference Manual
The vvooiidd message appears when a function is explicitly
declared with the vvooiidd keyword. The "no value" message
appears when a function definition has no rreettuurrnn statements.
The first appearance of an external variable is treated
in much the same way as the first appearance of a function.
You will see a message like
External "NAME" is "TYPE".
or
External "NAME" is assumed to be "TYPE".
With one exception, the messages we have described so
far are always issued, whether or not there are errors. The
exception is when a symbol appears in a LINT library
(described later on) and is not referenced in normal source
code. Messages about library functions and variables only
appear if the symbol is used in source code.
Other messages in LINT output describe situations that
may be errors. These messages refer to difficulties within
the function with which they are grouped.
TTyyppee IInnffoorrmmaattiioonn
At the end of its output, LINT displays a block of
information describing the types of the program. A typical
line of output is
filename,lineno: type
where filename is the name of the file where the type was
defined and lineno is the line number where the definition
began.
LINT provides information about any ttyyppeeddeeffs, enumerated
types, structures, and/or unions that were involved in the
messages produced. This lets you locate the definitions of
these types.
If a type appears twice in this list, it usually means
that there is more than one definition for the same type and
the types are not assignment-compatible.
LINT also checks for structures and unions which are
used in functions and which have been incompletely defined.
Incomplete definitions are acceptable as long as there is a
complete definition somewhere. All complete definitions
November, 1995 Page 7
LINT Reference Manual Thinkage Ltd.
have to be identical. If complete definitions conflict with
each other, LINT issues a diagnostic beginning with
filename : type
where filename is the name of a file where the type was used
and found to conflict with another definition.
Page 8 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 44
LLIINNTT CCoonnvveennttiioonnss
A function is _d_e_f_i_n_e_d by the function header that
actually starts the function. This tells the type of value
that the function returns and describes the arguments of the
function. An external variable is _d_e_f_i_n_e_d by a declaration
for the variable that is outside the scope of all functions
and that does not include the keyword eexxtteerrnn.
A function is _d_e_c_l_a_r_e_d by a declaration or function call
inside another function. An external variable is _d_e_c_l_a_r_e_d
by a declaration that includes the keyword eexxtteerrnn. Such a
variable declaration does not allocate space for the
variable; it merely describes the type of the variable and
presumes that the variable is defined elsewhere.
A variable is _s_e_t if it is assigned a value or if a
pointer to the variable is taken. Similarly, a variable is
_u_s_e_d if its value is used or if a pointer is taken. (You
might wonder why taking a pointer marks a variable as both
"set" and "used". The answer is that once a pointer to a
variable is taken, LINT can't keep track of assignments or
uses of the variable through the pointer. Once the pointer
is taken, LINT can only assume that the data object may have
been both set and used.)
November, 1995 Page 9
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 55
UUnnuusseedd DDeeffiinniittiioonnss aanndd DDeeccllaarraattiioonnss
One of the easiest problems for LINT to find is a
variable or function that is defined but not used or called
in the rest of the program. Such items can usually be
deleted, since they are not performing any function in the
program. The diagnostic messages for such situations are
listed and explained below.
Function "NAME" is never called.
The given function was defined in the source code but
never called.
External "NAME" is never used.
The given external variable was defined but never used.
External "NAME" is defined but never set or used.
This is essentially the same as the previous message.
External "NAME" is set but never used.
The given external variable was assigned a value, but
then was never used for anything.
Messages are _n_o_t generated if a symbol in a LINT library is
unused.
MMaarrkkiinngg SSyymmbboollss AAss UUsseedd
Sometimes, you may intentionally declare a variable
without using it. For example, suppose a variable is only
used inside a ##iiff block and that block of code is not
compiled because the ##iiff condition is not met. LINT would
normally issue an error message for this condition, but you
might not consider this situation an error.
To avoid this sort of message, you can add the LINT
directive
#pragma used NAME NAME NAME ...
to your source code. This tells LINT that the names listed
in the directive are used by your program, even if it
doesn't look like they are.
Page 10 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 66
UUnnddeeffiinneedd oorr UUnnddeeccllaarreedd DDaattaa OObbjjeeccttss
LINT uses a simple-minded way to find places where
undefined variables are used: a variable is assumed to be
undefined if a statement using the variable appears in the
code before the variable is set. Of course, it is possible
to construct programs where this approach fails. With the
use of spaghetti-like ggoottoos, the top-down technique can be
outwitted.
Because static and external variables are automatically
initialized to zero by the compiler if they are not
initialized explicitly, LINT does not pick up problems with
these variables.
The following diagnostics pertain to data objects that
are used before they are set, defined, or declared.
Function "NAME" is called but never defined.
The source code contains a call to the given function,
but the function is not defined anywhere in the code.
"NAME" is set but never defined.
The given variable has been assigned a value, but a
proper definition does not appear in the source code.
"NAME" is used but never defined.
The value of the given variable was used, but the
variable was never defined.
"NAME" is used but never defined or set.
The value of the given variable has been used, but the
variable was neither defined nor set.
"NAME" is defined and used but never set.
The given variable is defined and used, but never set.
This message is only issued for local variables, since
all external variables are automatically initialized to
zero (if no explicit initialization is specified).
November, 1995 Page 11
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 77
UUnnrreeaacchhaabbllee CCooddee
LINT attempts to detect parts of the source code that
cannot be reached (for example, unlabelled statements
following a ggoottoo). It also attempts to find loops that can
never be exited from the bottom, such as wwhhiillee((11))...... At the
same time, LINT finds loops that cannot be entered from the
top.
The message that is issued for detected unreachable code
is
Non reachable code at "TEXT".
where TEXT is the source code that cannot be reached.
MMaarrkkiinngg UUnnrreeaacchhaabbllee CCooddee
LINT cannot detect functions which are called and never
return (for example, ones that terminate execution via
exit). This means that it is possible for LINT to miss some
unreachable code, as in
g()
{
exit(-1);
}
f()
{
...
g();
/* everything that follows
* is unreachable */
...
}
To mark this kind of situation, you can use the LINT
directive
#pragma notreached
When this directive appears in your source code, LINT
regards any source code following the directive as
unreachable, up to the end of the block or the next
statement label. Appropriate diagnostic messages will be
issued.
Page 12 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 88
FFuunnccttiioonn RReettuurrnn VVaalluueess
LINT reports functions that contain both
return( expression );
and
return;
This kind of situation usually results in errors (since the
calling function may assume a value is being returned but
one of the rreettuurrnn statements does not return a value).
Correspondingly, LINT makes note of whether or not a
call to a function makes use of a return value from the
function. If the caller expects a value but the function
does not return one, it is clearly a bug. If the function
returns a value but the the caller does not use it, it could
be an error, an inefficiency, or sloppy programming style.
If a function definition contains no rreettuurrnn statements
that return a value, LINT regards the function type as iinntt
unless it is explicitly declared differently. If LINT finds
a reference to the function before it finds the function
definition, it assumes that the function returns a value
unless the function is explicitly declared as vvooiidd.
Programmers who are used to looser controls than this will
find themselves with a large number of diagnostic messages.
The messages related to function return values are
listed below.
Value is used but none returned.
A function did not return a value, but the statement
that called the function behaved as if a value was
returned.
Function NAME has no return value
A function was defined as returning a value (the
function is not vvooiidd)) but it did not contain a
return(expression)
statement.
Return value ignored.
The given function contains a
November, 1995 Page 13
LINT Reference Manual Thinkage Ltd.
return(expression);
statement, but the caller never uses the return result.
Return value sometimes ignored.
This is similar to the last situation, except that the
return result is sometimes used, sometimes not.
IIggnnoorriinngg RReettuurrnn VVaalluueess
There is always the possibility that you want to write a
function whose return value can be ignored. The C library
has several functions whose return value is superfluous.
For example,
strcpy(A,B)
copies string B into string A and returns a pointer to A.
This is unnecessary, since the caller already has a pointer
to A.
LINT lets you mark functions with optional return values
by using a directive similar to the ##directives of the C
preprocessor.
#pragma optresult
can be placed immediately before the definition of a
function that returns an optional result. LINT then
recognizes that this function returns a result that can be
ignored; LINT does not give error messages if the result is
ignored.
Page 14 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 99
TTyyppee CChheecckkiinngg
LINT enforces stronger type-checking than most compilers
do. In expressions where different types of data are
intermixed, LINT observes the strict conventions for
conversions of data and requires that everything else be
properly cast.
LINT checks for type incompatibilities in three places:
(a) in the arguments passed to functions
(b) in the return values received by functions
(c) in structure manipulations
For fullest type-checking, the code should use prototypes
wherever possible. LINT also checks for situations in which
some function calls take place with a prototype in scope
while others do not.
When arguments are passed to functions, LINT issues a
diagnostic if the argument type passed by the caller differs
from the argument type expected by the called function.
Similarly, LINT complains if the argument type returned by
the called function differs from the argument type expected
by the caller. The messages associated with this situation
are given below.
Argument N is "TYPE1", but declared as "TYPE2".
When the given function was called, the caller passed a
value of type TYPE1 for argument number N, but the
called function expected a value of TYPE2. For
example, you might see
Argument 2 is "int", declared "unsigned int".
This indicates that the caller passed an integer value
as the second argument of the function, but the called
function expected an unsigned integer.
Argument N is "TYPE", but declared as a different "TYPE"
This is an odd situation where the definition and a
declaration give the argument different types, but the
strings used to print out TYPE turn out to be the same.
For example, suppose that a function has a local ssttrruucctt
X, but there is also an external ssttrruucctt X which is not
compatible with the local one. If the program
invalidly tries to combine external and local variables
of type X, you get the above message; even though the
types have the same name, they are different. The same
November, 1995 Page 15
LINT Reference Manual Thinkage Ltd.
sort of situation may happen with other LINT error
messages.
"NAME" is redeclared as function type "TYPE".
When NAME was first declared, it was said to return a
value of one type. Now NAME has been declared or used
as a function returning a different type of value.
"NAME" declared as returning "TYPE"
The function NAME has been declared as returning a TYPE
that is different than its definition.
"NAME" declared as "TYPE"
The variable NAME has been declared with a TYPE that is
different than its definition.
"NAME" is redefined as function.
NAME was originally declared as a variable, but is now
being defined as a function.
LINT also issues a message whenever a data object is
implicitly shortened. For example, suppose we have
long l;
int i;
/* stuff */
i = l;
The C compiler automatically shortens the long "l" and
assigns the result to "i". However, LINT flags this as a
potential problem (since different integer sizes on
different machines may affect how this works). No error
message is issued if the conversion is done explicitly, as
in
i = (int) l;
As a final note about type-checking, LINT occasionally
gets some complicated types wrong. For example, warnings
about structures that contain arrays of structures do not
give the right type (namely ssttrruucctt). The same problem
occurs when LINT is not given the internal structure of a
ssttrruucctt. For example, it is valid for a source module to
declare
struct ABC *ptr;
without describing the internal structure of the ABC ssttrruucctt.
In such cases, LINT does not have enough information to
determine if code is valid, so the warning messages may not
be entirely accurate.
Page 16 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 1100
FFuunnccttiioonn DDeeccllaarraattiioonnss
LINT compares all the available prototype declarations
for a function to make sure that the prototypes match
_e_x_a_c_t_l_y. For example, LINT notes situations where one
prototype gives vvooiidd ** as the type of an argument while
another types the same argument as cchhaarr **. In practice,
there is no difference between these two pointer types;
however, LINT makes note of the situation because it may be
indicative of an error.
In addition to checking that the argument types expected
by a called function match the argument types passed by the
caller, LINT also checks that the _n_u_m_b_e_r of arguments
expected by the called function matches the number of
arguments passed by the caller. If there is a mismatch, it
prints
Called with N arguments, requires M
where N is the number of arguments that the caller passes
and M is the number of arguments that the function expects.
Whenever possible, LINT checks to see that argument
declarations in function prototypes agree exactly with the
declarations in the function definition. If the
declarations do not agree, LINT outputs
Prototype argument N is "TYPE" but declared as
"TYPE"
LINT expects argument declarations to match exactly. For
example, the vvooiidd ** type is considered assignment-compatible
with all pointer types and therefore there is not a conflict
between vvooiidd ** and another pointer type. Nevertheless, LINT
points out the difference, simply to warn you that there
seems to be a discrepancy in your code.
Finally, LINT makes sure that the number of arguments in
a prototype declaration matches the number in the function
definition. If not, LINT prints
Prototyped with N arguments, but requires M
where M and N are both integers.
November, 1995 Page 17
LINT Reference Manual Thinkage Ltd.
TThhee ##pprraaggmmaa vvaarraarrggss DDiirreeccttiivvee
In earlier versions of C it was valid to pass more
arguments than the function definition specifies or to pass
fewer arguments. This is not valid in ANSI C unless you use
the "..." construct in the prototype; however, older code
may still make use of such calling sequences and most
compilers still handle the situation properly.
In order to handle all the possibilities of this
situation, LINT introduces the ##pprraaggmmaa vvaarraarrggss directive.
The directive has two forms.
#pragma varargs N
indicates that the next function to be defined can take a
variable number of arguments but must have a minimum of N
arguments. For example, we might write
#pragma varargs 3
int Mini(N,a,b,c,d);
int N,a,b,c,d;
{ ....
to declare a function Mini that must take at least three
arguments and can have more. In this case, LINT does not
issue an error message if you have at least three integer
arguments present.
With this form of the ##pprraaggmmaa vvaarraarrggss directive, LINT
typechecks all the arguments that are present. In the above
example, LINT ensures that all the arguments being passed
are integers.
The second form of the directive is
#pragma varargs N M
where both N and M are integers. This indicates that the
next function to be defined must have a minimum of N
arguments, and LINT should typecheck up to M arguments if
they appear. For example, you can imagine a printf-like
function that takes a format string plus one or more values
to print. This could be preceded with
#pragma varargs 2 1
showing that the function must always have two arguments (a
format string and at least one output value) but that only
Page 18 November, 1995
Thinkage Ltd. LINT Reference Manual
the first argument should be typechecked (since the output
value(s) need not have a fixed type).
The directive can also take the form
#pragma varargs printf
#pragma varargs scanf
These forms may be used to indicate functions that take
format strings comparable to the strings of printf and scanf
(respectively). LINT compares the placeholders in the
format string to the types of the arguments that follow the
format string, and reports any conflicts between types. For
example, it tells you if the argument corresponding to a %s
placeholder is an iinntt value (incompatible with %s).
TThhee ##pprraaggmmaa aarrggssuusseedd DDiirreeccttiivvee
Some functions are able to use all the arguments they
are passed without actually referring to every argument by
name. For example, consider a function Max10 which can
accept up to 10 iinntt arguments and return the value of the
largest argument. The first argument passed to Max10 tells
how many values have actually been passed. This could be
defined with
int Max10(N,a,b,c,d,e,f,g,h,i)
int N,a,b,c,d,e,f,g,h,i;
{
int j,m,*p;
m = a;
p = &a;
for (j=1; j < N; ++j)
if (p[j] > m) m = p[j];
return(m);
}
As you can see, the function does not refer to the
parameters b, c, etc. by name. However, it does look at
their values, since it walks through the stack using offsets
from a. Therefore the values are used.
This sort of coding practice is a violation of the ANSI
standard. The standard doesn't let you use subscripts to
access memory locations outside the bounds of a single
object, so p[j] is invalid if j is not zero. On the other
hand, many compilers still accept code like this and older
programs may use it.
November, 1995 Page 19
LINT Reference Manual Thinkage Ltd.
For such programs, you can avoid some diagnostic
messages from LINT by putting the LINT directive
#pragma argsused
on a line preceding the function, as in
#pragma argsused
int Max10(N,a,b,c,d,e,f,g,h,i)
...
This tells LINT that the function uses all its arguments,
even if it doesn't appear to.
Page 20 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 1111
AAlltteerrnnaattee FFoorrmmss
For compatibility with the Bell Labs' version of LINT,
this version of LINT may accept some directives in the form
of comments. These are only recognized if the
+ControlComments option is specified on the LINT command
line.
/*VARARGSN*/
(where N is an integer) is automatically converted to
#pragma varargs 0 N
For example,
/*VARARGS3*/
is equivalent to
#pragma varargs 0 3
In addition,
/*VARARGS*/
(with no value N) is equivalent to
#pragma varargs 0
In addition to VARARGS, the comment
/*ARGSUSED*/
is automatically converted to
#pragma argsused
and the comment
/*NOTREACHED*/
is equivalent to
#pragma notreached
In all cases, the comment form may not contain white
space (blanks, tabs, or new-lines). All alphabetic
characters must be in upper case and there can be nothing
November, 1995 Page 21
LINT Reference Manual Thinkage Ltd.
else in the comment except the keyword and any number that
should follow.
Page 22 November, 1995
Thinkage Ltd. LINT Reference Manual
CChhaapptteerr 1122
MMiisscceellllaanneeoouuss NNootteess
LINT always uses the full name of functions and
variables, and always distinguishes between upper and lower
case letters. This is the way that C compilers are supposed
to work as well. However, some compilers or loaders
truncate long names to a certain number of characters, and
some compilers or loaders do not distinguish between the
case of letters in names. For this reason, LINT issues the
following warnings.
NAME1 and NAME2 not unique in first N caseless characters.
N is the number of characters to which names may be
truncated to meet loader requirements.
NAME1 and NAME2 not unique without case distinction.
This applies to names like VAR, var, and Var used in
the same program.
LINT detects redeclaration of functions and variables
defined outside the scope of any function. The set of
messages dedicated to this kind of problem are given below.
NAME redeclared.
A given variable has been invalidly declared in a
second place.
NAME retyped as "TYPE".
A given variable has been used as if it had a type
different from its declared type.
NAME redeclared with type "TYPE".
The given variable appears in a new declaration with a
different type than it previously had.
NAME is redefined as function.
A name that was previously given to an external
variable has now been given to a function.
LINT assumes that sshhoorrtt integers have a length of 16
bits and that lloonngg integers have a length of 32 bits,
regardless of what length these data types have on your
machine. The reason is that short and long integers are
guaranteed to have at least these lengths on all machines.
Your hardware may allow longer integers (for example, 36
bits) but code that uses the increased size is not portable
to machines with smaller words. For the same reason, LINT
assumes that all characters are 8-bit signed quantities,
even though they may be longer or unsigned on your machine.
November, 1995 Page 23
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 1133
EExxttrraa CCoommppiilleerr WWaarrnniinnggss
In addition to the diagnostics produced especially for
LINT, the LINT output also contains all the error and
warning messages produced by the parsing phase of the C
compiler. Most of these are self-explanatory, but there are
a few that deserve further comment.
Constant "CONSTANT" too large for "TYPE".
As noted earlier, LINT assumes short integers are 16
bits long and long integers are 32 bits long.
Therefore you may get this message, even though a short
or long integer type on your machine is actually long
enough to hold a given constant.
Character constant with no characters.
Some compilers do not accept a null character constant.
Your compiler may accept such constants, but LINT still
complains about the construct.
Constant valued logical expression.
This refers to situations like
while (1) { ... }
AAlliiggnnmmeenntt PPrroobblleemmss
In addition to the error messages listed above, you may
receive the warning
Possible alignment problems with cast
When casting data of one type to data of another,
alignment problems may occur. For example, there may be
difficulties in casting a character pointer to an integer
pointer if the character pointer is not aimed at a word
boundary. At times, however, you may have taken pains to
make sure that this kind of alignment problem will not
occur. In particular, you may have created a function that
returns a value or pointer that is suitably aligned for any
use. This is true of functions like malloc; the value that
malloc returns is officially a vvooiidd ** pointer, but it is
suitably aligned to store any sort of data.
If you have a function that returns a suitably aligned
pointer, you can tell LINT by placing
#pragma aligned
Page 24 November, 1995
Thinkage Ltd. LINT Reference Manual
in front of the start of the function declaration. This
tells LINT that the function itself deals with any alignment
problems.
November, 1995 Page 25
LINT Reference Manual Thinkage Ltd.
CChhaapptteerr 1144
TThhee LLIINNTT CCoommmmaanndd LLiinnee
_S_y_n_t_a_x_:
tlint [file] [option]*
(+|-)ControlComments (-) (+|-)Declarations (-)
(+|-)Keep (-) (+|-)StandardLibrary (+)
(+|-)Verbose (-) (+|-)Wide (-)
Configuration=file CrossReference=keyword
Define=name=value Include=directory
INSTallation=file Library=lib
libraryName=string Output=file
Output+=file StandardInclude=directory
StandardLibrary=name Summary=file
Target=keyword indeX=file
_E_x_a_m_p_l_e_s_:
tlint myfile
tlint x=files o=incls ln=proj def=PROJECT=1
_O_p_t_i_o_n_s_:
file
is a source file containing C code. The other options
on the command line determine whether LINT scans this
file for problem spots, or uses the file to create a
summary or an entry in a LINT library.
indeX=file
gives the name of a text file. Each line in this text
file should contain the name of one C source file.
LINT checks each of these source files individually.
In addition to a source file name, a line in an index
file may specify ControlComments, Configuration=,
Include= and Define= options. These options only apply
to the source file named on the same line. For
example, if the line
myfile define=VERSION=1
appeared in an index file, LINT would use the given
option when examining myfile but not for other files
named in the index file. When processing an index
line, LINT normally uses all the options appearing on
the main command line, followed by the options
specified on the index line. As a special case,
however, Include= options on a line in an index file
are used before any Include= options on the LINT
command line. Only one indeX= option may appear on the
command line.
Page 26 November, 1995
Thinkage Ltd. LINT Reference Manual
Configuration=file
specifies a configuration file for LINT. For more
information on configuration files, see below.
+ControlComments
indicates that control comments of the type
/*VARARGS*/
should be processed. The default is -ControlComments,
in which case such comments are ignored. A
ControlComments option on a line in an index file
overrides any ControlComments option on the main LINT
command line.
CrossReference=keyword
indicates that LINT output should include a cross-
reference table that shows where symbols are defined,
referenced, set, and used. (By default, cross-
references are not provided.) Possible values for the
keyword are:
All - cross-references all symbols;
External - only cross-references external symbols.
+Declarations
may be used when creating a LINT library or summary
file. With this option, LINT treats every file scope
declaration as if it were a definition for the
variable, instead of a simple reference.
Define=name=value
has the same effect as
#define name value
in the C source code. The option indicates that "name"
should be replaced with "value" (as text) wherever it
appears in the source code being examined. If "value"
contains blanks or tab characters, it should be
enclosed in double or single quotes.
Include=directory
is the same as the Include= option for the C compiler.
When LINT tries to find quoted include files, as in
#include "file"
it begins by searching the given directory for the
file. If the file is not found there, LINT searches
November, 1995 Page 27
LINT Reference Manual Thinkage Ltd.
any directory named in StandardInclude= options, and
finally searches the directory that contains the source
file being examined. Any number of Include= options
may be specified. Directories are searched in the
order given on the command line.
INSTallation=file
tells LINT where to find the installation file. The
installation file tells where various software
components have been installed. For more information,
see the section on _I_n_s_t_a_l_l_a_t_i_o_n_ _F_i_l_e_s below.
If you do not specify an INSTallation= option on the
command line, LINT checks for an environment variable
named LINT_INST and uses its value as the name of the
installation file. If this environment variable does
not exist, LINT uses the default installation file.
+Keep
does not delete intermediate files left by the
preprocessor and the LINT steps.
Library=lib
names a LINT library that should be used when checking
source code. Any number of Library= options may appear
on the command line. By default, LINT automatically
includes LINT libraries of standard C functions (e.g.
printf) so that such functions are always recognized.
libraryName=string
is used when creating a LINT library. See below for
more details.
Output=file
is used when creating a LINT library or summary file
(see below). The output overwrites the file's current
contents.
Output+=file
is the same as Output=file, except that output is
written to the end of the current contents of the
specified file, rather than overwriting what the file
already holds.
StandardInclude=directory
is the same as the StandardInclude= option for the C
compiler. When LINT tries to find include files whose
names are enclosed in angle brackets, as in
#include <file>
Page 28 November, 1995
Thinkage Ltd. LINT Reference Manual
it begins by searching the given directory for the
file. If the file is not found there, LINT searches
directories named in Include= options, and finally
searches the directory that contains the source file
being examined. Any number of StandardInclude= options
may be specified. Directories are searched in the
order given on the command line.
StandardLibrary=name
asks LINT to include the standard library indicated by
"name". The following names are recognized:
C - the standard C library. This is included
automatically, unless -StandardLibrary is specified.
-StandardLibrary
does not include the standard C library routines.
Summary=file
states that the given file is a summary file that
should be used as input to the LINT operation. See
below for more on summary files.
Target=keyword
controls the kind of problem-checking you want to do.
The following keywords are recognized.
Host - describes any problems that may arise if the
program is run on the host machine (i.e. the machine
where you are running LINT). This is the default.
Extensions - points out any extensions to C that might
have been used, as well as any machine-dependencies in
the code. It also describes the problems detected with
Target=Host.
Minimal - points out any features that may cause
problems if you port this program to a non-ANSI
compiler. This will make note of all ANSI features
used. It also describes the problems detected with
Target=Extensions.
+Verbose
prints out the name of the file being examined. The
default is -Verbose.
+Wide
prints output in a format that is 132 columns wide.
The default is -Wide, which prints in an 80-column
format.
November, 1995 Page 29
LINT Reference Manual Thinkage Ltd.
_A_b_b_r_e_v_i_a_t_i_n_g_ _O_p_t_i_o_n_s_:
The option keywords given above can be abbreviated by
omitting any or all of the letters shown in lower case. For
example, CrossReference=All may be abbreviated to
crossref=all
cref=all
cr=all
cr=a
and so on. When entering option keywords, you may type
letters in upper, lower, or mixed case; the use of upper and
lower case in this documentation is simply to show what
letters are and aren't required.
_O_t_h_e_r_ _W_a_y_s_ _t_o_ _U_s_e_ _L_I_N_T
In addition to checking C code for irregularities, LINT
can:
(a) Extract a summary file of information that can be used
in other LINT operations.
(b) Create a LINT library.
Summary files and LINT libraries are discussed below.
_S_u_m_m_a_r_y_ _F_i_l_e_s
A summary file contains a "summary" of your source code:
the names and types of all the external variables and
functions defined or referenced in the code, plus any other
information LINT may need when checking the code (such as
the declared types of function parameters). Summary files
also record any error messages that might be issued by the C
compiler when parsing the source code. All of this
information is stored in a special format that is not
directly readable by humans.
To create a summary file from a normal source code file,
use the Output=file option, as in
tlint src1.c output=summ
You can add more material to the same summary file using
Output+=file, as in
Page 30 November, 1995
Thinkage Ltd. LINT Reference Manual
tlint src2.c output+=summ
This appends new material to the existing contents of the
summary file.
When LINT creates a Summary file, LINT only summarizes
your source code and checks for syntax errors. It does not
check for such problems as non-portable constructs or type
mismatches. However, you can run a summary file through
LINT again to do standard type-checking. For example,
tlint srcfile output=lf
tlint summ=lf
creates a summary file, then uses the information in the
summary file to see if types match in symbol references and
definitions.
The reason for creating summary files is the same as the
reason for breaking up the source code of your program into
several source files: it is easier to deal with source code
in small pieces than in one big hunk. Some users may keep a
summary file for every source file. If the code in one
source file is changed, you can create a summary file from
that source file, then run all the summary files of the
program through LINT to see if the change has caused any
problems. This is much faster than using LINT on all the
raw source code.
_L_I_N_T_ _L_i_b_r_a_r_i_e_s
A LINT library is similar to a summary file, in that it
contains a summary of C source code. However, LINT
libraries are intended to parallel the way that object
libraries work.
To create a LINT library, specify both the Output=
option and the libraryName= option on the LINT command line.
For example,
tlint file output=mylib libname="abc"
creates a LINT library named abc in the file mylib. This
name is used in LINT diagnostic messages related to symbols
found in the LINT library. Using LINT in this way only
generates minimal messages; full messages are printed when
you actually use the LINT library.
To use a LINT library, specify the Library= option on
the LINT command line, as in
November, 1995 Page 31
LINT Reference Manual Thinkage Ltd.
tlint myfile library=mylib
When LINT finds that myfile contains a reference to an
undefined symbol, LINT checks the information in the given
LINT library to see if the symbol is defined there. This
works just like compiling a module while referring to an
object library. No error occurs if a symbol in the LINT
library has the same name as a symbol in the source file;
the source file symbol is the one that is used.
Functions should only be placed in a LINT library when
you are sure they contain no errors. LINT does not look for
errors when it is creating a LINT library.
_R_e_v_i_e_w_ _o_f_ _I_n_p_u_t_s_ _a_n_d_ _O_u_t_p_u_t_s
To specify a file as an input, simply give the file's
name. To specify a summary file as input, use Summary=file.
To specify a LINT library as input, use Library=file. LINT
uses all of the contents of a source file or a summary file;
it only uses library entries if they are referenced by
source code or a summary file.
An index file contains partial command lines to be used
by LINT in its operations. These command lines can name
source files as input, but not summary files or LINT
libraries.
When both an Output= and libraryName= option are
specified, LINT creates a LINT library. If only Output= is
specified, LINT creates a summary file. If Output= is not
specified, LINT examines a source file or summary file for
problem spots and writes its diagnostics to the standard
output.
_M_u_l_t_i_p_l_e_ _D_e_f_i_n_i_t_i_o_n_s
If LINT finds two definitions for the same function or
external variable, it always outputs a diagnostic message.
If the two definitions are both in normal source code, LINT
arbitrarily chooses the first definition it finds as the
"correct" definition, and issues diagnostics for any later
deviations from this definition. If one of the two
definitions is in a LINT library and the other is in normal
source code, LINT chooses the non-library version as the
"correct" definition. In this way, a definition in normal
source code overrides a library definition.
Page 32 November, 1995
Thinkage Ltd. LINT Reference Manual
_C_o_n_f_i_g_u_r_a_t_i_o_n_ _F_i_l_e_s
A configuration file consists of a series of directives
that control the behavior of LINT. The possible directives
are explained below.
define name string
has the same format and purpose as a ##ddeeffiinnee directive
in normal C code. It creates a manifest or macro with
the given value.
inline includefile
lets you simulate an include file. When LINT finds an
inline directive, it begins to gather input lines up
until the first line consisting of only a '#'
character. For example, in
inline sim.h
extern int junk1;
extern int junk2;
#
LINT collects the two declarations and associates them
with the name "sim.h". If a program contains the
directive,
#include <sim.h>
LINT takes the gathered text and includes it at that
point in the program, as if it had come from an
included file.
map includename1 includename2
says that all references of the form
#include includename1
should be converted to
#include includename2
null includefile
tells LINT to ignore all #include directives that
attempt to include the specified file.
search pathname
is equivalent to Include=pathname on the LINT command
line.
November, 1995 Page 33
LINT Reference Manual Thinkage Ltd.
system_search pathname
is equivalent to StandardInclude=pathname on the LINT
command line.
_I_n_s_t_a_l_l_a_t_i_o_n_ _F_i_l_e_s_:
An installation file specifies the pathnames for
software and data files used by LINT. Installation files
are text files made up of comment lines and option lines.
Comment lines:
Any line whose first non-blank character is # will be
taken as a comment. Blank lines are also considered
comments.
Option lines:
Option lines have the format
Keyword=pathname
In this documentation, keywords are written with some
letters in upper case and some in lower case. You may
abbreviate keywords by omitting any or all of the
letters shown in lower case. The remaining letters may
be entered in either upper or lower case; the
documentation simply uses upper case to show which
characters may not be omitted.
In this version of LINT, possible option lines are:
Include=pathname
gives the directory containing the LINT include files.
Library=pathname
gives the directory containing the LINT libraries.
Program=pathname
gives the directory containing the LINT executable
files (CPP, and so on).
Page 34 November, 1995