P4026

Code

P4026

Message

Function call argument type does not match parameter type

This error occurs when a function call passes an argument whose type does not match the declared parameter type. IronPLC converts the argument implicitly where the conversion is lossless — between integer types, from a narrow integer to a real, from REAL to LREAL, and within the bit-string types — and reports this error for every other mismatch, such as a narrowing conversion, a real argument for an integer parameter, or a signed argument for an unsigned parameter.

For the full set of allowed implicit conversions, see Type Conversions.

A whole array, a structure, an enumeration or a function block instance is only ever its own type, and no conversion applies to it. Passing one for a parameter of any other type, including a generic category such as ANY_NUM or ANY_STRING, is this error. An array or structure is accepted for a parameter whose type has the same shape, such as an inline ARRAY[1..2] OF DINT for a parameter declared with a named array type of two DINT elements.

The arithmetic functions ADD, SUB, MUL and DIV are the exception: they accept the numeric types and the time and date types, so a mismatch in their inputs is reported as P4049 instead, as it is for the operators +, -, * and /.

Example

The following code will generate error P4026:

FUNCTION DOUBLE_REAL : REAL
VAR_INPUT
    A : REAL;
END_VAR
    DOUBLE_REAL := A + A;
END_FUNCTION

PROGRAM main
VAR
    result : REAL;
    x : DINT;
END_VAR
    result := DOUBLE_REAL(x);  (* Error: DINT argument for REAL parameter *)
END_PROGRAM

The variable x is DINT, but parameter A expects REAL. A 32-bit integer does not fit exactly in REAL’s 23-bit mantissa, so the conversion is not implicit. An INT argument in the same position is accepted, because every 16-bit integer is exactly representable in REAL.

To fix this error, use an explicit type conversion:

result := DOUBLE_REAL(DINT_TO_REAL(x));

Widening to LREAL is the other way out: every integer type converts implicitly to LREAL, so a parameter declared LREAL accepts x as written.

Passing a whole array where a single value is expected is the same error:

PROGRAM main
VAR
    names : ARRAY[1..2] OF STRING[8];
    n : DINT;
END_VAR
    n := LEN(names);  (* Error: ARRAY[1..2] OF STRING[8] for an ANY_STRING parameter *)
END_PROGRAM

To fix this error, pass one element of the array:

n := LEN(names[1]);

Think IronPLC is wrong about this?

If you believe this diagnostic is incorrect, open an issue on GitHub with a small sample that demonstrates the problem.