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:

  1. Local variables
  2. a. Local variables of a method
  3. b. Local variables in the function block, program or function and in any basic function blocks
  4. c. Local methods of the function block
  5. Global variables
  6. a. Global variables in the project if the 'qualified_only' attribute is not set in the variable list where the global variables are declared.
  7. b. Global variables in attracted libraries when neither the library nor the variable list requires qualified access.
  8. Function block or type names
  9. a. Function block or type names from the project (i.e.: names of global variable lists, function blocks, etc.)
  10. b. Function block or type names from a library
  11. Libraries
  12. 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:

  1. Local variables
  2. a. Local variables of a method
  3. b. Local variables in the function block, program or function and in any basic function blocks
  4. c. Local methods of the function block
  5. Global variables
  6. 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.
  7. b. Global variables in attracted libraries when neither the library nor the variable list requires qualified access.
  8. Libraries
  9. a. Function block or type names from the local library (e.g. names of global variable lists, function blocks, etc.)
  10. b. Function block or type names from an attracted library
  11. 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.

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.

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: