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, to prevent confusion, this should be avoided.

Negative example:

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.

Naming conventions:

To ensure that names are always unique, naming conventions should be followed, for example for specifying 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.

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 shadowing rules.

Search order in the application

When the compiler encounters a single identifier in the code of an application, it looks for the associated declaration in the following order:

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