home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-03-29 | 50.3 KB | 1,526 lines |
-
- CLINT V1.67
- ───────────
-
- The Ultimate C Source Checking Tool
-
- (c) 1992-1994 R&D Associates - All Rights Reserved
-
- ┌──────────────────────────────────────────────────────────┐
- │ │
- │ R&D Associates, 356 D. W. Highway Suite 232, │
- │ Merrimack, NH 03054, USA │
- │ │
- │ R&D Associates, 16 High Street, Rainham, │
- │ Kent ME8 7JE, ENGLAND │
- │ │
- ├──────────────────────────────────────────────────────────┤
- │ │
- │ R&D Associates can be contacted on │
- │ COMPUSERVE by mailing user ID: │
- │ │
- │ 100013,1042 (USA) │
- │ 100111,1162 (Europe) │
- │ │
- └──────────────────────────────────────────────────────────┘
-
- NEW with version 1.67! Added -Jname for include environment name, -3
- for 32 bit ints, added new warning messages, added @name indirect
- command line file support, new warning messages.
-
-
- WHAT IS CLINT?
- ──────────────
-
- CLint is a tool which reads the source files of your C programs, and
- generates reports about possible problems. As it can look at ALL the
- files in a program, it is able to report far more than any C compiler
- can. Use CLint while developing your programs, and you'll be assured
- of type safe linkage, efficient code, and excellent portability.
-
- This version of CLint is released as SHAREWARE. This means that you
- use it on a try-before-you-buy basis. If you find CLint useful, you
- must register within 30 days. We'll then send you the latest version,
- with more documentation, and you'll receive news of updates and
- technical support. R&D Associates regrets that it is unable to provide
- any support for it's shareware products without registration. Please
- read the file LICENSE.DOC for more details.
-
- CLint understands all the industry standard extensions to the ANSI
- standard such as near, far, huge, cdecl, pascal, asm, and so on for
- all the supported compilers. It understands and supports the Borland
- psuedo registers, and segment types, and the Microsoft special segment
- control extensions.
-
- A special feature of CLint is that it does not support models.
- Instead, all type modifiers are unique, that is:
-
- char * char far * char near * char huge *
-
-
- Page - 1
-
-
-
- and all variations are considered unique pointer types. The advantage
- is that regardless of the model you use for any project, if CLint
- produces no warnings, then you can safely change models with no ill
- effects. At the same time, it understands that near pointers may be
- converted to far or huge by default. For those of you that have had
- problems with mixed model programming, this feature alone will justify
- your purchase!
-
- Clint costs just US$35 in the USA or Canada, and £19 in the UK or
- Europe. Register today for an easier programming life. Please use the
- enclosed file ORDER.DOC.
-
- **** UPDATE RECORD ****
- ───────────────────────
-
- Version 1.41 added '-x' switch which releases 50K more memory to
- CLint, but makes checking fractionally slower. Great for BorlandC++
- with Windows!
-
- Versions 1.42 - 1.44, fixed some minor bugs concerning the handling of
- prototypes with the 'register' keyword, and improved detection of
- illegal initialisations.
-
- Version 1.45 fixed some previously fatal error reports when extremely
- outrageous syntax was used.
-
- Version 1.46 fixed 'UL' constant modifier error and a couple of minor
- I/O irritations.
-
- Version 1.47 fixed upper/lower case problem in library redefinition
- warning, added '_asm' and '_segname' keywords for MSC users, added
- '-wlib' and '-w-lib' switches to enable/disable warnings about library
- symbol redefinition.
-
- Version 1.50: Major Upgrade. Replaced SETUP.EXE with a menu driven
- program CSETUP.EXE which allows CLINT.CFG to be edited rather than
- replaced when options are changed, and also automatically edits
- AUTOEXEC.BAT if you allow it. Added the ability to be invoked from
- inside the Borland IDE, with reports collected and usable by the IDE.
- Added indirect files with .CLN extension, allowing convenient
- specification of collections of files for projects.
-
- Added support for the Intel iC96 compiler, and other compilers for
- micro controllers which use the syntax 'extern register' for the on-
- board I/O registers.
-
- Added support for Borland C++ 3.1 and it's massive runtime library.
-
- Added the '-u' switch to supress messages when partial programs or
- libraries are examined.
-
- Added the '-T' switch to request that Clint reccomend variables or
- functions which could be static.
-
-
-
-
- Page - 2
-
-
-
- Added the '-E' switch to use CLint as a full ANSI preprocessor.
-
- Version 1.51 - 1.52 fixed a couple of minor errors, fixed address,
- corrected non-ANSI handling of labels.
-
- Version 1.53: added support for the Intel iC86 compiler, the Microsoft
- C++ 7.0 compiler, and the Microsoft QuickC for Windows compiler. Added
- '-w-lnf' to allow bit fields longer than 16 bits. Major re-write of
- the manual to include all the new features.
-
- Version 1.54: fixed a problem when the last line of a file did not
- have a line feed.
-
- Version 1.55: fixed a problem with #else after #elif.
-
- Version 1.56: Added support for the Archimedes 68HC11 compiler, and
- the Mix PowerC compiler. Also fixed a problem with functions taking a
- pointer-to-function with no arguments. Added support for #message
- which has the syntax:
-
- #message any_string
-
- and prints the string. Very useful for debugging conditional
- compilations, but not supported by all compilers.
-
- Version 1.57: Fixed a problem with division by floating point
- constants, and constant expression evaluation.
-
- Version 1.58: Fixed a problem with long command option lines from
- *.CLN files which caused improper out of memory complaints.
-
- Version 1.59: Fixed an internal error report with sizeof("string").
-
- Version 1.61: Fixed a problem with multiple CLint libraries not being
- properly checked.
-
- Version 1.62: Added support for Microsoft Visual C, Watcom C386,
- and Symantec C++ Pro 6.0.
-
- Version 1.63: Fixed error when given 'f(int x,)'.
-
- Version 1.64: Added support for Borland C++ 4.0, made DOS Extended.
-
- Version 1.65: Fixed pipe problem.
-
- Version 1.66: Fixed initializer problem.
-
- Version 1.67: Added -Jname for include environment name, -3 for 32 bit
- ints, added new warning messages, added @name indirect command line
- file support.
-
-
-
-
-
-
-
- Page - 3
-
-
-
- INSTALLATION
- ────────────
-
- Clint shareware may be downloaded from bulletin boards as a self-
- extracting archive, or on a floppy disk from shareware vendors. If
- downloaded, you must create a directory (we suggest C:\CLINT), copy
- the downloaded file there, then execute it, then execute CSETUP to
- complete the configuration.
-
- To install from a floppy insert the supplied CLint disk in a drive (we
- assume drive A: here), then type:
-
- A:
- CSETUP
-
- CSETUP now has an easy to use menu interface. Specify the target
- directory, select the compiler you're using, and specify where your
- compiler lives. CSETUP fully supports your mouse, and has full on-line
- context sensitive help. It writes (or updates if already existing) the
- CLINT.CFG file according to your choices, renaming any existing
- CLINT.CFG file as CLINTOLD.CFG. You can use CSETUP again at any time
- to change your choices.
-
- CSETUP will automatically update your AUTOEXEC.BAT file if required.
- You may refuse CSETUP permission to change it, in which case you
- should add the line:
-
- SET CLINT=C:\CLINT
-
- or similar if you installed to a different directory, and add CLint's
- directory to your path.
-
- If you use a ram disk, CLint will run faster if you tell it to place
- its temporary files on ram disk. Assuming you have a ram disk called
- D: then add to the following line to your AUTOEXEC.BAT file:
-
- SET TMP=D: (or E: etc.)
- or
- SET TEMP=D:
-
- WARNING: Don't specify a nonexistent name here, or CLint
- won't work!
-
- If CSETUP modifies your AUTOEXEC.BAT, it will reboot the computer to
- allow the changes to take effect. If instead you manually make the
- changes, you will need to re-boot.
-
- PLEASE NOTE: If you change your version of C you will need
- to run CSETUP again when you make the change.
-
- For the Shareware version only, you must complete your installation by
- executing the batch file corresponding to your chosen compiler. This
- will construct in your CLint directory the library file required to
- check all uses of your compiler's runtime library.
-
-
-
- Page - 4
-
-
-
- CONFIGURING CLINT
- ─────────────────
-
- You can configure CLint to your personal preferences by editing the
- supplied CLINT.CFG file which looks like this (varies according to
- what you told CSETUP when CLint was installed):
-
- # (c) R&D Associates 1992.
- # CLINT.CFG
- -IC:\TC\INCLUDE # TurboC++ 1.0
- -lC:\CLINTREG\CTCPP10 # Clint Library for TurboC++ 1.0
- #
- # Add additional include directories with -I
- # Add your Clint library directory with -l
- # Add your common Clint warning switches:
- # -wxxx to enable warning xxx,
- # -w-xxx to disable warning xxx.
- #
-
- As you will see later, you can add any of CLint's options to this file
- as you see fit. The '-I' line specifies the name of the directory
- where your compiler's header files are - change this as required, or
- use CSETUP. The '-l' line specifies where you keep the library
- definitions, and the name of the definition file. If you use CSETUP to
- change your CLint configuration, it edits your CLINT.CFG file
- retaining all the information that did not need to be changed.
-
- ─────────────────────────────────────────────────────────
- NOTE: You MUST specify complete pathnames with -I and -l!
- ─────────────────────────────────────────────────────────
-
- CLint searches for CLINT.CFG in the current directory, then in the
- directory specified in the CLINT environment (SET) variable. You
- should set up the standard CLINT.CFG file to reflect your general
- needs. If a special case arises in one of your programs, simply copy
- CLINT.CFG to that directory:
-
- CD MYDIR
- COPY \CLINT\CLINT.CFG
-
- and edit it as required. No other use of CLint will be affected. CLint
- expects that each line in CLINT.CFG is a CLint option which starts
- with '-' and is followed by an option letter, and any required text.
- Any number of other lines may be present in the file and will be
- ignored. You can also comment any line by using '#' like this:
-
- -l\clint\cbcpp30 # BorlandC++ 3.0
-
- Such comments are ignored. CLint is insensitive to case in the command
- line or in CLINT.CFG except as detailed later.
-
-
-
-
-
-
-
- Page - 5
-
-
-
- USING CLINT
- ───────────
-
- In the simplest case, you will use CLint like this:
-
- CLINT *.C
-
- CLint will read all of the source files, analyse them carefully, and
- report on any possibly problems, ANSI violations, portability problems
- and so forth. It assumes that all the files specified are part of one
- program, and will be linked together, and linked with the run-time
- library routines specified in CLINT.CFG or with '-l' options on the
- command line.
-
- It checks carefully that symbols declared in one file and used in
- another have the same declaration in both files; that all functions
- defined are actually called; that all variables defined are used. If
- CLint produces no warnings or errors about such things, you can be
- assured that the program when linked is type-safe.
-
- There may be cases where you have run-time libraries supplied by other
- vendors, or written by yourself. You will need to tell CLint about
- them to obtain full checking. If you don't, CLint will complain about
- symbols which are never defined.
-
- Let's assume that you have a library called MYLIB in \MYLIB, which has
- a header MYLIB.H. The first thing to do is verify that there are no
- errors in MYLIB:
-
- CD \MYLIB
- CLINT *.C -u
-
- Fix any errors reported before proceeding! Then you do:
-
- CLINT MYLIB.H -L MYLIBDEF
-
- And finally you add the line:
-
- -l\MYLIB\MYLIBDEF
-
- to CLINT.CFG. (If you don't want to add this line, simply type the
- '-l' option when you run CLint.)
-
- The really important options you may need to use are:
-
- -Dname=value define a preprocessor macro
- -Uname undefine a preprocessor macro
- -lfile specify a CLint library file to check against
-
-
-
-
-
-
-
-
-
- Page - 6
-
-
-
- When reading header files, CLint distinguishes between header
- directories specified in CLINT.CFG, and those specified in the command
- line. The former are assumed to be your compiler or library header
- files, the latter header files which are part of the program.
-
- This is only important when '-w-shd' is used (don't warn about
- compiler headers - the default), as CLint will only be silent on minor
- problems in compiler headers - not program ones.
-
- The search order for headers which use "file.h" is:
-
- 1) Current directory,
-
- 2) Directories given in -I in the command,
-
- 3) Directories given in -I in CLINT.CFG.
-
- For headers which use <file.h> only (2) and (3) are searched.
-
- The built-in preprocessor is a full ANSI implementation. It defines
- the required preprocessor macros:
-
- __LINE__, __FILE_, __DATE__, __TIME__
-
- and also the macros
-
- __DOS__ and __CLINT__
-
- with the value '1'. If you require __STDC__ place '-D__STDC__' on the
- command line or in CLINT.CFG.
-
- Some users have encountered problems with compilers which claim to be
- ANSI, but don't have fully ANSI preprocessors. Lines like:
-
- #ifdef (sizeof(int) == sizeof(short))
-
- often in LIMITS.H are a dead giveaway. The ANSI standard specifically
- prohibits expressions like this: you can't have casts, sizeof, or
- enumeration constants in a #if expression. It is usually done by
- compilers that are trying to deduce the model you are using. Compliant
- compilers define preprocessor symbols instead.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 7
-
-
-
- USING CLINT FROM THE BORLAND IDE.
- ─────────────────────────────────
-
- You can arrange to call CLint from inside the Borland IDE for Turbo
- C++ 1.0 and upwards like this:
-
- From the main menu select Options, then Transfer, then Edit a
- blank entry entering the following information:
-
- Program Title: ~CLint current file
-
- Program Path: C:\CLINT\CLINT.EXE
-
- Command Line: $SAVE CUR $NOSWAP $CAP MSG(CLNT2MSG) -u -x -Z
- -D__TURBOC__ $EDNAME
-
- Then select Shift-F9 as the hotkey.
-
- Then from the main menu select Options, then Transfer, then Edit
- a blank entry entering the following information:
-
- Program Title: C~Lint PROJECT.CLN
-
- Program Path: C:\CLINT\CLINT.EXE
-
- Command Line: $SAVE ALL $NOSWAP $CAP MSG(CLNT2MSG) -x -Z
- _D__TURBOC__ PROJECT.CLN
-
- Then select Shift-F10 as the hotkey.
-
- If you installed CLint in a different directory, use that directory
- name instead. If you told SETUP that you're using one of the supported
- Borland compilers, the output filter CLNT2MSG.EXE is copied to the
- compiler's BIN directory. The command line options for the IDE are:
-
- $SAVE CUR: save the current file
-
- $NOSWAP: don't switch screens
-
- $CAP: capture CLint's output
-
- MSG(CLNT2MSG): pipe CLint's output through the filter
-
- -x, -u: standard CLint switches
-
- -Z: a special CLint switch for the IDE only
-
- $EDNAME: the name of the current IDE file
-
-
-
-
-
-
-
-
-
- Page - 8
-
-
-
- Unfortunately, if you have existing project files, you'll need to
- enter this information for each one.
-
- Shift-F9 runs CLint against the current file. As it uses the '-u'
- option, tests for interaction with libraries or other files in the
- project are suppressed. It is useful for rapid checks of a file whilst
- being edited.
-
- To use the second option, create a file PROJECT.CLN for your project
- containing a line for each source file in the project. You should also
- place any project specific options using '-I', '-l', '-w' etc. one per
- line as though they were being typed on the command line (see the next
- section for details). This allows you to run CLint against your entire
- project by typing Shift-F10, and when CLint finishes the IDE will
- correctly position the cursor against any errors or warnings detected.
-
- Once you've created PROJECT.CLN, it is just as useful from the DOS
- command line - just type:
-
- CLINT
-
- as the special file PROJECT.CLN is used (if it exists) when CLint is
- invoked with no file specifications. If you use MAKE, you may find it
- convenient to add a target:
-
- clint:
- clint -o report
-
- to completely check your entire project, and leave the report in
- 'REPORT'.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 9
-
-
-
- THE COMMAND LINE OPTIONS.
- ─────────────────────────
-
- CLint takes a number of source file names, possibly with wildcards,
- and analyses these sources. To control the analysis and reporting, a
- number of options may occur on the command line, or in the
- configuration file CLINT.CFG, or in files with a '.CLN' extension -
- PROJECT.CLN is special, if no files are specified and that file exists
- it is used by default.
-
- The filenames may be specified in full or in part. Filenames with no
- extension are assumed to have the extension '.C', failing which they
- are assumed to have the extension '.CLN'. The files are inspected in
- order of their occurrence on the command line. When wild card
- expansion occurs, the expanded names are ordered alphabetically.
-
- File names with no wildcards and no extension if not matching any
- files with the extension '.C' have the extension '.CLN' appended, and
- are then searched for in the current directory.
-
- Files with the extension '.CLN' are assumed to contain command line
- options and filenames, one per line. If filenames are present in the
- file, no wildcards are permitted, neither are nested '.CLN' files.
- Such files are supported to allow the convenient specification of the
- group of files comprising a project and the options they need. You may
- have any number of blank lines in the file, and you can add comments
- to any line by prefixing them with the '#' character.
-
- If you use any version of the Borland IDE from Turbo C++ 1.0 upwards,
- you should name such files PROJECT.CLN as described earlier. Such
- files are read strictly in left to right order as encountered while
- reading the command line. The effect is exactly as though each line of
- the '.CLN' file is inserted as an argument into the command line
- replacing the '.CLN' filename argument. In subsequent discussion, all
- comments regarding the precedence of command line options includes any
- options found in '.CLN' files too.
-
- All CLint options begin with a leading '-' or '/' character - in
- examples below, we use '-'. Except as described below, options are
- case insensitive unless the C standard or operating system requires
- otherwise.
-
- Options may occur in any order on the command line, intermixed with
- file names. The options are read in the order:
-
- CLINT.CFG
- and
- command line left-to-right
-
-
-
-
-
-
-
-
-
- Page - 10
-
-
-
- which can be important. Options in the command line may override
- options in CLINT.CFG or earlier options in the command line.
-
- ──────────────────────────────────────────────────────────────────────
- NOTE: CLint searches for CLINT.CFG first in the current directory, and
- then in the directory specified in your CLINT environment variable.
- CLint issues no warnings if CLINT.CFG can't be found.
- ──────────────────────────────────────────────────────────────────────
-
- Typing:
-
- CLINT /?
-
- produces a usage screen summarising the options.
- ──────────────────────────────────────────────────────────────────────
- -Ipath
- -ipath
-
- where 'path' is a directory name. Case may be important in directory
- names depending on the operating system you use. It specifies a
- directory to search for header files. There may be as many of these
- options as required. The order of search for:
-
- #include "file"
-
- is
-
- current directory,
- -I directories given on the command line,
- -I directories given in CLINT.CFG.
-
- and for:
-
- #include <file>
-
- is
-
- -I directories given on the command line,
- -I directories given in CLINT.CFG.
-
- You can force CLint to forget all the -I options in CLINT.CFG by
- giving '-I-' or '-i-' on the command line prior to any other include
- paths.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 11
-
-
-
- ──────────────────────────────────────────────────────────────────────
- -Dname
- -dname
- -Dname=value
- -dname=value
-
- These options define preprocessor macros. Although the option letter
- is case insensitive, the macro names and values are NOT. The first
- form defines a macro with default replacement text '1'. The second
- form gives the replacement text explicitly. For your convenience, you
- may append several definitions to an option with ';' like this:
-
- -Dname1;name2=4;name3=5;name4
-
- Note that the DOS command line can't handle options like:
-
- -Dname="1"
-
- properly.
-
- ──────────────────────────────────────────────────────────────────────
- -Uname
-
- This option deletes a preprocessor macro. It is not an error to
- specify a macro which was not defined. It is an error to attempt to
- undefine:
-
- '__TIME__', '__DATE__', '__FILE__', or '__LINE__'.
-
- It can be used to undefine
-
- '__CLINT__' or '__DOS__'
-
- or any symbols defined in CLINT.CFG. As with '-D' you can append
- several names with ';' like this:
-
- -Uname1;name2
-
- The order of '-D' and '-U' is important - you may only undefine macros
- whose definition precedes the '-U' option.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 12
-
-
-
- ──────────────────────────────────────────────────────────────────────
- -o file
- -O file
- -ofile
- -Ofile
-
- This option specifies a file to receive CLint's output. By default the
- output is written to 'stderr'. If you use this option, CLint still
- writes the source file name it is working on to 'stderr' to show you
- how it is proceeding. If more than one of these options occur, the
- rightmost one is used.
-
- ──────────────────────────────────────────────────────────────────────
- -e0
-
- By default CLint stops reading a file if 15 errors are produced, and
- proceeds to the next file with the message 'Too many errors'. If you
- use this option the limit is removed.
-
- ──────────────────────────────────────────────────────────────────────
- -eNNN
-
- Use this option to specify the error limit you need. The default is
- 15. If this option and '-e0' occur together, the rightmost one is
- obeyed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 13
-
-
-
- WARNINGS
- ────────
-
- ──────────────────────────────────────────────────────────────────────
- -w0
- -W0
-
- By default, CLint stops reading a file if 60 warnings are produced,
- and proceeds to the next file with the message 'Too many warnings'. If
- you use this option the limit is removed.
-
- ──────────────────────────────────────────────────────────────────────
- -wNNN
-
- Use this option to specify the warning limit you need. The default is
- 60. If this option and '-w0' occur together, the rightmost one is
- obeyed.
-
- ──────────────────────────────────────────────────────────────────────
- -wall
-
- A number of CLint's warnings are optional, and OFF by default. This
- turns all warnings on.
-
- ──────────────────────────────────────────────────────────────────────
- -w-all
-
- This turns all warnings off. It may usefully occur in CLINT.CFG when
- followed by '-wxxx' options to turn on only those warnings you need.
-
- ──────────────────────────────────────────────────────────────────────
- -wxxx
-
- Turn the specified warning on.
-
- ──────────────────────────────────────────────────────────────────────
- -w-xxx
-
- Turn the specified warning off.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 14
-
-
-
- ──────────────────────────────────────────────────────────────────────
-
- This is the complete list of warning switches. Any of them may be used
- in CLINT.CFG or on the command line. Unless changed by CLINT.CFG,
- those switches marked below with '*' are enabled by default.
-
- *wcom warn of nested comments
- webr else needs '{'
- wfbr for needs '{'
- wibr if needs '{'
- wwbr while needs '{'
- wspc advise on spacing
- wlfb warn of functions longer than 120 lines
- wlfbNNN warn of functions greater than NNN lines long
- wtyb typedefing primitive types
- *wtye warn of typedefing enums
- *wtyg warn of general (complex) typedefs
- *wtyp warn of typedefing pointer types
- *wtys warn of typedefed structs with lower case names
- wtysU typedefed structs with names not fully in upper case
- *wstv warn of passed/returned structs (by value)
- *wcon warn of constant conditions
- *whdr show warnings in user header files
- wshd show warnings in system header files
- *wprn warn of misuse of printf (sprintf, fprintf, etc)
- *wenu warn of enum misuse
- *wtri warn about trigraphs
- *winc warn of multiply included header files
- *wiag warn of auto aggregate initialisation
- *wunr warn of unreachable code
- *welb warn of empty loop bodies
- *wcil long constant needs 'L'
- *wsig warn of loss of significance with longs
- wsig+ warn of loss of significance with any type
- *wmxp warn of mixed pointers to signed/unsigned char
- *wenu warn of enum misuse
- *wnus warn of variables defined but not used
- *wpro warn of function use without a prototype
- *wret warn of return misuse
- *wlib warn of library symbol redefinition
- *wlnf warn of bit fields longer than 16 bits
- *wreg warn of register usage
- *wpua warn of possibly unintended assignments
- *wbbr warn of non-ANSI initializer bracing
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 15
-
-
-
- SPECIAL OPTIONS
- ───────────────
-
- -L file
-
- This important option instructs CLint to change it's behaviour, in
- that it knows that the source files will be headers not program text.
- Each prototype or external declaration in the source files is written
- to the 'file' in a form to be later read into CLint using the '-l'
- option. This file is needed if CLint is to check your usage of library
- functions and variables properly.
-
- Note that many errors will be reported if this option is applied to
- program source, and that the '-L' MUST be upper case. The file name
- case is only important if your operating system requires.
-
- ──────────────────────────────────────────────────────────────────────
- -lfile
-
- This option instructs CLint to read a definition file previously
- prepared with the '-L' option above after reading all the source
- files. Declarations and usage in your source files will be compared to
- those recorded in the definition file, and may result in the warning:
-
- Warning: 'name' in file(NNN) hides a library symbol in 'file'
-
- If this happens, you have defined a function or variable which is also
- defined in a library. C allows this, but in some cases it may be a bug
- in your code. You may suppress these warnings with the '-w-lib'
- option.
-
- If you don't use the '-l' option for each library you use, CLint will
- complain about a long list of functions and variables used but not
- defined (exactly as the linker would if you failed to link in the
- library at link time).
-
- The '-l' option is used differently in CLINT.CFG: you must use a
- directory name. For example, suppose that you place all the definition
- files you created with the '-L' option above in
-
- \CLINT\MYLIBS
-
- If you want CLint to check usage in ALIB in this directory, you place:
-
- -l\clint\mylibs
-
- in CLINT.CFG, and on the command line use:
-
- -lalib
-
-
-
-
-
-
-
-
- Page - 16
-
-
-
- ──────────────────────────────────────────────────────────────────────
- -E
-
- Use CLint as an ANSI C pre-processor. The output is written to
- 'stdout' and may be redirected, or the '-o' option may be used to
- write the output to any named file. If wild cards are used, each
- source file is pre-processed in turn resulting in all output appearing
- in the same file.
-
- ──────────────────────────────────────────────────────────────────────
- -u
-
- This switch informs CLint that the files given are not complete,
- either they are a library or only part of a program. In any case,
- complaints about symbols used but not defined and defined but not used
- are suppressed.
-
- ──────────────────────────────────────────────────────────────────────
- -T
-
- This switch tells Clint to detect functions and variables which are
- only used in the file in which they are declared. It then prints a
- warning about all such variables, observing that they should be
- declared 'static'.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 17
-
-
-
- CONTROL OF TYPEDEFS
- ───────────────────
-
- 'typedef' is often misused. You can control the way CLint reports
- these misuses in a number of ways:
-
- ──────────────────────────────────────────────────────────────────────
- -wtye enables reports of typedefing enums, for example:
-
- typedef enum { A, B} THING;
-
- provokes the report: "typedefed enum as 'THING'". We consider
- typedefing enums to be poor practise as discussed elsewhere, except
- for the example given below.
-
- ──────────────────────────────────────────────────────────────────────
- -wtys enables reports about typedefing structs or unions without an
- initial capital letter in the name, -wtysU enables reports about this
- without the name being all upper case. We consider that at least the
- name should start with a capital letter, preferably all upper case.
-
- ──────────────────────────────────────────────────────────────────────
- -wtyp enables reports about typedefing pointer types. We consider this
- to be one of the major abuses of typedef.
-
- ──────────────────────────────────────────────────────────────────────
- -wtyg enables reports about strange typedefs - for example typedefing
- an array. We produce this message for any typedef which is complex
- (not a primitive type, struct, union, enum, or pointer). Complex
- typedefs are in our opinion dangerous as they hide too much
- information.
-
- ──────────────────────────────────────────────────────────────────────
- -wtyb enables reports about typedefing primitive types such as 'int'
- with names that are not all lower case. There are occasions where this
- is useful, but we believe that for clarity the typedef name should
- always be lower case.
-
- CLint already knows about standard ANSI names which are typedefed, as
- follows:
-
- div_t, ldiv_t, size_t, wchar_t, clock_t, time_t,
- fpos_t, jmp_buf, va_list, tm,
-
- and will never complain about their definitions.
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 18
-
-
-
- DISCUSSION SECTIONS
- ───────────────────
-
- We believe that C programs should be understandable, maintainable,
- portable, and above all efficient. CLint was designed to assist in the
- achievement of these goals. CLint produces several reports which can
- help you write code meeting these objectives. We discuss several of
- the reports which may occur.
-
- 1. EFFICIENCY
- ─────────────
-
- ──────────────────────────────────────────────────────────────────────
- auto aggregate initialisation
-
- An 'aggregate' is any structure, union or array - i.e. a
- collection of more primitive objects. All compilers use code to
- initialise 'auto' objects. Where these objects are primitive
- types, the code is equivalent to assignment.
-
- Where the object is a 'struct', 'union', or array, the compilers
- generate a static unnamed object of the same type and initialise
- that - and then generate code to copy this hidden object to your
- object.
-
- You can save code and speed up your program by declaring the
- object 'static' which avoids the copy operation as the
- initialisation is performed once at compile time. This will only
- work if you never modify the object! If you do, then carefully
- examine the logic of your code - it is almost never necessary,
- and often confusing. A common case is:
-
- void f()
- {
- char string[] = "a string ....";
- }
-
- where if 'string' is not modified it should be static. You can
- disable this warning with -w-iag.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 19
-
-
-
- ──────────────────────────────────────────────────────────────────────
- struct/union passed by value
- struct/union value returned
-
- Both these cases cause a significant amount of code to be
- generated, and stack space usage equivalent to the size of the
- object. When you pass a structure value, the entire value is
- pushed on the stack. When you return a structure, space for the
- return value is reserved on the stack, and in normal cases copied
- from the stack to the destination, for example:
-
- struct x {
- ......
- };
-
- struct x f(void)
- {
- struct x y;
-
- ......
- return y;
- }
-
- This typical code skeleton copies the value of 'y' to the
- reserved space on the stack, and (assuming you use the result by
- assignment) copies that value to the destination! If you don't
- want these warnings, use -w-stv.
-
- ──────────────────────────────────────────────────────────────────────
- '<name>' not used
- static '<name>' not used
- '<name>' assigned to but not used
- static '<name>' assigned to but not used
- argument '<name>' not used
-
- These all indicate problems with the program logic - often they
- are a result of code changes which cause previously used
- variables to become unused. Sometimes they indicate a real bug -
- you assigned a value for a reason, but then that value is not
- used. However they arise, they should be cleared - if only to
- reduce the size of the program.
-
- In the case of "argument 'x' not used" this may be intentional -
- you can silence CLint by placing:
-
- #pragma argsused
-
- ahead of the function declaration. This clearly announces what is
- going on to any people reading the code too.
-
-
-
-
-
-
-
-
- Page - 20
-
-
-
- ──────────────────────────────────────────────────────────────────────
- label '<name>' unused
-
- Most compilers assume when they see a label that control may be
- transferred to a label by 'goto', and therefore discard the
- values of any registers they may be remembering. A label that is
- not used will usually not be detected as such, and will cause the
- same action. This can result in larger slower code being
- generated immediately following such a label.
-
- 2. CODING STYLE
- ───────────────
-
- ──────────────────────────────────────────────────────────────────────
- statement after 'for' should have '{'
- statement after 'while' should have '{'
- statement after 'do' should have '{'
- statement after 'if' should have '{'
- statement after 'else' should have '{'
-
- Any of these not followed by a keyword, as for example:
-
- if (x > 5)
- ++i;
-
- should be fully braced like this:
-
- if (x < 5) {
- ++i;
- }
-
- If you agree with us, any of these may be enabled by -wfbr,
- -wwbr, -wibr, -webr.
-
- ──────────────────────────────────────────────────────────────────────
- ' ' advised after '='
- ' ' advised after ','
- ' ' advised after ';'
- ' ' advised after ':'
-
- Some spacing styles are hard to read. We believe that all
- operators should have white space either side, but this is too
- draconian, so we object to things like:
-
- a=1,b=2;f(3,a);
-
- which will provoke 5 complaints. It should be written as:
-
- a = 1, b = 2; f(3, a);
-
- If you want this checking, enable it with -wspc.
-
-
-
-
-
-
- Page - 21
-
-
-
- ──────────────────────────────────────────────────────────────────────
- ' ' advised after '<keyword>'
-
- We believe that many people reading code use visual clues
- extensively. One of the clues often used is function calls have
- the form 'name(...)'. Some programmers have a habit of writing
- language clauses as though they were function calls, like:
-
- if(j == 0)
-
- At first glance, this is enough like a function call to at least
- arrest the eye. This is also enabled by -wspc.
-
-
- 3. USE OF TYPEDEF.
- ──────────────────
-
- ──────────────────────────────────────────────────────────────────────
- typedefed enum as '<name'>
- typedefed struct/union as '<name>' - use initial capital
- typedefed a pointer as '<name>'
- typedefed 'unsigned char' as '<name>' - use lower case
-
- We consider typedef misuse to be one of the major crimes often
- committed with C. Some extremely obscure code can occur when
- typedefs are used, and if the declaration is in a header file,
- considerable time may be needed to discover what the code really
- means - for example, given:
-
- #include "junk.h"
-
- void f()
- {
- garbage x;
-
- ........
- }
-
- what is 'x'? We propose some rules for the use of typedef to make
- it at least possible to get some hints:
-
- 1) When typedefing unions or structs, always have an initial
- capital letter in the name - or capitalise the entire name.
-
- 2) Never typedef an enumeration - use 'enum thing x' instead
- which clearly announces to the reader what is going on.
-
- 3) Never typedef pointer types - the presence of the '*' in
- the declaration is a valuable clue to understanding.
-
- 4) When typedefing a primitive type, always use a lower case
- name, the reader can then be assured that all lower case
- type names are really simple objects like 'int'.
-
-
-
-
- Page - 22
-
-
-
- These objections can be enabled if you agree with us: -wtye,
- -wtys, -wtyp, -wtyb.
-
- 4. POTENTIALLY SERIOUS BUGS
- ───────────────────────────
-
- There are many potential bugs which CLint warns about. Some of them
- can lead to extremely obscure problems. The most important are:
-
- ──────────────────────────────────────────────────────────────────────
- '<name>' possibly used before definition
-
- You will recall that 'auto' and 'register' objects which are
- not the arguments of functions have undefined values (for
- this read 'whatever was on the stack before the call'). If
- you refer to the value of such an object before a value is
- assigned to it you are guaranteed to get junk. Sometimes the
- message may be inappropriate, as in:
-
- struct x {
- struct x *next;
- ......
- } *head, *p, *q;
-
- ──> for (p = head; p; p = q) {
- q = p->next;
- }
-
- This provokes "'q' possibly used before definition" at the
- line marked with the arrow - but we can see that 'q' is in
- fact assigned before it's value is required in the 'for'.
- Almost any other occurrence of this bug is a genuine error,
- and it is worth clearing this non-error occasion by
- initialising 'q' to NULL anyway.
- ──────────────────────────────────────────────────────────────────────
- "evaluation order undefined"
-
- The standard clearly states that in a statement like:
-
- int a[10], i;
-
- a[i] = ++i;
-
- that the meaning of the statement is undefined because the
- compiler writer is free to evaluate the expression
- components in any order that is convenient - to the compiler
- writer! In cases like this, he may decide to evaluate the
- address of the array element before evaluating the right
- hand side - or he may not.
-
-
-
-
-
-
-
-
- Page - 23
-
-
-
- Similar problems arise with any operator which has a side
- effect, and CLint takes some care to check them all. It is
- also careful that when operators whose evaluation order is
- defined by the standard are used, ('||', '&&', '?', ',')
- that improper complaints don't occur.
-
- A particular trap with optimising compilers is that the
- order of evaluation of function arguments is undefined, so:
-
- f(a[i], i++);
-
- provokes this complaint too.
-
- ──────────────────────────────────────────────────────────────────────
- ambiguous operators need parentheses
-
- This occurs if any of the operators '||', '&&', '|', '&', or
- '^' are adjacent and different in an expression without
- parentheses round one of them. For example:
-
- if (flag && test1 || test2) ....
-
- is true if 'flag && test' or 'test2'. This occurred in CLint
- itself - in several places! - before we fixed it. What was
- meant was of course:
-
- if (flag && (test1 || test2)) ....
-
- This can cause no end of grief, because most people forget
- the relative precedences of these operators.
-
- ──────────────────────────────────────────────────────────────────────
- printf: ....
-
- There are a series of possible errors that can be given
- concerning the use of 'printf', 'fprintf', and 'sprintf'.
- All calls to these library functions are tested argument by
- argument against the ANSI standard for the supported
- conversions. Each '%' conversion is checked against the
- corresponding argument to be of the correct type. This can
- catch a surprising number of bugs in apparently working
- programs.
-
- You can also define functions of your own which work like
- 'printf()'. You should then use the -FNname switch to inform
- CLint of these functions so that it can check your use of
- these functions.
-
-
-
-
-
-
-
-
-
-
- Page - 24
-
-
-
- ──────────────────────────────────────────────────────────────────────
- unreachable code
-
- This may occur due to any number of logical problems. It can
- also be caused by providing a 'return x' which Borland
- compilers sometimes incorrectly insists on at the end of
- functions. In cases where you know the statement concerned
- can't be reached, precede the offending statement with:
-
- #pragma notreached
-
- which will silence CLint, but not unfortunately Borland
- compilers.
-
- ──────────────────────────────────────────────────────────────────────
- value should be returned
- both return and return of a value
-
- These are often a hold-over from pre-ANSI C code. You would
- often write:
-
- func()
- {
- .....
- }
-
- where under ANSI you should write:
-
- void func(void)
- {
- .....
- }
-
- The second case is more worthy of attention. A number of so-
- called working programs exhibit this one - it can be a nasty
- trap. Often, the program will work - under a particular
- compiler - because the value in the return register left by
- a prior expression just happened to be the value required!
- You should always fix this.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page - 25
-