LCLint Sample - All Macros

Changes from Memory Checks 3

Differences

Fixed all messages reported in third run using memory checks.

Now running LCLint reports no anomalies.

Modules

   * employee - employee datatype (LCL, Code, Header)
   * empset - sets of employees (LCL, Code, Header)
   * dbase - database of employees (LCL, Code, Header)
   * eref - reference to an employee (LCL, Code, Header)
   * erc - collection of erefs (LCL, Code, Header)
   * ereftab - table of employees and erefs (LCL, Code, Header)

All Macros

Without the +allmacros flag, only macros corresponding to specified
iterators, functions and constants are checked. Other macros are expanded
normally. Using +allmacros, causes all macros declared with parameter lists
to be checked as macros and all other macros (except those with empty
definitions that are used for preprocessing) are checked as constants. With
+allmacros LCLint reports 6 anomalies.

Unrecognized Identifiers

LCLint generates two messages concerning unrecognized identifiers:

dbase.c: (in macro firstERC)
dbase.c:4,20: Unrecognized identifier in macro definition: mMGRS
dbase.c: (in macro lastERC)
dbase.c:5,19: Unrecognized identifier in macro definition: fNON

The macro definitions are before the enumerator definition, so mMGRS and
fNON are not yet defined. (Without macro checking, no error was reported
since they are defined where the macro is used.) We move the macro
definitions after the enumerator definitions.

Missing Declarations

LCLint reports macros that do not correspond to declarations:

employee.h:5: Macro constant employeeFormat not declared
  Macro constant has no declaration.  Use /*@constant ...@*/ to declare the
  macro.  Use -macroconstdecl to suppress message.
dbase.c:4: Macro constant firstERC not declared
dbase.c:5: Macro constant lastERC not declared
dbase.c:6: Macro constant numERCS not declared

Since there is no declaration, the type of the macro cannot be checked, and
it is allowed to match any type. For the three errors in dbase.c, we add
/*@constant ...@*/ declarations for the macros:

/*@constant static employeeKinds firstERC;@*/
# define firstERC mMGRS

/*@constant static employeeKinds lastERC;@*/
# define lastERC fNON

/*@constant static int numERCS;@*/
# define numERCS (lastERC - firstERC + 1)

We could do the same thing for employeeFormat, but then we would not get
checking for the printf arguments where employeeFormat is used. Instead, we
put /*@notfunction@*/ before the definition, so employeeFormat is expanded
normally.

