Sign in Join
Wiki copytemporary

User Changes 2.4.0

About this page

Below you can find a list of intentional changes between the the FPC 2.2.4 release and the 2.4.0 release which can change the behaviour of previously working code, along with why these changes were performed and how you can adapt your code if you are affected by them.

All systems

Usage Changes

ppc386.cfg configuration file is no longer read

Language changes

Passing ordinal constants to formal const parameters

pascal
procedure test(const a);
begin
end;

begin
  test(5);
end.

The above program used to compile, but now it does not anymore.

Treating direct-mapped properties as regular fields

pascal
{$mode objfpc}
type
  trec = record
    a, b: integer;
  end;

  tc = class
   private
    fmyfield: integer;
    frec: trec;
   public
    property myfield: integer read fmyfield write fmyfield;
    property rec: trec read frec write frec;
  end;

var
  c: tc;
begin
  c:=tc.create;
  inc(c.myfield); //1
  c.rec.a:=5; //2
  cardinal(c.myfield):=$ffffffff; //3
end.

The above code used to compile. Now the line marked with //1 will be flagged as Can't take the address of constant expressions, and the lines marked with //2 and //3 as Argument can't be assigned to.

Overloading the assignment operator with a shortstring result

pascal
type
  ts1 = string[4];
  ts2 = string[255];

operator :=(l: longint) res: ts1;
begin
  str(l:4,res);
end;

operator :=(l: longint) res: ts2;
begin
  str(l:20,res);
end;

begin
end.

The above code used to compile in previous versions. Now, the operator with ts1 as result is refused.

pascal
type
  ts1 = record
    s: string[4];
  end;
  ts2 = record
    s: string[255];
  end;

operator :=(l: longint) res: ts1;
begin
  str(l:4,res.s);
end;

operator :=(l: longint) res: ts2;
begin
  str(l:20,res.s);
end;

begin
end.

Absolute variable declarations

pascal
type
  ta = class
    p: pointer;
    procedure test;
  end;

procedure ta.test;
var
  pa: ta absolute p;
  b: pchar;
  c: char absolute b[4];
begin
end;

begin
end.

The above code used to compile, but now it is rejected.

Indexed properties and default parameters

pascal
{$mode objfpc}{$H+}

type
  { TForm1 }
  TForm1 = class
  private
    function GetFoo(Index: Integer; Ask: Boolean = True): Integer;
  public
    property Foo[Index: Integer; Ask: Boolean]: Integer read GetFoo;
  end; 

function TForm1.GetFoo(Index: Integer; Ask: Boolean): Integer;
begin
  Result := Foo[Index]; //1
end;

end.

The above code used to compile, because Foo[index] was interpreted as GetFoo(index), which caused the compiler to automatically add the default True parameter at the end. Now this code will fail.

Order of field and method/property declarations

pascal
{$mode objfpc}

type
  tc = class
    constructor create;
    a: longint;
  end;

constructor tc.create;
begin
end;

begin
end.

The above code used to compile, but now it will cause an error due to the a field appearing after the constructor.

pascal
{$mode objfpc}

type
  tc = class
    function getx(i: longint): longint;
    property prop[i: longint]: longint read getx;
    default: longint;
  end;

function tc.getx(i: longint): longint;
begin
end;

begin
end.

The above code was ambiguous to the compiler, because when it finished parsing the property, it could not decide based on seeing the default token whether this meant that the property was a default property, or whether a field coming after the property was called "default". It did find this out after it had parsed the default token (because the next token was a ":" rather than a ";"), but by then it was too late.

In general, the problem is that several valid field names can also appear as modifiers for methods or properties. So in order to prevent any ambiguities, fields are no longer allowed to appear right after method/property declarations. This is Turbo Pascal and Delphi-compatible.

pascal
{$mode objfpc}

type
  tc = class
    function getx(i: longint): longint;
    property prop[i: longint]: longint read getx;
  public // added
    default: longint;
  end;

Local type definitions in parameter lists

pascal
procedure write(var f: file of extended; e: extended);
begin
  system.write(f,e);
end;

procedure writestring(const s: string[80]);
begin
  writeln(s);
end;

function mystr: string[50];
begin
  mystr:='abc';
end;

All of the above subroutine definitions will now be rejected, because they all define new types inside their parameter lists or result type.

pascal
type
  textendedfile = file of extended;
  tstring50 = string[50];
  tstring80 = string[80];

procedure write(var f: textendedfile; e: extended);
begin
  system.write(f,e);
end;

procedure writestring(const s: tstring80);
begin
  writeln(s);
end;

function mystr: tstring50;
begin
  mystr:='abc';
end;

Implementation changes

Alignment of record variables

pascal
type
  tr = packed record
    d: double;
    b: byte;
  end;

tr used to be aligned to 1 byte in stack frames and as global variable. Now it will be aligned to the native alignment of double (4 or 8 bytes depending on the target platform, limited by the maximum global/local alignment settings). Its size will remain 9 bytes as before (because of the packed specifier).

Byte/Word/Long/Qwordbool types

pascal
var
  b: byte;
  bb: bytebool;
begin
  bb:=true;
  writeln(ord(bb));
  b:=3;
  writeln(byte(wordbool(b)));
end.

This program used to print 1 in both cases, now it prints -1 for the first statement and 3 for the second.

Encoding of single-character constants assigned to widestring

pascal
{$codepage cp866}

{$ifdef unix}
uses
  cwstring;
{$endif}

var
  w: widestring;
  a: ansistring;
begin
  w:='Б';
  s:='Б';
end.

(it is assumed that the above source file is saved using code page 866)

The "Б" character has ordinal value 129 in code page 866. Previously, at run time ord(w[1]) and ord(s[1]) would equal 129. Now, at run time w[1] will equal widechar('Б'), and s[1] will (still) equal #129.

Sets in RTTI (run-time type information)

Unit changes

OpenGL loading

pascal
uses
  gl, glext;

begin
  if not Load_GL_version_2_0 then
    begin
      writeln('OpenGL 2.0 is not supported');
      Halt;
    end;
end.

The above program used to only initialize the functions from the glext unit added in OpenGL 2.0. Now, it will also initialize the functions from OpenGL 1.2-1.5 (the gl unit already contains everything up to and including OpenGL 1.1).

dom unit: memory management for nodes

pascal
  // code like this
  MyNode.ReplaceChild(NewNode, OldNode);
  // will now have to become
  MyNode.ReplaceChild(NewNode, OldNode).Free;

The described change is backwards-compatible, because calling Free for nil objects which were returned by older versions is actually a no-op.

dom unit: memory management for node lists

Almost all old 1.0.x socket unit functions have been removed

Infozip-based unzip renamed unzip51g

All Unix-based systems

FindFirst/FindNext

Signals/exceptions in libraries

Mac OS X

Case sensitivity for unit names

Previous release notes


From the Free Pascal wiki, page "User Changes 2.4.0", as it stood on 2020-03-03 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.