Shading rules
In TwinCAT it is in principle allowed to use the same identifier for different elements. For example, a function block and a variable can be named the same. However, name the function block and variable differently to avoid confusion.
Negative sample:
In the following code snippet, a local function block instance has the same name as a function:
FUNCTION Sample : INT
FUNCTION_BLOCK FB_Sample
PROGRAM MAIN
VAR
Sample : FB_Sample;
END_VAR
Sample();
In such a case it is unclear whether the instance or the function is called in the program.
Compiler behavior with shading
The compiler basically reports neither errors nor warnings when the same identifier is used for different elements. Instead, the compiler searches the code in a specific order for the declaration of the identifier. If a declaration was found, then the compiler does not search for possible further declarations elsewhere. If further declarations exist, then these are "shadowed" for the compiler. The following describes the shadowing rules, this means, the search order that the compiler uses when searching for the declaration for identifiers. In the section "Ambiguous accesses and qualified accesses", ways are shown to avoid ambiguous accesses and to circumvent the shading rules.
Avoid shading
Naming conventions:
Observe naming conventions to ensure that names are always unique, for example certain prefixes for variables. For a possible definition of such prefixes, see the Identifier/name section of TwinCAT 3 programming conventions.
Naming conventions can be checked automatically using TE1200 | PLC Static Analysis. Static code analysis could also detect duplicate use of the name Sample
by checking rule SA0027 and report it as an error.
Qualified access:
Ambiguous situations can also be avoided by consistently using the 'qualified_only' attribute for enumerations and global variable lists and by using qualified libraries.
Search order in the PLC project
When the compiler encounters a single identifier in the code of a PLC project, it searches for the associated declaration in the following order:
- Local variables
- a. Local variables of a method
- b. Local variables in the function block, program or function and in any basic function blocks
- c. Local methods of the function block
- Global variables
- a. Global variables in the project if the 'qualified_only' attribute is not set in the variable list where the global variables are declared.
- b. Global variables in attracted libraries when neither the library nor the variable list requires qualified access.
- Function block or type names
- a. Function block or type names from the project (i.e.: names of global variable lists, function blocks, etc.)
- b. Function block or type names from a library
- Libraries
- a. Namespaces of locally attracted libraries and libraries published by libraries
Search order in the library
When the compiler encounters a single identifier in the code of a library, it looks for the associated declaration in the following order:
- Local variables
- a. Local variables of a method
- b. Local variables in the function block, program or function and in any basic function blocks
- c. Local methods of the function block
- Global variables
- a. Global variables in the local library if the variable list in which the global variables are declared does not have the 'qualified_only' attribute set.
- b. Global variables in attracted libraries when neither the library nor the variable list requires qualified access.
- Libraries
- a. Function block or type names from the local library (e.g. names of global variable lists, function blocks, etc.)
- b. Function block or type names from an attracted library
- c. Namespaces of locally attracted libraries and libraries published by locally attracted libraries.
Ambiguous accesses and qualified accesses
Despite these search orders, ambiguous accesses may occur. This is the case, for example, when a variable with the same name occurs in two global variable lists that require unqualified access. Such a case is reported by the compiler as an error (for example: ambiguous use of the name <variable>).
Such an ambiguous use can be made unambiguous by a qualified access, for example by accessing it via the name of the global variable list (for example: GVL.<Variable>
).
Qualified access can also always be used to bypass shading rules.
- The name of the global variable list can be used to uniquely access a variable in this list.
- The name of a library can be used to uniquely access elements in that library.
- The pointer THIS can be used to uniquely access variables in a function block, even if a local variable with the same name exists in a method of the function block.
To find the declaration point of an identifier at any time, select the Command Go To Definition, available in the context menu of the editor window. This can be especially helpful if the compiler produces a seemingly incomprehensible error message.
Search in instance paths
The search orders described above do not apply to identifiers that appear in an instance path as a component, or to identifiers that are used as inputs in calls.
For an access of the type yy.Komponente
it depends on the entity described by yy
where to look for the declaration of Komponente
.
- If
yy
refers to a variable with structured data type (i.e. of type STRUCT or UNION), thenKomponente
is searched in that order: - Local variables of the function block
- Local variables of the basic function block
- Methods of the function block
- Methods of the basic function block
- If
yy
refers to a global variable list or a program, thenKomponente
is searched only in this list. - If
yy
refers to a namespace of a library, thenKomponente
is searched in this library in the same way as described in the above section "Search order in the library".
Only in the second instance does the compiler decide whether access to the element found is permitted, i.e. whether the variable is possibly only accessible locally, or whether a method is private. If access is not allowed, an error is issued.
See also: