Blog

All Blog Posts  |  Next Post  |  Previous Post

Static code analysis for Delphi with TMS FixInsight v2021.10

Friday, October 8, 2021

TMS Software Delphi  Components

We are pleased to announce the immediate availability of the new TMS FixInsight version v2021.10!

Highlights of this new release are:

  • Delphi 11 support
  • Better type resolving
  • Improved & more robust code parser
  • 5 New code analysis rules added


The first three highlights are quite obvious, but let's have a deeper look at the 5 new code analysis rules that have been added and that will enable you to detect possible code issues faster.

W537 Format parameter type mismatch

The Delphi compiler is not able to check data types used in Format() function. The example below will compile, but will never work properly. FixInsight is able to catch that.

 var
 StringTypeParameter: string;

begin
  Result := Format('String type parameter value = %d', [StringTypeParameter]);
end;

W539  Interface method call passing the same interface reference as out parameter

In the example below access violation will be raised because Delphi compiler cleans up Node variable before the actual Node.GetParent() function call.

 type
   INode = interface
   ['{39EE5CA9-C4C1-46E1-B326-BAA2D004A5CD}']
   function GetParent(out Parent: INode): Boolean;
 end;

 TNode = class(TInterfacedObject, INode)
 strict private
   // INode.
   function GetParent(out Parent: INode): Boolean;
 end;

{ TNode }

function TNode.GetParent(out Parent: INode): Boolean;
begin
  Parent := TNode.Create;
  Result := True;
end;

procedure InterfaceErrorSample;
var
  Node: INode;
begin
  Node := TNode.Create;
  // Before calling Node GetParent, the compiler generates code that clears the Node variable
  // because the GetParent parameter is declared with the out parameters.
  // Thus calling Node.GetParent will result in AV.
  while Node.GetParent(Node) do
    // Getting root node.
  ;
  // Do somthing with root node.
end;


W540 String variable used twice in a call both as an output and an input parameter

In the example below Str parameter in IsStringSliceNotEmpty() function will always be an empty string if you pass the same variable twice. Because the variable will be cleaned up by Delphi compiler.

function IsStringSliceNotEmpty(const Str: string; out Slice: string; Index, Count: Integer): Boolean;
begin
  Slice := Copy(Str, Index, Count);
  Result := Slice <> '';
end;

procedure StringErrorSample;
var
  Str: string;
begin
  Str := 'qwerty';
  if IsStringSliceNotEmpty(Str, Str, 1, Length(Str)) and (Str[Length(Str)] = 'y') then
    ShowMessage(Str); // ShowMessage never run because Str was cleared before the SliceString call.
end; 


W541 Type-casting from Pointer to Integer type (or vice versa)

Type casting from Pointer to Integer and Integer to Pointer is often used in legacy code. But it is not safe on some platforms, because types size are differ. For instance, Pointer is 8 byte on x64, and the code below will lead to data loss.

procedure TypecastSample(A: Pointer);
var
  B: Integer;
begin
  B := Integer(A);
  //...
end;

W542 Direct floating-point comparison

There are several not obvious problems with comparing floating-point numbers. They are perfectly explained in DocWiki https://docwiki.embarcadero.com/RADStudio/Sydney/en/Floating-Point_Comparison_Routines

In short, you should never use equal sign to compare two floating-point numbers, but rather use special comparison routines.

var
   X:Single;
   Y:Double;

begin
  X:=0.1;
  Y:=0.1;
  if X=Y then
   Writeln('Equal')
  else
   Writeln('Not equal');
  ReadLn;
end.

The program outputs:

Not equal


Get the update & increase the quality of your code!

If you have an active license for TMS FixInsight, the update is available for you free. Users with an expired license can purchase a renewal at discount price.
If you haven't used TMS FixInsight before, download our trial version and see how it will offer tons of suggestions to improve your code.



Bruno Fierens




This blog post has not received any comments yet.



Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post