|
Top Previous Next |
Targets: All
This report contains several sections that present different types of warnings. These warnings point to possible anomalies or errors in your source code. Because PAL does not require full access to all source code, some of these warnings may however turn out to be just false.
Sections:
WARN1-Interfaced identifiers that are used, but not outside of unit WARN2-Interfaced class identifiers that are public/published, but not used outside of unit WARN3-Variables that are referenced, but never set WARN4-Variables that are referenced, but possibly never set (ref/set by unknown subprograms) WARN5-Variables that are set, but never referenced
WARN6-Variables that are set, but possibly never referenced (ref/set by unknown subprograms) WARN7-Local variables that are referenced before they are set WARN8-Local variables that may be referenced by unknown subprogram before they are set WARN9-Var parameters that are used, but never set WARN10-Var parameters that are used, but possibly never set (ref/set by unknown subprograms
WARN11-Value parameters that are set WARN12-Value parameters that are possibly set (ref/set by unknown subprogram) WARN13-Interfaces passed as parameters without "const" directive WARN14-Variables with absolute directive WARN15-Constructors/destructors without calls to inherited
WARN16-Destructors without override directive WARN17-Classes with more than one destructor WARN18-Function result not set WARN20-Dangerous Exit-statements
WARN22-Dangerous Label-locations inside for-loops WARN23-Dangerous Label-locations inside repeat/while-loops WARN24-Possible bad object creation WARN25-Bad thread-local variables
WARN26-Instance created of class with abstract methods WARN27-Empty code blocks and short-circuited statements WARN29-Short-circuited for-statements WARN30-Short-circuited if/case-statements
WARN31-Short-circuited on-statements WARN32-Short-circuited repeat-statements WARN33-Short-circuited while-statements
WARN36-Forward directive in interface WARN37-Empty subprogram parameter list WARN38-Ambiguous references in with-blocks WARN39-Classes without overrides of abstract methods WARN40-Local for-loop variables read after loop
WARN41-Local for-loop variables possibly read after loop WARN42-For-loop variables not used in loop WARN43-Non-public constructors/destructors WARN44-Functions called as procedures WARN45-Mismatch property read/write specifiers
WARN46-Local variables that are set but not later used WARN48-Duplicate class types in except-block WARN49-Redeclared identifiers from System unit WARN50-Identifier with same name as keyword/directive
WARN51-Out parameter is read before set, or never set WARN52-Possible bad assignment WARN53-Mixing interface variables and objects WARN54-Set before passed as out parameter WARN55-Redeclares ancestor member, or method in helped class/record
WARN56-Parameter to FreeAndNil is not an object WARN57-Enumerated constant missing in case structure WARN58-Mixed operator precedence levels WARN59-Explicit float comparison WARN60-Condition evaluates to constant value
WARN62-Possible orphan event handler
WARN1-Interfaced identifiers that are used, but not outside of unit
This section lists all identifiers that are declared in the interface section of a unit, and that are used in the unit, but not outside the unit. You should declare these identifiers in the implementation section of the unit instead.
This section is also generated for multi-projects.
Restrictions: Interfaced identifiers that are not used at all are not listed. These identifiers are already listed in the “Identifiers never used” section in the Code Reduction Report.
Recommendation: Declare these identifiers in the implementation section of the unit, to avoid unnecessary exposure.
__________________________________________________
WARN2-Interfaced class identifiers that are public/published, but not used outside of unit
This section lists all identifiers that are members of a class, and are declared with the public/published directive, but not used outside of the unit.
This section is also generated for multi-projects.
Recommentation: Declare these identifiers with the private/protected directive instead.
__________________________________________________
WARN3-Variables that are referenced, but never set
This section lists all declared and referenced variables that never are set. Possibly this is an error, but the reason could also be that the variable is set in code that is not seen by the parser.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, and are changed whenever the other variable changes.
Recommendation: Examine why these variables are referenced, but never set. False warnings may be generated in some cases for null-terminated strings, where the actual pointer (PChar) is not set, but when the contents of the buffer pointed to is indeed changed.
__________________________________________________
WARN4-Variables that are referenced, but possibly never set (ref/set by unknown subprograms)
This section lists all variables that are declared and referenced but never set. They are referenced in unknown fashion, and the parser is unable to determine whether they are set or just referenced in these locations.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, and are changed whenever the other variable changes.
Recommendation: Examine why these variables are referenced, but never set. False warnings may be generated in some cases for null-terminated strings, where the actual pointer (PChar) is not set, but when the contents of the buffer pointed to is indeed changed.
__________________________________________________
WARN5-Variables that are set, but never referenced
This is a list of all variables that are set but never referenced. Either these variables are unnecessary or something is missing in the code, because it is meaningless to set a variable and then never reference, or use it.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, and are changed whenever the other variable changes.
Recommendation: Examine why these variables are set, but never referenced. __________________________________________________
WARN6-Variables that are set, but possibly never referenced (ref/set by unknown subprograms)
This is a list of all variables that are set but never referenced. The variables are referenced in unknown fashion, and the parser cannot determine whether they are set or just referenced in these locations. They are either unnecessary or something is missing in the code, because it is meaningless to set a variable and then never reference, or use it.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, they are changed whenever the other variable changes.
Recommendation: Examine why these variables are set, but never referenced. Also, try to make more source code available to PAL. __________________________________________________
WARN7-Local variables that are referenced before they are set
This is a list of all local variables that are referenced before they are set. Probably this is an error, because the values of these identifiers are undefined before they are set. An exception is long strings that are not examined, because they are implicitly initialized upon creation.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, they are changed whenever the other variable changes.
Recommendation: Examine why these variables are referenced before they are set.
Example:
Pascal Analyzer also examines local subprograms that are called. Consider this scenario:
Example:
This code triggers a warning, because the local variable I is first referenced by InnerProc. The call to InnerProc occurs before I is set in the main body of Proc. Even if I is only referenced when Condition evaluates to True (in InnerProc), this must happen at some occasion, otherwise that check would be pointless.
A usual situation which triggers this warning is when an non-initialized variable is passed as a parameter to a function. The function signature declares the parameter as a var-parameter. Changing the parameter to an out-parameter (if possible), avoids this warning.
__________________________________________________
WARN8-Local variables that may be referenced by unknown subprogram before they are set
This is a list of all local variables that are referenced before they are set. They are referenced in unknown fashion, and the parser cannot determine whether they are set or just referenced in these locations. Probably this is an error because the values of these identifiers are undefined before they are set. An exception is long strings that are not examined, because they are implicitly initialized to empty strings when created.
Restrictions: Variables marked with the absolute directive are not examined. These identifiers shadow another variable in memory, they are changed whenever the other variable changes.
Example:
__________________________________________________
WARN9-Var parameters that are used, but never set
This is a list of all var parameters that are used but never set in the subprogram they belong to. Although this is not an error, it may be an indication that something is wrong with your code. Otherwise, you may omit the var keyword, or change it to a const parameter.
Example:
Restrictions: Parameters to event handlers are not reported.
__________________________________________________
WARN10-Var parameters that are used, but possibly never set (ref/set by unknown subprograms
This is a list of all var parameters that are used but never set in the subprogram they belong to. They are referenced in unknown fashion, and the parser cannot determine whether they are set or just referenced in these locations. Although this is not an error, it may be an indication that something is wrong with your code. Otherwise, you may omit the var keyword, or change it to a const parameter.
Example:
Restrictions: Parameters to event handlers are not reported.
__________________________________________________
WARN11-Value parameters that are set
This is a list of all value parameters that are set in the subprogram they belong to. Although this is permitted by the compiler, it may not be what you intended. If you want to really change the variable, use the var directive instead.
Example:
__________________________________________________
WARN12-Value parameters that are possibly set (ref/set by unknown subprogram)
This is a list of all value parameters that are set in the subprogram they belong to. They are referenced in unknown fashion, and the parser cannot determine whether they are set or just referenced in these locations. Although this is permitted by the compiler, it may not be what you intended. If your intention is to really change the variable, use the var directive instead.
Example:
__________________________________________________
WARN13-Interfaces passed as parameters without "const" directive
This is a list of all parameters that are of interface type and passed without "const" directive. Omitting the "const" directive may cause problems with the reference counting for interfaces.
__________________________________________________
WARN14-Variables with absolute directive
This is a list of all variables that are declared with the absolute directive keyword. You should watch these variables carefully, since they may potentially overwrite memory.
Example:
Recommendation: Examine absolute variables carefully, and make sure that they do not overwrite memory. __________________________________________________
WARN15-Constructors/destructors without calls to inherited
This is a list of all constructors and destructors that never call their inherited constructor/destructor. This call is often required. so that the object can be correctly created or destroyed. For a class descending directly from TObject, the inherited call in the constructor is not needed, since the constructor in TObject does not actually do anything. There is no guarantee though that the constructor will be empty in future versions. If the constructor/destructor does not call inherited itself, but calls another constructor/destructor that calls inherited, there will be no warning.
Recommendation: Call the inherited constructor as the first statement in the constructor, and as the last statement in the destructor.
__________________________________________________
WARN16-Destructors without override directive
This is a list of all destructors that miss the override directive keyword. Normally this directive must be set, or a call to the Free method would never be successful. This is because Free calls the destructor.
Limitation: Not examined for Borland Pascal 7. For other targets, old-style objects are never reported, because in this case the override keyword is not allowed.
__________________________________________________
WARN17-Classes with more than one destructor
This is a list of all classes that have more than one destructor declared. To declare more than one destructor is usually pointless and should be avoided. __________________________________________________
WARN18-Function result not set
This is a list of all functions where the result value is not always set. It may be set for some but not all possible code paths. Although this is acceptable for the compiler, it implies an error in the code. Maybe the function could be implemented as a procedure instead, if the result value is not needed.
Functions that return long strings are not examined. Those strings are zero-initialized by the function.
Recommendation: Check these functions and examine if they should be implemented as procedures instead. __________________________________________________
This is a list of all subprograms (procedures and functions) that are recursive (call themselves). Recursive subprograms are difficult to implement, and should be given extra attention.
Recommendation: Check these subprograms and make sure that they cannot fall into infinite recursion. __________________________________________________
WARN20-Dangerous Exit-statements
This is a list of all locations with dangerous Exit-statements. These Exit-statements may leave a whole block of code that is never executed (dead code). Every unconditional (not within an if-statement) Exit-statement is considered dangerous in this respect. Exit-statements within except-blocks are considered as safe, however.
There are situations when a developer inserts Exit-commands just for testing purposes, for example to quit a function without executing a block of code. This report section catches those locations where the Exit-commands have not been removed.
Example:
__________________________________________________
This is a list of all locations with dangerous raise commands. These raise-commands may leave a whole block of code that is never executed (dead code). Every unconditional (not within an if-statement) raise-command is considered dangerous in this respect. Raise-commands within except-blocks are considered as safe, however.
There are situations when a developer inserts raise-commands just for testing purposes, for example to quit a function without executing a block of code. This report section catches those locations where raise-commands have not been removed.
Example:
__________________________________________________
WARN22-Dangerous Label-locations inside for-loops
This is a list of all locations with dangerous goto-labels. These labels are located inside for-loops. In the case of a for-loop, this is especially dangerous, since the loop variable will have an undefined value.
Example:
__________________________________________________
WARN23-Dangerous Label-locations inside repeat/while-loops
This is a list of all locations with dangerous goto-labels. These labels are located inside repeat/while-loops. If the loop counter is considered, this may work just fine, but these labels should be given extra attention.
Example:
__________________________________________________
WARN24-Possible bad object creation
This is a list of all locations in the code where an object possibly is created in a bad fashion.
Example:
This is an error!
Example:
PAL reports this as an error, since the reference to the new object is not assigned to a variable. It could possibly be a mistake. However, in a situation where the object is inserted into a list managed by “Parent”, it is not a mistake. This is the case for the common TTreeView control.
Limitation: Not examined for Borland Pascal 7. For other targets, old-style objects are never reported, because in this case the override keyword is not allowed.
__________________________________________________
WARN25-Bad thread-local variables
This is a list of all thread-local variables (declared with the “threadvar” keyword) with bad declarations. Reference-counted variables (such as long strings, dynamic arrays, or interfaces) are not thread-safe and should not be declared with “threadvar”. Also, do not create pointer- or procedural-type thread variables.
Limitation: Not examined for Borland Pascal 7 and Delphi 1
Example:
__________________________________________________
WARN26-Instance created of class with abstract methods This is a list of all locations where instances of classes with abstract methods are created. Such classes should serve as ancestor classes only.
Example:
__________________________________________________
WARN27-Empty code blocks and short-circuited statements
This is a list of all empty code blocks and short-circuited statements. Short-circuited statements are of these kinds:
Example:
These statements may be mistakes.
_______________________________________________
Example:
The first case-branch is empty, which may be a mistake.
__________________________________________________
WARN29-Short-circuited for-statements
Example:
__________________________________________________
WARN30-Short-circuited if/case-statements
Example:
Also short-circuited else-branches are reported, both in if- and case-statements.
__________________________________________________
WARN31-Short-circuited on-statements
Example:
__________________________________________________
WARN32-Short-circuited repeat-statements
Example:
__________________________________________________
WARN33-Short-circuited while-statements
Example:
__________________________________________________
Example:
__________________________________________________
Example:
__________________________________________________
WARN36-Forward directive in interface
Even if a forward directive is allowed by at least some versions of the Pascal/Delphi compiler, they are unnecessary and should be avoided.
________________________________________________
WARN37-Empty subprogram parameter list
Somewhat surprisingly, this code is accepted by at least some versions of the Pascal/Delphi compiler:
Example:
________________________________________________
WARN38-Ambiguous references in with-blocks
This section reports locations where a valid references to an identifier inside a with-block could be mixed up with another identifier declared in the same scope. It is not an error, but just means that you should check that the code does what you intended.
Example:
The record field referenced in the with-block could be mixed up with the global Title. Maybe the programmer instead intended to set the global Title identifier.
________________________________________________
WARN39-Classes without overrides of abstract methods
This section lists classes that do not override abstract methods in ancestor classes. If a method is declared abstract in an ancestor class, it must be overridden in descendant classes. Otherwise, calling the method for the descendant class will result in a runtime error.
________________________________________________
WARN40-Local for-loop variables read after loop
This section lists for-loop variables that are read in code after the loop. Their values are undefined, and thus it is not recommended to use their values. ________________________________________________
WARN41-Local for-loop variables possibly read after loop
This section lists for-loop variables that possibly are read in code after the loop. Their values are undefined, and thus it is not recommended to use their values. ________________________________________________
WARN42-For-loop variables not used in loop
When a for-loop variable is not used in the loop, it may be a coding error. ________________________________________________
WARN43-Non-public constructors/destructors
This section lists constructors/destructors that are non-public. ________________________________________________
WARN44-Functions called as procedures
This section lists locations in the source code where functions are called as procedures, that is without using the result value. Maybe this is a coding error, and the function should really be called as a function instead. ________________________________________________
WARN45-Mismatch property read/write specifiers
This section lists property declarations with mismatch between read/write specifiers, like
This is probably a coding error.
________________________________________________
WARN46-Local variables that are set but not later used
This section lists local variables that are set but not later used further down in the code, like
________________________________________________
This section lists locations in the source code where a line is duplicated, that is when two lines immediately following each other, have the same content.
The check is done without case-sensitivity, so ...
.. are considered to be duplicate.
But for differences within string literals, the lines below..
.. in the case-structure are considered NOT to be duplicate.
________________________________________________
WARN48-Duplicate class types in except-block
This section lists locations in the source code where an except-block contains more than one handler for the same class type. Like in this code:
________________________________________________
WARN49-Redeclared identifiers from System unit
This section lists identifiers that use the same name as an identifier from the System.pas unit for the compiler target. Although allowed, at least it is a source for confusion when maintaining the code.
________________________________________________
WARN50-Identifier with same name as keyword/directive
This section reports identifier with names that conflict with keywords/directives. Although allowed, is a source for confusion when maintaining the code, and sharing it with others.
________________________________________________
WARN51-Out parameter is read before set, or never set
This section reports parameters marked with the "out" directive that are read before set in the function/procedure, or never set. An "out" parameter is just a placeholder for a return value. The function should not assume that its initial value has any meaning.
________________________________________________
WARN52-Possible bad assignment
This section reports occurrences of assignments to smaller from bigger, possibly resulting in data loss. It will also report situations where for example UInt32 is assigned to Int32, where the range of the types do not fully overlap.
Example:
________________________________________________
WARN53-Mixing interface variables and objects
This section reports locations in your code with assignments between objects and interface variables. Normally, unless you really know what you are doing, it is a bad idea to mix interfaces and objects. The reason is that the reference counting mechanism of interfaces can be disturbed, leading to access violations and/or memory leaks.
Example:
________________________________________________
WARN54-Set before passed as out parameter
This section reports locations in your code where a variable is set and then passed as an "out" parameter to a function.
Because the "out" parameter will be set in the called function without being read first, it is at least pointless to set it before it is passed. It may also indicate some misunderstanding about the code.
It is recommended to check if it is meaningful to set the variable before passing it. If not, remove the assignment, or else modify the signature of the called function from "out" to "var".
Example:
See also our blog article about out parameters.
________________________________________________
WARN55-Redeclares ancestor member, or method in helped class/record
This section lists class fields or methods that redeclare ancestor members with the same name. This may lead to confusion about which member is actually referenced. Also reported is when a helper class/record redeclares a method that exists in the helped class/record. The helper method will take precedence.
Example of redeclared ancestor members:
________________________________________________
WARN56-Parameter to FreeAndNil is not an object
This section reports locations in your code where FreeAndNil takes a parameter which is not an object, for example an interface variable. This may lead to access violations. Unlike Free, the compiler will not complain.
Example:
Note, that starting with Delphi 10.4 it is much harder to produce this warning, because FreeAndNil only accepts parameter based on TObject. It is still however possible to produce the error, for example with code like:
FreeAndNil(TObject(IAnyInterface))
________________________________________________
WARN57-Enumerated constant missing in case structure
This section lists locations in your code where a case statement does not list all possible values of an enumerated type. This is probably most often as intended, but it may also point out an error in the code.
Example:
In the code above, cpKing is missing from the case structure, and will trigger a warning.
If you want to suppress warnings for a case-structure, just use PALOFF on the same line as the "case" keyword.
________________________________________________
WARN58-Mixed operator precedence levels
This section lists locations in your code where operators of different levels are mixed. Operators are in Object Pascal evaluated from left to right, unless parentheses are used. Operators of level 1 are evaluated before operators of level 2 etc.
Level 1: @, not Level 2: *, /, div, mod, and, shl, shr, as Level 3: +, -, or, xor Level 4: =, <>, <, >, <=, >=, in, is
Example:
Mixing operators is perfectly valid but you will find that your code is clearer and easier to understand if you insert parentheses. Then you do not have to think about operator precedence.
________________________________________________
WARN59-Explicit float comparison
This section lists locations in your code where floating point numbers are directly compared. It is considered not secure to compare floating numbers directly. Instead use functions in Delphi's System.Math unit, like IsZero and SameValue.
Example:
In the example above, use instead SameValue function from System.Math unit.
________________________________________________
WARN60-Condition evaluates to constant value
This section lists locations in your code where a condition evaluates to a constant value.
Example:
________________________________________________
This section lists locations in your code where a variable has been assigned to itself. Even if this assignment is harmless, it makes no sense. It may indicate other problems with the code, so you should check the surrounding code.
________________________________________________
WARN62-Possible orphan event handler
This section lists class procedures in your code that look like event handlers. But they are not connected to any control in the corresponding DFM-file.
This section is analyzed only if DFM files are found.
________________________________________________
This section reports locations where 32-bits (or smaller) variables are passed as 64-bits parameters (or vice versa). In many cases this is totally harmless, but consider the case where a 32-bits pointer is passed to a function that expects a 64-bits pointer. Also if there is a mismatch when assigning values, it will be reported.
See also:
|