Constant propagation
Available from TwinCAT 3.1.4026.14 |
Static code analysis is based on constant propagation, the results of which are used for various checks. For example, it checks whether pointers are not equal to 0 or whether array indices are outside the valid range.
They can effectively support static analysis if they know how this analysis works and where its limits lie.
See also: 'Show constant propagation values for current editor' command
Constant propagation
Static analysis attempts to determine the value of a variable based on its use.
Sample:
PROGRAM MAIN
VAR
x : INT;
bTest : BOOL;
END_VAR
x := 99;
IF x < 100 THEN
bTest := TRUE;
END_IF
In the implementation in line 1, the constant propagation sets the value 99 for the variable x
in order to use this value for further analyses. The analysis then recognizes that the expression in the subsequent IF statement is constantly TRUE.
Locally performed constant propagation
A value is only determined locally in the function block. It is irrelevant how an input is transferred. The results of function calls are also irrelevant.
Sample:
FUNCTION Func : BOOL
VAR_INPUT
bTest : BOOL;
END_VAR
IF bTest THEN
Func := OtherFunc(TRUE);
END_IF
If the parameter bTest
is set to TRUE for each call, this has no effect on the constant propagation. Even if OtherFunc(TRUE)
always returns TRUE, this has no effect on the constant propagation.
Only temporary variables have initial values
Static local variables in programs and function blocks do not have an assumed initial value. The variables retain their values from the last call and can therefore be "anything" in principle.
Local variables in functions and temporary variables have an initial value each time they are called. The constant propagation calculates with this initial value.
Sample:
PROGRAM MAIN
VAR
x : INT := 6;
bTest : BOOL;
END_VAR
VAR_TEMP
y : INT := 8;
END_VAR
bTest := x < y;
The variable y
will have the value 8 each time MAIN is executed. However, the variable x
will not necessarily. Therefore, the constant propagation will only assume a value for y
, but not for x
.
It is advisable to declare variables that are always written first and then read as temporary variables.
Constant propagation determines value ranges for numerical data types
To reduce complexity, a value range with upper and lower limits is determined for each variable.
Sample:
PROGRAM MAIN
VAR
x : INT := 6;
bTest : BOOL;
y : INT;
END_VAR
IF bTest THEN
x := 1;
ELSE
x := 100;
END_IF
IF x = 77 THEN
y := 13;
END_IF
The value range [1..100]
is determined here for the variable x
. As a result, the comparison x = 77
is not recognized as a constant expression in line 7, as 77 is within the value range.
Recurring sophisticated expressions are not recognized as the same variable
Sophisticated expressions may not have a value assigned. If such expressions occur more than once, it is helpful to introduce an auxiliary variable.
Sample:
PROGRAM MAIN
VAR
x : DINT;
py : POINTER TO INT;
y : INT;
testArray : ARRAY [0..4] OF DINT;
END_VAR
IF py <> 0 THEN
IF py^ >= 0 AND py^<= 4 THEN
x := testArray[py^];
END_IF
y := py^;
IF y <= 0 AND y <=4 THEN
x := testArray[y];
END_IF
END_IF
In line 3, an error is output for a possible access to a value via pointer, although the area to which the pointer points is checked. If the value is first copied into a local variable and its range is checked, then the constant propagation can determine the value range for this variable and allows access to the array in line 9.
Branches
For branches, individual branches are calculated separately. Value ranges from the individual ranges are then combined to form a new value range.
Sample:
IF func(TRUE) THEN
x := 1;
ELSE
x := 10;
END_IF
IF func(FALSE) THEN
y := x;
ELSE
y := 2*x;
END_IF
In line 6, x
has the range [1..10]
. After line 11, y
has the value range [1..20]
. This results from the union of the two value ranges [1..10]
and [2..20]
.
Conditions
Sample:
Conditions can restrict the value range of a variable in a code block. Several conditions can be combined. Mutually exclusive conditions can also result in an empty value range.
IF y > 0 AND y < 10 THEN
x := y;
ELSE
x:= 0;
END_IF
IF x < 0 THEN
i := 99;
END_IF
y
has the value range [1..9] in line 2. This results in the value range [0..9]
for x
in line 6. Combined with the condition x < 0
, this results in an empty set of possible values in line 9 for x
. The code is not accessible. The static analysis will report that the condition x < 0
always results in FALSE at this point.
Loops
The constant propagation will execute loops in the code until the values of the variables in the loop no longer change. It is assumed that a loop can be run through as often as required. The values determined so far are combined with the previous values. Variables that are changed within the loop have a successively growing range. The constant propagation does not assume all possible values for ranges, but only uses limits that occur in the code and also the values 0, 1, 2, 3 and 10, as these often play a role.
The easiest way to illustrate the procedure is with an example.
Sample:
PROGRAM MAIN
VAR
x : DINT;
i : DINT;
y : DINT;
END_VAR
x := 0;
y := 0;
FOR i := 0 TO 5 DO
x := x + 1;
y := i;
END_FOR
The constant propagation knows the following about the loop:
i
, x
, and y
are 0 at the beginning of the first execution of the loop. The condition i <= 5
applies to the code in the loop. The condition i > 5
applies to the code after the loop.
The constant propagation determines the following values for the variables in the loop:
| i | x | y |
|
---|---|---|---|---|
|
|
|
|
|
The following intermediate steps are carried out in detail:
Run | i | x | y |
|
---|---|---|---|---|
1 |
|
|
|
|
2 |
|
|
|
|
6 |
|
|
| First, the range |
7 |
|
|
|
|
10 |
|
|
|
|
11 |
|
|
|
|
from 11 |
|
|
| From the 11th run, the values in the loop will no longer change. The propagation is finished. |
In addition, the following applies to the code after this loop: i = 6
. The range [0..6] is determined in the loop and this is combined with the condition i > 5
, which results in the exact value 6.