This is a supplement to the LCLint User's Guide describing changes between Version 2.0 and Version 2.1a. These sections are also included in the LCLint User's Guide, Version 2.1a.
Sometimes it is necessary to specify function interfaces at a lower level than is possible with the standard annotations. For example, if a function defines some fields of a returned structure but does not define all the fields. The /*@special@*/ annotation is used to mark a parameter, global variable, or return value that is described using special clauses. The usual implicit definition rules do not apply to a special declaration.
Special clauses may be used to constrain the state of a parameter or return value before or after a call. One or more special clauses may appear in a function declaration, before the modifies or globals clauses. Special clauses may be listed in any order, but the same special clause should not be used more than once. Parameters used in special clauses must be annotated with /*@special@*/ in the function header. In a special clause list, result is used to refer to the return value of the function. If result appears in a special clause, the function return value must be annotated with /*@special@*/.
The following special clauses are used to describe the definition state or parameters before and after the function is called and the return value after the function returns:
/*@uses references@*/
References in the uses clause must be completely defined before the function is called. They are assumed to be defined at function entrance when the function is checked./*@sets references@*/
References in the sets clause must be allocated before the function is called. They are completely defined after the function returns. When the function is checked, they are assumed to be allocated at function entrance and an error is reported if there is a path on which they are not defined before the function returns./*@defines references@*/
References in the defines clause must not refer to unshared, allocated storage before the function is called. They are completely defined after the function returns. When the function is checked, they are assumed to be undefined at function entrance and an error is reported if there is a path on which they are not defined before the function returns./*@allocates references@*/
References in the allocates clause must not refer to unshared, allocated storage before the function is called. They are allocated but not necessarily defined after the function returns. When the function is checked, they are assumed to be undefined at function entrance and an error is reported if there is a path on which they are not allocated before the function returns./*@releases references@*/
References in the releases clause are deallocated by the function. They must correspond to storage which could be passed as an only parameter before the function is called, and are dead pointers after the function returns. When the function is checked, they are assumed to be allocated at function entrance and an error is reported if they refer to live, allocated storage at any return point.
Additional generic special clauses can be used to describe other aspects of the state of inner storage before or after a call. Generic special clauses have the form state:constraint. The state is either pre (before the function is called), or post (after the function is called). The constraint is similar to an annotation. The following constraints are supported:
Some examples of special clauses are shown in Figure 17. The defines clause for record_new indicates that the id field of the structure pointed to by the result is defined, but the name field is not. So, record_create needs to call record_setName to define the name field. Similarly, the releases clause for record_clearName indicates that no storage is associated with the name field of its parameter after the return, so no failure to deallocate storage message is produced for the call to free in record_free.Aliasing Annotations
pre:only, post:only
pre:shared, post:shared
pre:owned, post:owned
pre:dependent, post:dependent
References refer to only, shared, owned or dependent storage before (pre) or after (post) the call.Exposure Annotations
pre:observer, post:observer
pre:exposed, post:exposed
References refer to observer or exposed storage before (pre) or after (post) the call.Null State Annotations
pre:isnull, post:isnullReferences have the value NULL before (pre) or after (post) the call. Note, this is not the same name or meaning as the null annotation (which means the value may be NULL.)pre:notnull, post:notnullReferences do not have the value NULL before (pre) or after (post) the call.
The standard behavior of LCLint on encountering
#include <X.h>is to search for a file named X.h on the include search path (set using -I) and then the system base include path (usually /usr/include, default is set when LCLint is compiled). The file X.h will be included normally, unless X.h is the name of a standard library include file, X.h is found in directory that is a system directory (as set by the -systemdirs flag; the default is /usr/include), and skipansiheaders is on (it is on by default). To force all headers to be included normally, use -skipansiheaders.
Processing header files on gcc systems may require the +gnuextensions flag. This causes LCLint to support some of the gcc extensions including __asm__, __attribute__ and alternate keywords.
In LCLint 2.0, the standard library types size_t, ptr_diff and wchar_t were declared to have type long unsigned. In fact, the standard does not constrain their types other than limiting them to integral types. In LCLint 2.1a, an arbitrary integral type is used to represent these library types. The matchanyintegral, longintegral, and longunsignedanyintegral flags control type checking for the arbitrary integral type. If none of these flags is on, a type mismatch is reported anywhere an arbitrary integral type is used where a specific (possibly inconsistent) integral type is expected.
Prevent inclusion of header files in a system directory with names that match standard ANSI headers. The symbolic information in the standard library is used instead.
plain: +
Expand macros in system directories regardless of other settings, except
for macros corresponding to names defined in a load library.
plain: -
A line continuation marker (\) appears inside a comment on the
same line as the comment close. Preprocessors should handle this correctly, but it causes problems for some preprocessors.
plain: +
Report duplicate type qualifiers (e.g., long long). Duplicate type
qualifiers not supported by ANSI, but some compilers (e.g., gcc) do
support duplicate qualifiers.
plain: -
Support some GNU (gcc) language extensions.
plain: +
Stylized comment is unrecognized.
A pointer to a function is cast to (or used as) a pointer to void (or
vice versa).
plain: + A character constant may be used as an int.
plain: -
Allow long type to match an arbitrary integral type (e.g., size_t).
m: +---
Allow long unsigned type to match an arbitrary integral type (e.g.,
size_t).
plain: -
Allow any integral type to match an arbitrary integral type (e.g.,
size_t).
Only storage transferred to an unqualified global or static reference.
This may lead to a memory leak, since the new reference is not
necessarily released.
m: --++
Static storage is used as an initial value in an inconsistent way.
m: --++
Unqualified storage is used as an initial value in an inconsistent way.
systemdirexpandmacros
continuecomment
duplicatequals
gnuextensions
unrecogcomments
Type Checking
plain: +
castfcnptr
charintliteral
longintegral
longunsignedintegral
matchanyintegral
Memory Transfers
m: --++
onlyunqglobaltrans
staticinittrans
unqualifiedinittrans
University of Virginia, Computer Science
[email protected]