sonar-delphi icon indicating copy to clipboard operation
sonar-delphi copied to clipboard

Incorrect intrinsic return type for `System.Length` on dynamic arrays

Open zaneduffield opened this issue 4 months ago • 0 comments

Prerequisites

  • [X] This bug is in SonarDelphi, not SonarQube or my Delphi code.
  • [X] This bug has not already been reported.

SonarDelphi version

1.9.0

SonarQube version

No response

Issue description

In Delphi 12 the length of open array parameters was changed to be a NativeInt (from Integer). #142 made a change to reflect this, however we didn't realise that this was a fix to bring open arrays in line with dynamic arrays.

Furthermore, the actual return type of the Length intrinsic is platform dependent, and not just in the way that NativeInt is.

Here's a Delphi program that can be used to inspect the return type of Length. For good measure, I included const arrays.

program LengthIntrinsicType;

{$APPTYPE console}

uses System.TypInfo;

type
  TypeInformation = record
    class function name<T> (const value : T) : string; static;
  end;

class function TypeInformation.name<T> (const value : T) : string;
begin
  Result := GetTypeName(TypeInfo(T));
end;

procedure Test(openarr: array of byte);
const
  constarr: array[0..0] of byte = (0);
var
  dynarr: array of byte;
begin
  WriteLn('Dynamic array length type: ', TypeInformation.Name(Length(dynarr)));
  WriteLn('Open array length type: ', TypeInformation.name(Length(openarr)));
  WriteLn('Const array length type: ', TypeInformation.name(Length(constarr)));

  WriteLn('NativeInt TypeInfo: ', NativeInt(TypeInfo(NativeInt)));
  WriteLn('Int64 TypeInfo: ', NativeInt(TypeInfo(Int64)));
  WriteLn('Integer TypeInfo: ', NativeInt(TypeInfo(Integer)));
end;

begin
  Test([0]);
  readln;
end.

My findings are

Delphi Version Platform Type(Length(OpenArray)) Type(Length(DynArray)) Type(Length(ConstArray))
11 32-bit Integer Integer Integer
11 64-bit Integer NativeInt Integer
12 32-bit NativeInt NativeInt Integer
12 64-bit NativeInt NativeInt Integer

Note that on Delphi 12 NativeInt is a weak alias, so the runtime type information cannot distinguish the alias from the aliased type - this is why my test program prints the TypeInfo pointer. To make the results easier to understand, I have substituted NativeInt for some of the Delphi 12 results.

My conclusions are

  1. In Delphi 12+ open and dynamic arrays both always have a length of type NativeInt (which is a weak alias)
  2. In Delphi 11-
    1. Only dynamic arrays have a length of type NativeInt on 64-bit but Integer on 32-bit (not NativeInt strongly aliased to Integer)
    2. Open arrays always have a length of type Integer
  3. Const arrays always have a length of Integer

The current modelling doesn't match this https://github.com/integrated-application-development/sonar-delphi/blob/51412489dc8158268ae5e9d7681e92acbe2a6269/delphi-frontend/src/main/java/au/com/integradev/delphi/type/intrinsic/IntrinsicReturnType.java#L115-L125

Steps to reproduce

n/a

Minimal Delphi code exhibiting the issue

No response

zaneduffield avatar Oct 01 '24 01:10 zaneduffield