SA0160: Recursive calls

Function

Determines recursive calls of programs, actions, methods and properties. Determines possible recursions through virtual function calls and interface calls.

Reason

Recursions lead to non-deterministic behavior and are therefore a source of errors.

Importance

Medium

PLCopen rule

CP13

Sample 1:

Method FB_Sample.SampleMethod1:

METHOD SampleMethod1
VAR_INPUT
END_VAR
SampleMethod1(); (* => SA0160: Recursive call:
                              'MAIN -> FB_Sample.SampleMethod1 -> FB_Sample.SampleMethod1' *)

Method FB_Sample.SampleMethod2:

METHOD SampleMethod2 : BOOL
VAR_INPUT
END_VAR
SampleMethod2 := THIS^.SampleMethod2();(* => SA0160: Recursive call:
                                                    'MAIN -> FB_Sample.SampleMethod2 -> FB_Sample.SampleMethod2' *)

MAIN program:

PROGRAM MAIN
VAR
    fbSample : FB_Sample;
    bReturn  : BOOL;
END_VAR
fbSample.SampleMethod1();
bReturn := fbSample.SampleMethod2();

Sample 2:

Please note regarding properties:

For a property, a local input variable is implicitly created with the name of the property. The following Set function of a property thus assigns the value of the implicit local input variables to the property of an FB variable.

Function block FB_Sample:

FUNCTION_BLOCK FB_Sample
VAR
    nParameter : INT;
END_VAR

Set function of the property SampleProperty:

nParameter := SampleProperty;

 

In the following Set function, the implicit input variable of the property is assigned to itself. The assignment of a variable to itself does not constitute a recursion, so that this Set function does not generate an SA0160 error.

Set function of the property SampleProperty:

SampleProperty := SampleProperty;              // no error SA0160

 

However, access to a property using the THIS pointer is qualified. By using the THIS pointer, the instance and thus the property is accessed, rather than the implicit local input variable. This means that the shading of implicit local input variables and the property itself is lifted. In the following Set function, a new call to the property is generated, which leads to a recursion and thus to error SA0160.

Set function of the property SampleProperty:

THIS^.SampleProperty := SampleProperty;        // => SA0160