RADE |
C++ Source Checker |
mkCheckSource FiltersTesting source code in the CAA V5 environment |
Technical Article |
AbstractSome errors reported by CSC may not be valid, for several reasons. Then error filtering can be useful. |
There are several causes which can lead to invalid errors generated by CSC:
The presence of invalid errors in CSC report have some negative consequences :
Generation of invalid errors by CSC leads to a certain confusion for the developer between the "real" errors, which are mandatory to correct, and the invalid ones, which should be ignored.
Then, using the filter mechanism for invalid errors, after a manual code review, can help to improve efficiency of CSC tool.
[Top]
UINC (see [5]) is the only kind of error which does not support for the moment the filter mechanism. All the other kinds of error supports the filtering mechanism, even if some are supposed to be always valid. Then, any error reported by CSC tool, excepted UINC one, can be filtered.
[Top]
Filtering CSC errors consists in tagging the source files containing the errors. It is made up of two parts: the filter tags point out the errors to filter, and a source-level certification tag activates the filters.
If the key contained in the certification tag (referred from now as "the certification key") is valid (i.e. has the expected value), the errors tagged in the source will not be reported by CSC.
A filter consists in the tag @CSC-Filter
and its parameter
<error-type>, which is the type of CSC error(s) it will filter. The type
must be one of those listed in section "Supported
types of error".
Example - Filter tag:
The following tag is a filter for a LCVMNAAR error:
@CSC-Filter LCVMNAAR |
The following LCVMNAAR error:
// Some comments if (_attribute) _attribute->Release(); // LCVMNAAR error is generated .... |
can be filter for example in this way:
if (_attribute) // Some comments // @CSC-Filter LCVMNAAR - filter for the invalid LCVMNAAR error generated below: // Another comment _attribute->Release(); // instruction/declaration which generates an error ... |
or in this other way:
... // Some comments /** LCVMNAAR error to filter @CSC-Filter LCVMNAAR - filter for the invalid LCVMNAAR error generated below: */ if (_attribute) _attribute->Release(); // instruction/declaration which generates an error ... |
-- End of Example
Actually, to filter an error, a tag of this type must be put on a line before the line containing the error and after the line of code preceeding the beginning of the inner declaration or instruction containing the entity which causes the error (the next section -- "Where to place the filter" -- specifies for each error type which is the entity to filter). But it will be easier to apply the following rule, more restrictive but less confusing:
Rule: A filter tag @CSC-Filter <error-type>
will
filter all the errors of <error-type> (if there is) generated by the line
of code following this filter.
This means that there must be one filter before each line containing at least one error of the same type to filter. If there are several errors of the same type on one line, they will all be filtered by one single filter tag (of the same type). On the other hand, if there are, on one single code line, several errors of several types to filter, one filter must be set for each error type generated on the line.
Be careful: there must be no code in the same line as a filter tag.
Exception: Filtering LCDMNI and LCDMMN errors (Pointer Null Part 1 errors [1]) obeys particular rules. All LCDMNI (resp. LCDMMN) errors reported for the same constructor method (resp. destructor method) will be filtered by a single filter, which must be put just before the declaration of this constructor (resp. destructor).
A certification tag is needed in each source file containing CSC filters, in order to activate these filters. This certification tag ensures that the errors have been reviewed and are not valid.
A certification tag consists in the tag @CSC-FilterKey
and the
value of the certification key as parameter. The certification key is an
unsigned integer computed from the source file name and from the count of
filters of each type existing in this source. All these parameters are
case-sensitive. It is recommended to insert this tag near the top of the file.
Example - Certification tag:
The certification tag for a file named myFilter.cpp, and which
contains one filter for a LCVMNAAR error is:
@CSC-FilterKey 1925307082 |
-- End of Example
Then, a key which is valid for a certain file will not be valid for another file, even if the filters are the same.
Moving a file, moving the filters in the file, changing the code or making invalid errors disappear (as long as the corresponding filters remain in the source) does not invalidate the current key. On the other hand, renaming the file, adding or deleting filters requires to compute the new key value, the old one being no more valid for the source file modified in this way.
See step 2 in Step-by-step process section to find out how to generate a certification key.
The syntax of the comments is flexible, within a certain limit: tags can be
included in C or C++ comment blocks ; occurrences of other comments before or
after this block are allowed...
But it is needed that the tag name (@CSC-Filter
or @CSC-FilterKey
)
is separated from their parameter (key, error name) only by "separator
characters" (space, tabulation, new-line and secondarily '*'
for C++ comments). Furthermore, the name and the value of the tag are
case-sensitive.
Here is presented, for each type of error, the code entity which must be tagged to filter the error. The corresponding line is usually reported in the error message.
delete
operator
indicated in error message.if
instruction reported as erroneous.open
method.strcpy
function.delete
operator.Example - LCLVNI:
Pointers to array are badly analyzed for the moment by CSC tool, so it
can lead to invalid errors. Here such a case:
//... int i, size, *pos = NULL, newpos, newsize, (*newref)[2], *((*newid)[2]); // ... |
Thus one can filter the errors generated by the declaration of newref
and newid
pointers, as shown here:
//... // @CSC-Filter LCLVNI int i, size, *pos = NULL, newpos, newsize, (*newref)[2], *((*newid)[2]); // ... |
-- End of Example
Example - LCDMNI:
As conditional preprocessing directives are not taken into account,
CSC tool analyzed the following code :
CATSupport::CATSupport (const int width, const int height, const void *display) : /*...*/ _StartTimer(0), #if defined (_AIX) _UseTimer(0) #elif defined(_WINDOWS_SOURCE) _shaderCompileAction(NULL), _shaderDrawAction(NULL), _UseTimer(0) #else _Wp1(NULL), _Wp2(NULL), _UseTimer(0) #endif { //... |
CATSupport::CATSupport (const int width, const int height, const void *display) : /*...*/ _StartTimer(0), _UseTimer(0) _shaderCompileAction(NULL), _shaderDrawAction(NULL), _UseTimer(0) _Wp1(NULL), _Wp2(NULL), _UseTimer(0) |
in which commas are missing between _UserTimer and _shaderCompileAction initializations, and between those of _UseTimer and _Wp1. So the tool does not see _shaderCompileAction and _Wp1 initializations and generates two LCDMNI error. The filter put as follows will prevents the two errors to be reported:
// @CSC-Filter LCDMNI CATSupport::CATSupport (const int width, const int height, const void *display) // No change in the rest of method // ... |
-- End of Example
Example - LCVMNAR:
Here a particular case where a pointer must not be assigned after
being released:
if (CharacCollector && (! CharacCollector->Release())) delete CharacCollector; |
And here a way to filter the error:
/******* @CSC-Filter LCLVMNAR ******/ if (CharacCollector && (! CharacCollector->Release())) delete CharacCollector; |
-- End of Example
Example - PNSS:
Let's assume that CATISpecObject::AddAttribute returns an AddRef'ed
pointer. The chained calls are not yet supported by CSC, a PNSS error is
generated by code below:
CATISpecObject* pIStartupImage = NULL; // Next line generates an error. pIStartupImage->AddAttribute("DisplayList", tk_list(tk_component), sp_IN)->Release(); |
A filter can be set temporarily:
CATISpecObject* pIStartupImage = NULL; /* CSC bug. Waiting for correction... * @CSC-Filter PNSS */ pIStartupImage->AddAttribute("DisplayList", tk_list(tk_component), sp_IN)->Release(); |
-- End of Example
Example - BCBA:
Here is a piece of code generating 2 BCBA errors, due to invalid
calls to AddAnalyseNotification method:
switch(TypeOfView){ case TheViewInheritance : AddAnalyseNotificationCB(this, GetMenuIActivateNotification(), (CATCommandMethod)&CATBSpecPushView::ViewInheritance, NULL); break; case TheViewZoom : AddAnalyseNotificationCB(this, GetMenuIActivateNotification(), (CATCommandMethod)&CATBSpecPushView::ViewZoom, NULL); break; default; } |
And here the code in which the errors are filtered:
switch(TypeOfView){ //@CSC-Filter BCBA case TheViewInheritance : AddAnalyseNotificationCB(this, GetMenuIActivateNotification(), (CATCommandMethod)&CATBSpecPushView::ViewInheritance, NULL); break; case TheViewZoom : //@CSC-Filter BCBA - Be careful, filter can not be in the same line as "case TheViewZoom" AddAnalyseNotificationCB(this, GetMenuIActivateNotification(), (CATCommandMethod)&CATBSpecPushView::ViewZoom, NULL); break; default; } |
-- End of Example
Example - EXCP:
Let's assume that the global function CATBindInterface_B can throw
an exception. The following code generates a EXCP error:
//... SEQUENCE(octet) name = ...; CATIBindParameters* parameters = ...; CATILinkableObject* pointed = NULL; pointed = CATBindInterface_B(name, CATILinkableObject::ClassName(), parameters); //... |
And here the corresponding filter:
//... SEQUENCE(octet) name = ...; CATIBindParameters* parameters = ...; CATILinkableObject* pointed = NULL; // @CSC-Filter EXCP - EXCP error to filter, exception case. pointed = CATBindInterface_B(name, CATILinkableObject::ClassName(), parameters); //... |
-- End of Example
delete
operator indicated in error message.
These errors are supposed to be valid. Nevertheless, here is the manner
to filter them.
Example - BDON:
The following code generates a BDON error:
TestClass* ptr = new ClassTest[12]; delete ptr; |
And here the error is filtered:
TestClass* ptr = new ClassTest[12]; // @CSC-Filter BDON delete ptr; |
-- End of Example
if
instruction reported as erroneous.
Example - SCIS:
The following code generated a SCIS error:
if (_attribute && _attribute->use()); |
In the code below, the error is filtered:
// ------ @CSC-Filter BVSS ------ // if (_attribute && _attribute->use()); |
-- End of Example
open
method. These errors are
supposed to be valid. Nevertheless, if, here manner of filtering them.
Example - IOS2:
Here a code generating an IOS2 error:
ofstream dumpFile ; // File's opening dumpFile.open(filePathString.CastToCharPtr(), ios::in); |
and here the corresponding code with filter:
ofstream dumpFile ; // @CSC-Filter IOS2 // File's opening dumpFile.open(filePathString.CastToCharPtr(), ios::in); |
-- End of Example
strcpy
function. These errors are
supposed to be valid. Nevertheless, here is the manner of filtering
them.
Example - BVSS:
Here a piece of code where a BVSS error is generated:
char hello [3]; strcpy(hello, "hello"); |
And here the same where error is filtered:
char hello [3]; // Filter for the following error : @CSC-Filter BVSS strcpy(hello, "hello"); |
-- End of Example
delete
operator.
Example - UADC:
In this example, deleting the CATGraphicPrimitive is authorized, as
the code comes from the graphic primitive modeler.
CAT2DLineGP::~CAT2DLineGP(){ //... if (_nbText){ !_text; CAT2DGeometricTextGP *gp = NULL; while (gp=++_text) delete gp; } // ... |
Here the code with filtering:
CAT2DLineGP::~CAT2DLineGP(){ //... if (_nbText){ !_text; CAT2DGeometricTextGP *gp = NULL; // @CSC-Filter UADC while (gp=++_text) delete gp; } // ... |
-- End of Example
Example - UACS:
Here is an example where ClassName mechanism is use instead of ClassId
one.
if (hCurr != NULL_var && (pFilter = hCurr->QueryInterface(CATISketch::ClassName())) != NULL){ // ... |
If the context made it necessary, the filtering would be:
// @CSC-Filter UACS if (hCurr != NULL_var && // The filter could have also been inserted here (pFilter = // or here hCurr->QueryInterface(CATISketch::ClassName())) != NULL){ // ... |
-- End of Example
[Top]
Check that the error is really an invalid one.
Particularly, one must check that the error is not caused by the inaccuracy of the settings file used during the CSC run (a macro not expanded, a method falsely declared as returning an AddRef'ed pointer ...). In this case, the settings file should be updated (see [7]).
The certification key is computed from the source file name, and the number of filters for each error type. Be careful: all these parameters are case sensitive.
If the source file does not still contain a certification key, use CSCCreateCertificationKey command.
CSCCreateCertificationKey [-h] [-s <source>] (-filter <error > <number>)* [-out <file>]
-h |
displays help. |
-s source |
name of source file, including extension. |
-filter error number |
for each type of error to filter, the name of the error and the number of filters for this error type one wants to insert in the file. |
-out file |
to keep a trace of the command result. If file does not exist, it will be created. file will contained more or less the same output as the one obtained on the standard output. |
Example 1 - CSCCreateCertificationKey:
This command creates a key for myFile.cpp, in which there is one LCVMNAAR
errror to filter:
> CSCCreateCertificationKey -s myFile.cpp -filter LCVMNAAR 1 Errors of type LCVMNAAR: 1 to filter. # CKEY-RESULT: certification key for aFile.cpp is: ####### 1925307082 |
The key generated for aFile.cpp is 1925307082.
-- End of Example
Example 2 - CSCCreateCertificationKey:
The following command creates a key for a file named aFile.cpp, in which one
wants to insert 1 filter for AWRS errors and 2 filters for LCVMNA errors, with
an output file generated:
> CSCCreateCertificationKey -s aFile.cpp -filter AWRS 1 -filter LCVMNA 2 -out ../myOutFile.txt Errors of type AWRS: 1 to filter. Errors of type LCVMNA: 2 to filter. # CKEY-RESULT: certification key for aFile.cpp is: ####### 1843354957 |
The key generated for aFile.cpp is 1843354957.
-- End of Example
Otherwise, you can either use CSCCreateCertificationKey command, as explained above, or the CSCChangeCertificationKey command. This command enables to specify only the additions and removals for each type of filters and not the total count.
CSCChangeCertificationKey [-h] [-s <source_path>] (-update <error type> <[+,-]n>)* [-out <file>]
-h |
displays help. |
-s source_path |
path of a source file. |
-update <error type> <[+,-]n> |
for each type of error to filter, the name of the error and the number of filters of error type one wants to add or withdraw in the file. |
-out file |
to keep a trace of command result. If file does not exist, it will be created. file will contained more or less the same output as the one obtained on the standard output. |
Example 1 - CSCChangeCertificationKey:
One wants to add 1 AWRS filter and remove 1 LCVMNA filter in previous
aFile.cpp
> CSCChangeCertificationKey -s ./aFile.cpp -update LCVMNA -1 -update AWRS +1 #### Previous : # CCKEY-RESULT: Key found in file ./aFile.cpp is <1843354957> ## Error filter of source ./aFile.cpp Certification key: 1843354957 ErrorFilters in source: - AWRS : 1 error(s) to filter. - LCVMNA : 2 error(s) to filter. ## # CCKEY-RESULT: Key found in file ./aFile.cpp is valid. #### Computation of new error filter counts Update : AWRS : +1 LCVMNA : -1 #### New : AWRS : 2 filter(s). LCVMNA : 1 filter(s). # CCKEY-RESULT: new certification key for ./aFile.cpp is: ####### 1591679794 |
The new key generated for aFile.cpp is 1591679794.
-- End of Example
Let take myFile.cpp file, which contains the following invalid error to filter:
/** * 11/11/2002: Creation */ #include "CATBaseUnknown.h" void myClass::myMethod(){ if (_attribute) // A comment // Another comment _attribute->Release(); // instruction where error is generated ... } ... |
First, the filtering tag @CSC-Filter LCVMNAAR
must be inserted
at the correct location. Section Where to set
the filter specifies that the code entity to tag is the call to Release
method. Then, the file becomes:
/** * 11/11/2002: Creation * 12/12/2002: Filtering invalid LCLVMNAAR error in myMethod */ #include "CATBaseUnknown.h" void myClass::myMethod(){ if (_attribute) // A comment // @CSC-Filter LCVMNAAR - filter for the invalid LCVMNAAR error generated below: // Another comment _attribute->Release(); // instruction where error is generated ... } ... |
Then, the certification key must be added. Running the CSCCreateCertificationKey command (see 2nd step, Example 1 - CSCCreateCertificationKey) gives the key value 1925307082. The tag @CSC-FilterKey can be set anywhere, but it is recommended to set it at the beginning of the source file.
Here the new version of myFile.cpp, where the invalid LCVMNAAR error is no more reported by CSC:
/** * 11/11/2002: Creation * 12/12/2002: Filtering invalid LCLVMNAAR error in myMethod */ // @CSC-FilterKey 1925307082 - Certification key for CSC tool. #include "CATBaseUnknown.h" void myClass::myMethod(){ if (_attribute) // A comment // @CSC-Filter LCVMNAAR - filter for the invalid LCVMNAAR error generated below: // Another comment _attribute->Release(); // instruction where error is generated ... } ... |
Run of command mkCheckSource on the source file must generate the following
message in standard output:
#CSC-INFO: Valid certification key in file <file path>
#CSC-INFO --> Tagged errors will be filtered.
and filtered errors should no more be reported by the tool.
If invalid errors appear, referring to the output message must help. Defective filtering can be due to
#CSC-WARNING: Certification key is of unexpected form
.#CSC-Warning: Certification key is not valid.
@CSC-Filter
tag and run again the command. Be careful: all these arguments are case
sensitive. Check the syntax of the filter tags (see section Syntax).#CSC-INFO: Valid certification key in file
, but
filtered errors still appear.CSC-FilterKey
tag (See section
Syntax).Use of option -noCheckFiltering of mkCheckSource command can help in some cases (see next part).
[Top]
-ignoreFiltering |
all filters are ignored: all errors, even filtered ones, are reported. |
-noCheckFiltering |
all filters are activated, key values are not checked. |
Example:
Here the file myFile.cpp:
// @CSC-FilterKey 11111111 -- Invalid Key #include "CATBaseUnknown.h" void myClass::myMethod() if (_attribute) // A comment // @CSC-Filter LCVMNAAR - filter for the invalid LCVMNAAR error generated below: // Another comment _attribute->Release(); // instruction/declaration where error is generated ... |
Running CSC with default filtering option will generate the following output:
> mkCheckSource -s myFile.cpp # CSC-INFO: 1 source file to process # CSC-WARNING: Certification key in file myFile.cpp is not valid. # CSC-WARNING: found key is <11111111> # CSC-WARNING: --> All filter tags in the source are disabled. LCVMNAAR : Variable [_attribute] not set to NULL (or to a valid data) after Release at line 9 in file myFile.cpp # CSC-INFO: Found 1 Error and Warning |
Running CSC using option -ignoreFiltering will generate the following output:
> mkCheckSource -s myFile.cpp -ignoreFiltering # CSC-INFO: Error filters are ignored in all source files. # CSC-INFO: 1 source file to process LCVMNAAR : Variable [_attribute] not set to NULL (or to a valid data) after Release at line 9 in file myFile.cpp # CSC-INFO: Found 1 Error and Warning |
Running CSC using option -noCheckFiltering will generate the following output:
> mkCheckSource -s myFile.cpp -noCheckFiltering # CSC-INFO: Validity of certification keys is not checked. # CSC-INFO: --> Tagged errors will be filtered. # CSC-INFO: 1 source files to process # CSC-INFO: Found 0 Error and Warning |
[Top]
For different reasons, invalid errors can be generated by CSC tool. A filter mechanism is then provided. It consists in inserting in each source file: filter tags before invalid errors and a certification key to activates the filtering mechanism.
[Top]
[1] | Null Pointers Part 1 Checks |
[2] | AddRef Release Checks |
[3] | Callbacks Checks |
[4] | Exception Checks |
[5] | C++ Checks |
[6] | Forbidden constructions Checks |
[7] | Setting Files |
Version: 1 [Dec 2002] | Document created |
[Top] |
Copyright © 2002, Dassault Systèmes. All rights reserved.