_WARNING Warnings Report

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.

 

 

 

Interfaced identifiers that are used, but not outside of unit (WARN1)

 

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.

 

__________________________________________________

 

 

Interfaced class identifiers that are public/published, but not used outside of unit (WARN2)

 

 

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.

 

__________________________________________________

 

 

Variables that are referenced, but never set (WARN3)

 

 

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.

 

__________________________________________________

 

 

Variables that are referenced, but possibly never set (ref/set by unknown subprograms) (WARN4)

 

 

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.

 

__________________________________________________

 

 

Variables that are set, but never referenced (WARN5)

 

 

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.
 

__________________________________________________

 

 

Variables that are set, but possibly never referenced (ref/set by unknown subprograms) (WARN6)

 

 

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.
 

__________________________________________________

 

 

Local variables that are referenced before they are set (WARN7)

 

 

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:

 

clip0064

 

Pascal Analyzer also examines local subprograms that are called. Consider this scenario:

 

Example:

 

clip0065

 

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.

 

__________________________________________________

 

Local variables that may be referenced by unknown subprogram before they are set (WARN8)

 

 

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:

 

clip0066

__________________________________________________

 

Var parameters that are used, but never set (WARN9)

 

 

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:

 

clip0067

 

Restrictions:

Parameters to event handlers are not reported.

 

__________________________________________________

 

Var parameters that are used, but possibly never set (ref/set by unknown subprograms (WARN10)

 

 

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:

 

clip0071

 

Restrictions:

Parameters to event handlers are not reported.

 

__________________________________________________

 

Value parameters that are set (WARN11)

 

 

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:

 

clip0072

 

__________________________________________________

 

Value parameters that are possibly set (ref/set by unknown subprogram) (WARN12)

 

 

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:

 

clip0073

 

__________________________________________________

 

Interfaces passed as parameters without "const" directive (WARN13)

 

 

This is a list of all parameters that are of interface type and passed without "const" directive.

 

__________________________________________________

 

Variables with absolute directive (WARN14)

 

 

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:

 

clip0074

 

Recommendation:

Examine absolute variables carefully, and make sure that they do not overwrite memory.
 

__________________________________________________

 

Constructors/destructors without calls to inherited (WARN15)

 

 

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.

 

__________________________________________________

 

Destructors without override directive (WARN16)

 

 

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.

 

__________________________________________________

 

Classes with more than one destructor (WARN17)

 

 

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.
 

__________________________________________________

 

Function result not set (WARN18)

 

 

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.
 

__________________________________________________

 

Recursive subprograms (WARN19)

 

 

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.
 

__________________________________________________

 

Dangerous Exit-statements (WARN20)

 

 

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:

 

clip0075

__________________________________________________

 

Dangerous Raise (WARN21)

 

 

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:

 

clip0076

 

__________________________________________________

 

Dangerous Label-locations inside for-loops (WARN22)

 

 

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:

 

clip0077

 

__________________________________________________

 

Dangerous Label-locations inside repeat/while-loops (WARN23)

 

 

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:

 

clip0078

 

__________________________________________________

 

Possible bad object creation (WARN24)

 

 

This is a list of all locations in the code where an object possibly is created in a bad fashion.

 

Example:

 

clip0079

 

This is an error!

 

Example:

 

clip0080

 

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.

 

__________________________________________________

 

Bad thread-local variables (WARN25)

 

 

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:

 

clip0081

__________________________________________________

 

Instance created of class with abstract methods (WARN26)
 

 

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:

 

clip0082

__________________________________________________

 

Empty code blocks and short-circuited statements (WARN27)

 

 

This is a list of all empty code blocks and short-circuited statements. Short-circuited statements are of these kinds:

 

Example:

 

clip0083

 

These statements may be mistakes.

 

_______________________________________________

 

Empty case labels (WARN28)

 

 

Example:

 

clip0084

 

The first case-branch is empty, which may be a mistake.

 

__________________________________________________

 

Short-circuited for-statements (WARN29)

 

 

Example:

 

clip0085

 

__________________________________________________

 

Short-circuited if/case-statements (WARN30)

 

 

Example:

 

clip0086

 

 

Also short-circuited else-branches are reported, both in if- and case-statements.

 

__________________________________________________

 

Short-circuited on-statements (WARN31)

 

 

Example:

 

clip0087

 

__________________________________________________

 

Short-circuited repeat-statements (WARN32)

 

 

Example:

 

clip0088

 

__________________________________________________

 

Short-circuited while-statements (WARN33)

 

 

Example:

 

clip0089

 

__________________________________________________

 

Empty except-block (WARN34)

 

 

Example:

 

clip0090

 

__________________________________________________

 

Empty finally-block (WARN35)

 

 

Example:

 

clip0091

 

__________________________________________________

 

Forward directive in interface (WARN36)

 

 

Even if a forward directive is allowed by at least some versions of the Pascal/Delphi compiler, they are unnecessary and should be avoided.

 

________________________________________________

 

Empty subprogram parameter list (WARN37)

 

 

Somewhat surprisingly, this code is accepted by at least some versions of the Pascal/Delphi compiler:

 

Example:

 

clip0092

 

________________________________________________

 

Ambiguous references in with-blocks (WARN38)

 

 

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:

 

clip0093

 

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.

 

________________________________________________

 

Classes without overrides of abstract methods (WARN39)

 

 

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.

 

________________________________________________

 

Local for-loop variables read after loop (WARN40)

 

 

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.

________________________________________________

 

Local for-loop variables possibly read after loop (WARN41)

 

 

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.

________________________________________________

 

For-loop variables not used in loop (WARN42)

 

 

When a for-loop variable is not used in the loop, it may be a coding error.

________________________________________________

 

Non-public constructors/destructors (WARN43)

 

 

This section lists constructors/destructors that are non-public.

________________________________________________

 

Functions called as procedures (WARN44)

 

 

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.

________________________________________________

 

Mismatch property read/write specifiers (WARN45)

 

 

This section lists property declarations with mismatch between read/write specifiers, like

 

clip0094

 

This is probably a coding error.

 

________________________________________________

 

Local variables that are set but not later used (WARN46)

 

 

This section lists local variables that are set but not later used further down in the code, like

 

clip0096

 

________________________________________________

 

Duplicate lines (WARN47)

 

 

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.

 

clip0097

 

The check is done without case-sensitivity, so ...

 

clip0098

 

.. are considered to be duplicate.

 

But for differences within string literals, the lines below..

 

clip0099

 

.. in the case-structure are considered NOT to be duplicate.

 

________________________________________________

 

Duplicate class types in except-block (WARN48)

 

 

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:

 

clip0100

 

 

________________________________________________

 

Redeclared identifiers from System unit (WARN49)

 

 

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.

 

 

clip0101

 

________________________________________________

 

Identifier with same name as keyword/directive (WARN50)

 

 

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.

 

 

________________________________________________

 

Out parameter is read before set, or never set (WARN51)

 

 

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.

 

 

________________________________________________

 

Possible bad assignment (WARN52)

 

 

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:

 

clip0184

 

________________________________________________

 

Mixing interface variables and objects (WARN53)

 

 

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:

 

clip0192

 

________________________________________________

 

Set before passed as out parameter (WARN54)

 

 

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:

 

clip0172

 

See also our blog article about out parameters.

 

________________________________________________

 

Redeclares ancestor member (WARN55)

 

 

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.

 

Example:

 

clip0173

 

 

________________________________________________

 

Parameter to FreeAndNil is not an object (WARN56)

 

 

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:

 

clip0174

 

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))

 

________________________________________________

 

Enumerated constant missing in case structure (WARN57)

 

 

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:

 

clip0170

 

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.

 

________________________________________________

 

Mixed operator precedence levels (WARN58)

 

 

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:

 

clip0171

 

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.

 

________________________________________________

 

Explicit float comparison (WARN59)

 

 

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:

 

clip0169

 

In the example above, use instead SameValue function from System.Math unit.

 

________________________________________________

 

Condition evaluates to constant value (WARN60)

 

 

This section lists locations in your code where a condition evaluates to a constant value.

 

Example:

 

clip0206

 

________________________________________________

 

Assigned to itself (WARN61)

 

 

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.

 

 

 

________________________________________________

 

Possible orphan event handler (WARN62)

 

 

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.

 

 

________________________________________________

 

Mismatch 32/64-bits (WARN63)

 

 

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:

 

R_GEN General Reports