Weak Definial Checking
Unused Headers | Removable
from Header | Externals that can be made Static
The weak definials consist of the following:
macro definitions
typedef's
declarations
struct, union and enum definitions and members
template's
They are compile-time entities and for this reason, perhaps, they
are not used as carefully or as scrupulously as run-time objects. Their
definitions may be redundant or may lay around unused. Sometimes they are
defined inconsistently across modules. Because they are only compile-time
entities, they are referred to as 'weak'. The word 'definial' means simply
that which is defined. It has the benefit of no prior use and hence semantic
neutrality in C or C++. Where there is no possibility of confusion, we
will use the word 'definial' as an abbreviation for the term 'weak definial'.
The weak definials are important because they represent those entities
normally placed into headers to provide communication for the many modules
that comprise a program. To determine whether a header is unused or not
depends upon whether any of its weak definials have been used.
Critical to the identification of unused definials is the notion
of a library header. By default, headers included via the <filename>
syntax and headers included via the assistance of an include directory
(identified with a -idirectory option), are considered to be library
headers. Other criterion can be added and these criterion can be dropped
for the purpose of identifying library headers.
The leading idea of a library header is that the header is employed
in more than one program. For this reason, unused weak definials that appear
within library headers go unreported. Otherwise, weak definials that appear
within project headers (headers that are not library) and within modules
are reported upon if they are unused.
Unused Headers
Whether a header is used or not depends on whether any of its definials
have been used by any file other than itself or the set of files in the
same group. A group of headers is defined below. For now assume
a group contains just the file itself. For example, let the complete contents
of hdr.h be:
typedef int INT;
extern INT f();
Assume a single module includes this header but makes no use of either
f or of INT. The definial INT would be considered
used by virtue of its appearance within the declaration of f and
f would be reported unused. The header would be reported unused by
the module because the only use of any of its definials was a self reference,
a reference to INT from within the same header. If the declaration
of f were removed, then INT would be reported as unused
and hdr.h would also be reported as unused.
Consider the following example:
hdr.h:
typedef int INT;
alpha.c:
#include "hdr.h"
typedef int INT;
INT x = 0;
Is the definial INT within hdr.h being used or
not? Is the header hdr.h being used? Since we have two identical
declarations for INT it is hard to say. What we do in this case
is report that the second typedef is redundant. We then act as
if the second never appeared and so the header appears to have been used.
If the second typedef were a different type, an error would be
reported, and the first typedef would be considered unused.
A group of headers is defined by a #include at the
module level and contains the included header and all other headers directly
or indirectly included by that header. It is important to note that the
base of a group is a header directly included by a module.
Consider an example where module.c includes group.h
which, in turn, includes hdr1.h and hdr2.h. If
hdr2.h uses something out of hdr1.h this is not considered
a module use since both headers lie in the same group (consisting of
group.h, hdr1.h and hdr2.h). If module.c makes
no other reference to any item in the group you will receive a message
(766) header file not used for group.h (i.e. the base of the group.)
You will not normally receive a message about the subheaders hdr1.h
and hdr2.h not used (this is available as Elective Note 966).
Experience has shown that programmers are much more interested in
eliminating #include's at the module level. Modifying headers
themselves may be unwise owing to the variety of contexts in which headers are used.
In a similar vein, if module.c uses something from, say
hdr1.h, but nothing from group.h, group.h is nonetheless
considered used and 766 is not issued. You can learn that group.h
was not used directly by enabling Elective Note 964 but this fact is not
normally very interesting as it would require a rearrangement of header
information to exploit.
If module.c includes another header group2.h, then any reference
to an element of group.h by this new header, lying as it does
in some other group, is considered a reference by the module and serves
to suppress 766 for group.h.
Removable from Header
A special message (759) is issued for objects declared in headers
but then not referenced outside the module that defines them. (This message
is automatically suppressed if there is only one module being processed).
If a declaration is used by only one module, it can be removed from the
header thereby reducing its size. Headers have a tendency to become big
and fat; compilers are always indicating when something has to be added
but hardly ever indicate when something can be deleted; this produces uni-directional
growth. Message 759 is intended to combat this tendency.
static-able
A related message (765) is the identification of all objects that
are 'file-scopable'; i.e., external objects that may be tagged static
and hence not placed into the pool of external names. A programmer
may not at all be interested in staticizing everything because modern debuggers
sometimes depend critically on such external symbols. However you may wish
to employ the following technique:
#if debug && !defined(_lint)
#define LOCALF
#define LOCALD extern
#else
#define LOCALF static
#define LOCALD static
#endif
LOCALD stands for local Declaration.
LOCALF stands for local deFinition.
These are used as:
LOCALD double func( );
.
.
.
LOCALF double func( ) {return 37.5; }
For debugging (and provided we are not running PC-lint/FlexeLint)
the function func is external and its name is available to the
debugger. Otherwise it is made static. The macros provide good
documentation and PC-lint/FlexeLint enforces compliance.
|
|
Home | Contact | Order
PC-lint and FlexeLint are trademarks of Gimpel Software
Copyright © 2006, Gimpel Software, All rights reserved.
|
|