Difference between revisions of "User Changes Trunk"

From Lazarus wiki
Jump to navigationJump to search
m (Fix typos)
 
(444 intermediate revisions by 31 users not shown)
Line 1: Line 1:
 
== About this page==
 
== About this page==
  
Below you can find a list of intentional changes since the [[User_Changes_2.2.4|the previous release]] not yet scheduled for inclusion in a next fixes release that 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.
+
Listed below are intentional changes made to the FPC compiler (trunk) since the [[User_Changes_3.2.2|previous release]] that may break existing code. The list includes reasons why these changes have been implemented, and suggestions for how you might adapt your code if you find that previously working code has been adversely affected by these recent changes.  
  
== All systems ==
+
The list of new features that do not break existing code can be found [[FPC_New_Features_Trunk|here]].
  
=== Alignment of record variables ===
+
Please add revision numbers to the entries from now on. This facilitates moving merged items to the user changes of a release.
  
* '''Old behaviour''': Variables of record types (not just their fields, but the records as a whole when declared as independent variables) would be aligned at most to the maximum alignment of their fields, limited by the maximum field alignment set for the target. This same limit was used to determine padding of the record size.
+
== All systems ==
* '''New behaviour''': Variables of record types are now always aligned inside stack frames or as global variables in a way which provides optimal alignment for their embedded fields, regardless of the used packrecords setting. Moreover, unpacked records are also padded up to a size which is a multiple of this alignment (to also provide optimal alignment inside arrays of such records). The alignment of record fields inside other records obviously only depends on the packing settings of the "parent" record.
 
* '''Example''':
 
<delphi>
 
type
 
  tr = packed record
 
    d: double;
 
    b: byte;
 
  end;
 
</delphi>
 
''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).
 
* '''Reason''': Performance.
 
* '''Effect''': The size of some non-packed records may change compared to previous versions. Other than that, the different alignment rules cannot impact your code unless you are making unsupported assumptions (like taking the address of a local variable, adding some value to it, and expecting that you are now pointing at the next local variable).
 
* '''Remedy''': If you depend on the layout and/or size of a record staying the same, always declare it as packed. Non-packed records are free to be changed by the compiler in any way that it sees fit (except for changing the types or order of the fields).
 
  
=== Byte/Word/Long/Qwordbool types ===
+
=== Language Changes ===
  
* '''Old behaviour''': Assigning "true" to variables of these types resulted in these variables getting the value "1". Typecasting ordinal values to Byte/Word/Long/Qwordbool also mapped these values onto [0,1] if the source and destination type were of different sizes.
+
==== Precedence of the IS operator changed ====
* '''New behaviour''': Assigning true to such variables now sets them to "-1" (i.e., all 1 bits). Typecasting an ordinal value to such a type now leaves that ordinal value untouched.
+
* '''Old behaviour''': The IS operator had the same precedence as the multiplication, division etc. operators.
* '''Example''':
+
* '''New behaviour''': The IS operator has the same precedence as the comparison operators.
<delphi>
+
* '''Reason''': Bug, see [https://bugs.freepascal.org/view.php?id=35909].
var
+
* '''Remedy''': Add parenthesis where needed.
  b: byte;
 
  bb: bytebool;
 
begin
 
  bb:=true;
 
  writeln(ord(bb));
 
  b:=3;
 
  writeln(byte(wordbool(b)));
 
end.
 
</delphi>
 
This program used to print 1 in both cases, now it prints -1 for the first statement and 3 for the second.
 
* '''Reason''': Delphi-compatibility, compatibility with WinAPI functions. See http://bugs.freepascal.org/view.php?id=10233 for more information.
 
* '''Effect''': Code assuming that assigning true to a Byte/Word/Long/Qwordbool variable or parameter results in assigning the ordinal value "1" no longer works. This may affect e.g. translations of C headers where certain int parameters which function basically as boolean parameters were replaced with longbool.
 
* '''Remedy''': If you depend on the the ordinal value of a particular variable being 1, either use an expression such as longbool(1) (which can also be used in the declaration of a constant), or use a regular ordinal type rather than one of the *bool types.
 
  
=== Passing ordinal constants to formal const parameters ===
+
==== Visibilities of members of generic specializations ====
 +
* '''Old behaviour''': When a generic is specialized then visibility checks are handled as if the generic was declared in the current unit.
 +
* '''New behaviour''': When a generic is specialized then visibility checks are handled according to where the generic is declared.
 +
* '''Reason''': Delphi-compatibility, but also a bug in how visibilities are supposed to work.
 +
* '''Remedy''': Rework your code to adhere to the new restrictions.
  
* '''Old behaviour''': Ordinal constants could be passed directly to formal parameters.
+
=== Implementation Changes ===
* '''New behaviour''': Passing ordinal constants to formal parameters is no longer allowed.
 
* '''Example''':
 
<delphi>
 
procedure test(const a);
 
begin
 
end;
 
  
begin
+
==== Disabled default support for automatic conversions of regular arrays to dynamic arrays ====
  test(5);
+
* '''Old behaviour''': In FPC and ObjFPC modes, by default the compiler could automatically convert a regular array to a dynamic array.
end.
+
* '''New behaviour''': By default, the compiler no longer automatically converts regular arrays to dynamic arrays in any syntax mode.
</delphi>
+
* '''Reason''': When passing a dynamic array by value, modifications to its contents by the callee are also visible on the caller side. However, if an array is implicitly converted to a dynamic array, the result is a temporary value and hence changes are lost. This issue came up when adding [https://bugs.freepascal.org/view.php?id=35580 TStream.Read() overloads].
The above program used to compile, but now it does not anymore.
+
* '''Remedy''': Either change the code so it no longer assigns regular arrays to dynamic arrays, or add ''{$modeswitch arraytodynarray}''
* '''Reason''': It is not clear from the code above what the size of the ordinal constant (1, 2, 4 or 8 bytes) will be when it is passed to the procedure. See for example http://bugs.freepascal.org/view.php?id=9015 for how this can cause problems. The change in behaviour is also Delphi-compatible.
+
* '''Example''': this program demonstrates the issue that appeared with the TStream.Read() overloads that were added (originally, only the the version with the untyped variable existed)
* '''Effect''': Code using this construct will no longer compile.
 
* '''Remedy''': Declare a variable of the appropriate size, assign the value to it and then pass this variable as parameter instead.
 
  
===Treating direct-mapped properties as regular fields===
+
<syntaxhighlight lang="pascal">
 
 
* '''Old behaviour''': The compiler allowed treating properties that directly read and write a field (as opposed to redirecting via a getter/setter) as direct references to this field. This means that you could pass such properties to ''var'' and ''out'' parameters, that you could take their address, that you could assign values to subscripted properties with non-pointer result types (see example ''//2'' below), and that you could assign values to typecasted properties.
 
* '''New behaviour''': All properties are now treated equal, regardless of whether they directly map to a field or use a getter/setter.
 
* '''Example''':
 
<delphi>
 
 
{$mode objfpc}
 
{$mode objfpc}
 
type
 
type
   trec = record
+
   tdynarray = array of byte;
    a, b: integer;
 
  end;
 
  
  tc = class
+
procedure test(var arr); overload;
  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.
 
</delphi>
 
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''.
 
* '''Reason''': Properties abstract the underlying memory layout and class implementation. By ignoring this abstraction in case a property directly mapped to a field, it became impossible to afterwards transparently change the property into an indirection via a getter and/or setter. The new behaviour is also Delphi-compatible.
 
* '''Remedy''': Change your code so that the address of properties is no longer taken, that they are no longer used as ''var'' or ''out'' parameters, that subscripts of properties with a non-pointer result types are no longer assigned to, and that properties to which you write are not typecasted. Note that a class instance qualifies as a pointer type in this context.
 
 
 
===Encoding of single-character constants assigned to widestring===
 
 
 
* '''Old behaviour''': If a source file's encoding was not utf-8 and a single character constant was assigned directly to a widestring, then this character would not be converted from the source code's code page. It would therefore result in a string with ''ord(str[1])'' equal to the ordinal value of that character as it appeared in the source file (i.e., in the source file's code page).
 
* '''New behaviour''': Such character constants are now converted at compile time from the source file's code page into an utf-16 character before being stored into the widestring. In case of ansistrings/shortstrings, nothing changes (i.e., a character with the original ordinal value as it appears in the source file is directly stored into the ansistring/shortstring, without any compile-time conversion)
 
* '''Example''':
 
<delphi>
 
{$codepage cp866}
 
 
 
{$ifdef unix}
 
uses
 
  cwstring;
 
{$endif}
 
 
 
var
 
  w: widestring;
 
  a: ansistring;
 
 
begin
 
begin
   w:='Б';
+
   pbyte(arr)[0]:=1;
  s:='Б';
 
end.
 
</delphi>
 
(it is assumed that the above source file is saved using code page 866)
 
 
 
The "Б" character has ordinal value 129 in [http://en.wikipedia.org/wiki/Code_page_866 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.
 
* '''Reason''': The previous behaviour was buggy, as multi-character constants were correctly converted from the source file's code page.
 
* '''Remedy''': If you want to store a particular ordinal value directly into a widestring without the compiler converting anything regardless of the source file's code page, use #xyza notation (i.e., use 4 digits to define the number, e.g. #0129 in the above example).
 
 
 
===Overloading the assignment operator with a shortstring result===
 
 
 
* '''Old behaviour''': It was possible to overload the assignment operator ":=" for every possible shortstring length as result (i.e., for string[1], string[2], ..., string[255])
 
* '''New behaviour''': It is now only possible to overload the assignment operator for string[255] as result.
 
* '''Example:
 
<delphi>
 
type
 
  ts1 = string[4];
 
  ts2 = string[255];
 
 
 
operator :=(l: longint) res: ts1;
 
begin
 
  str(l:4,res);
 
 
end;
 
end;
  
operator :=(l: longint) res: ts2;
+
procedure test(arr: tdynarray); overload;
 
begin
 
begin
   str(l:20,res);
+
   test[0]:=1;
 
end;
 
end;
  
 +
var
 +
  regulararray: array[1..1] of byte;
 
begin
 
begin
 +
  regulararray[1]:=0;
 +
  test(arr);
 +
  writeln(arr[0]); // writes 0, because it calls test(tdynarr)
 
end.
 
end.
</delphi>
+
</syntaxhighlight>
The above code used to compile in previous versions. Now, the operator with <tt>ts1</tt> as result is refused.
+
* '''svn''': 42118
* '''Reason''': Since shortstrings of all lengths are assignment-compatible with all other shortstrings, an overloaded assignment operator defined for a single shortstring length has to work for assigning to shortstrings of all lengths (see [http://bugs.freepascal.org/view.php?id=12109 bug #12109]). As a result, having assignment operators for multiple shortstring lengths would introduce ambiguity in case there is no exact match.
 
* '''Remedy''': If you require differentiating between multiple shortstring lengths, you now have to wrap these shortstrings in a record:
 
<delphi>
 
type
 
  ts1 = record
 
    s: string[4];
 
  end;
 
  ts2 = record
 
    s: string[255];
 
  end;
 
  
operator :=(l: longint) res: ts1;
+
==== Directive clause ''[…]'' no longer useable with modeswitch ''PrefixedAttributes'' ====
 +
* '''Old behaviour''': A function/procedure/method or procedure/method variable type could be followed by a directive clause in square brackets (''[…]'') that contains the directives for the routine or type (e.g. calling convention).
 +
* '''New behaviour''': If the modeswitch ''PrefixedAttributes'' is enabled (which is the default in modes ''Delphi'' and ''DelphiUnicode'') the directive clause in square brackets is no longer allowed.
 +
* '''Reason''': As custom attributes are bound to a type/property in a way that looks ambiguous to a directive clause and this ambiguity is not easily solved in the parser it is better to disable this feature.
 +
* '''Remedy''':
 +
** don't set (in non-''Delphi'' modes) or disable modeswitch ''PrefixedAttributes'' (in ''Delphi'' modes) if you don't use attributes (''{$modeswitch PrefixedAttributes-}'')
 +
** rework your directive clause:
 +
<syntaxhighlight lang="pascal">
 +
// this
 +
procedure Test; cdecl; [public,alias:'foo']
 
begin
 
begin
  str(l:4,res.s);
 
 
end;
 
end;
  
operator :=(l: longint) res: ts2;
+
// becomes this
 +
procedure Test; cdecl; public; alias:'foo';
 
begin
 
begin
  str(l:20,res.s);
 
 
end;
 
end;
 +
</syntaxhighlight>
 +
* '''svn''': 42402
  
begin
+
==== Type information contains reference to attribute table ====
end.
+
* '''Old behavior''': The first field of the data represented by ''TTypeData'' is whatever the sub branch of the case statement for the type contains.
</delphi>
+
* '''New behavior''': The first field of the data represented by ''TTypeData'' is a reference to the custom attributes that are attributed to the type, only then the type specific fields follow.
 
+
* '''Reason''': Any type can have attributes, so it make sense to provide this is a common location instead of having to parse the different types.
===''Absolute'' variable declarations===
+
* '''Remedy''':
 +
** If you use the records provided by the ''TypInfo'' unit no changes ''should'' be necessary (same for the ''Rtti'' unit).
 +
** If you directly access the binary data you need handle an additional ''Pointer'' field at the beginning of the ''TTypeData'' area and possibly correct the alignment for platforms that have strict alignment requirements (e.g. ARM or M68k).
 +
* '''svn''': 42375
 +
==== Explicit values for enumeration types are limited to low(longint) ... high(longint) ====
 +
* '''Old behavior''': The compiler accepted every integer value as explicit enumeration value. The value was silently reduced to the longint range if it fell outside of that range
 +
* '''New behavior''': The compiler throws an error (FPC mode) or a warning (Delphi mode) if an explicit enumeration value lies outside the longint range.
 +
* '''Reason''': ''Type TEnum = (a = $ffffffff);'' resulted in an enum with size 1 instead of 4 as would be expected, because  $ffffffff was interpreted as "-1".
 +
* '''Remedy''': Add Longint typecasts to values outside the valid range of a Longint.
  
* '''Old behaviour''': It was possible to use ''absolute'' variable declarations to refer to expressions containing implicit pointer dereferences (class fields, dynamic array elements, pchar elements, ansistring/widestring elements, ...). Expressions containing explicit dereferencing were forbidden.
+
==== Comp as a type rename of Int64 instead of an alias ====
* '''New behaviour''': ''absolute'' variable declarations can no longer be used to refer to any kind of dereferenced expressions, be it implicit or explicit.
+
* '''Old behavior''': On non-x86 as well as Win64 the Comp type is declared as an alias to Int64 (''Comp = Int64'').
* '''Example:
+
* '''New behavior''': On non-x86 as well as Win64 the Comp type is declared as a type rename of Int64 (''Comp = type Int64'').
<delphi>
+
* '''Reason''':
type
+
** This allows overloads of ''Comp'' and ''Int64'' methods/functions
  ta = class
+
** This allows to better detect properties of type ''Comp''
    p: pointer;
+
** Compatibility with Delphi for Win64 which applied the same reasoning
    procedure test;
+
* '''Remedy''': If you relied on ''Comp'' being able to be passed to ''Int64'' variables/parameters either include typecasts or add overloads for ''Comp''.
  end;
+
* '''svn''': 43775
 
 
procedure ta.test;
 
var
 
  pa: ta absolute p;
 
  b: pchar;
 
  c: char absolute b[4];
 
begin
 
end;
 
 
 
begin
 
end.
 
</delphi>
 
The above code used to compile, but now it is rejected.
 
* '''Reason''': Consistency (implicit vs. explicit dereferencing should make no difference), Delphi compatibility.
 
* '''Remedy''': You can replace such constructs often either using initialized variables, or using ''with''-statements.
 
  
 +
==== Routines that only differ in result type ====
 +
* '''Old behaviour:''' It was possible to declare routines (functions/procedures/methods) that only differ in their result type.
 +
* '''New behaviour:''' It is no longer possible to declare routines that only differ in their result type.
 +
* '''Reason:''' It makes no sense to allow this as there are situations where the compiler will not be able to determine which function to call (e.g. a simple call to a function ''Foo'' without using the result).
 +
* '''Remedy:''' Correctly declare overloads.
 +
* '''Notes:'''
 +
** As the JVM allows covariant interface implementations such overloads are still allowed inside classes for the JVM target.
 +
** Operator overloads (especially assignment operators) that only differ in result type are still allowed.
 +
* '''svn:''' 45973
  
===Sets in RTTI (run-time type information)===
+
==== Open Strings mode enabled by default in mode Delphi ====
 +
* '''Old behaviour:''' The Open Strings feature (directive ''$OpenStrings'' or ''$P'') was not enabled in mode Delphi.
 +
* '''New behaviour:''' The Open Strings feature (directive ''$OpenStrings'' or ''$P'') is enabled in mode Delphi.
 +
* '''Reason:''' Delphi compatibility.
 +
* '''Remedy:''' If you have assembly routines with a ''var'' parameter of type ''ShortString'' then you also need to handle the hidden ''High'' parameter that is added for the Open String or you need to disable Open Strings for that routine.
 +
* '''git:''' [https://gitlab.com/freepascal.org/fpc/source/-/commit/188cac3bc6dc666167aacf47fedff1a81d378137 188cac3b]
  
* '''Old behaviour''': The ''TParamFlags'' and ''TIntfFlagsBase'' sets from the ''typinfo'' unit used to be four bytes large. They were also always stored in the little endian set format.
+
=== Unit changes ===
* '''New behaviour''': These sets are now one byte large and always stored according to the endianess of the target system.
 
* '''Effect''': Code parsing RTTI information may no longer compile if it typecasts these values into integers.
 
* '''Reason''': Delphi-compatibility.
 
* '''Remedy''': Change longint/integer typecasts into byte typecast when treating these fields as ordinals, and do not fiddle with the bits before using the set values on big endian systems.
 
  
===OpenGL loading===
+
==== System - TVariantManager ====
  
* '''Old behaviour''': After calling any of the ''Load_GL_version_X_X'' routines of the ''glext'' unit, only the extensions/functions introduced by that particular revision of the OpenGL standard became available.
+
* '''Old behaviour:''' ''TVariantManager.olevarfromint'' has a ''source'' parameter of type ''LongInt''.
* '''New behaviour''': All of the ''Load_GL_version_X_X'' functions now also load the functions related to any extensions by earlier versions.
+
* '''New behaviour:''' ''TVariantManager.olevarfromint'' has a ''source'' parameter of type ''Int64''.
* '''Example:
+
* '''Reason for change:''' 64-bit values couldn't be correctly converted to an OleVariant.
<delphi>
+
* '''Remedy:''' If you implemented your own variant manager then adjust the method signature and handle the range parameter accordingly.
uses
+
* '''svn:''' 41570
  gl, glext;
 
  
begin
+
==== System - buffering of output to text files ====
  if not Load_GL_version_2_0 then
 
    begin
 
      writeln('OpenGL 2.0 is not supported');
 
      Halt;
 
    end;
 
end.
 
</delphi>
 
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).
 
* '''Reason''': This is more logical, since all of those OpenGL versions are backwards compatible..
 
* '''Remedy''': Removed any extra OpenGL extension initialization calls from your code. Leaving them there will not cause errors, but they are no longer necessary.
 
  
===dom unit: memory management===
+
* '''Old behaviour:''' Buffering was disabled only for output to text files associated with character devices (Linux, BSD targets, OS/2), or for output to Input, Output and StdErr regardless of their possible redirection (Win32/Win64, AIX, Haiku, BeOS, Solaris).
 +
* '''New behaviour:''' Buffering is disabled for output to text files associated with character devices, pipes and sockets (the latter only if the particular target supports accessing sockets as files - Unix targets).
 +
* '''Reason for change:''' The same behaviour should be ensured on all supported targets whenever possible. Output to pipes and sockets should be performed immediately, equally to output to character devices (typically console) - in case of console users may be waiting for the output, in case of pipes and sockets some other program is waiting for this output and buffering is not appropriate. Seeking is not attempted in SeekEof implementation for files associated with character devices, pipes and sockets, because these files are usually not seekable anyway (instead, reading is performed until the end of the input stream is reached).
 +
* '''Remedy:''' Buffering of a particular file may be controlled programmatically / changed from the default behaviour if necessary. In particular, perform TextRec(YourTextFile).FlushFunc:=nil immediately after opening the text file (i.e. after calling Rewrite or after starting the program in case of Input, Output and StdErr) and before performing any output to this text to enable buffering using the default buffer, or TextRec(YourTextFile).FlushFunc:=TextRec(YourTextFile).FileWriteFunc to disable buffering.
 +
* '''svn:''' 46863
  
* '''Old behaviour''': Destroying a ''TDOMDocument'' or ''TXMLDocument'' would free only those DOM nodes which were part of the document tree. Nodes not yet inserted into the tree would leak unless explicitly destroyed. Once inserted into the tree, a node could not be removed without destroying it. Node replacement/removal methods (namely, ''TDOMNode.RemoveChild'', ''TDOMNode.ReplaceChild'', ''TDOMElement.SetAttributeNode'' and TDOMElement.SetAttributeNodeNS) destroyed their return values and returned ''nil''.
+
==== System - type returned by BasicEventCreate on Windows ====
* '''New behaviour''': Every node created by one of ''TDOMDocument.CreateXX'' methods is "owned" by the document and is guaranteed to be destroyed together with the document. The behaviour of nodes created by other means is unchanged. The node replacement/removal functions listed above no longer destroy their return value and therefore return a valid node.
 
* '''Effect''': The peak memory usage will grow if you replace/remove many nodes during document lifetime.
 
* '''Reason''': Compliance to the DOM specification and compatibility with other DOM implementations, including Delphi.
 
* '''Remedy''': If you wish to keep memory usage at minimum, manually free the nodes that are returned by the methods listed above. This is not a requirement, however.
 
* '''Example''':
 
<delphi>
 
  // code like this
 
  MyNode.ReplaceChild(NewNode, OldNode);
 
  // will now have to become
 
  MyNode.ReplaceChild(NewNode, OldNode).Free;
 
</delphi>
 
The described change is backwards-compatible, because calling ''Free'' for ''nil'' objects which were returned by older versions is actually a no-op.
 
  
===Indexed properties and default parameters===
+
* '''Old behaviour:''' BasicEventCreate returns a pointer to a record which contains the Windows Event handle as well as the last error code after a failed wait. This record was however only provided in the implementation section of the  ''System'' unit.
 +
* '''New behaviour:''' BasicEventCreate returns solely the Windows Event handle.
 +
* '''Reason for change:''' This way the returned handle can be directly used in the Windows ''Wait*''-functions which is especially apparent in ''TEventObject.Handle''.
 +
* '''Remedy:''' If you need the last error code after a failed wait, use ''GetLastOSError'' instead.
 +
* '''svn:''' 49068
  
* '''Old behaviour''': If a getter for an index property has default parameters, it was possible to leave away those parameters also when accessing the property.
+
==== System - Ref. count of strings ====
* '''New behaviour''': When indexing a property, you always have to specify all parameters.
 
* '''Example''':
 
<delphi>
 
{$mode objfpc}{$H+}
 
  
type
+
* '''Old behaviour:''' Reference counter of strings was a ''SizeInt''
  { TForm1 }
+
* '''New behaviour:'''  Reference counter of strings is now a ''Longint'' on 64 Bit platforms and ''SizeInt'' on all other platforms.
  TForm1 = class
+
* '''Reason for change:''' Better alignment of strings
  private
+
* '''Remedy:''' Call ''System.StringRefCount'' instead of trying to access the ref. count field by pointer operations or other tricks.
    function GetFoo(Index: Integer; Ask: Boolean = True): Integer;
+
* '''git:''' [https://gitlab.com/freepascal.org/fpc/source/-/commit/ee10850a5793b69b19dc82b9c28342bdd0018f2e ee10850a57]
  public
 
    property Foo[Index: Integer; Ask: Boolean]: Integer read GetFoo;
 
  end;
 
  
function TForm1.GetFoo(Index: Integer; Ask: Boolean): Integer;
+
==== System.UITypes - function TRectF.Union changed to procedure ====
begin
 
  Result := Foo[Index]; //1
 
end;
 
  
end.
+
* '''Old behaviour:''' ''function TRectF.Union(const r: TRectF): TRectF;''
</delphi>
+
* '''New behaviour:'''  ''procedure TRectF.Union(const r: TRectF);''
 +
* '''Reason for change:''' Delphi compatibility and also compatibility with TRect.Union
 +
* '''Remedy:''' Call ''class function TRectF.Union'' instead.
 +
* '''git:''' [https://gitlab.com/freepascal.org/fpc/source/-/commit/5109f0ba444c85d2577023ce5fbdc2ddffc267c8 5109f0ba]
  
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.
+
==== 64-bit values in OleVariant ====
* '''Reason''': Delphi compatibility, and the fact that you cannot use default parameters with setters (since there the set value appears as the last parameter) made this (unintential) feature behave asymmetrically.
 
* '''Remedy''': Always specify all parameters when using indexed properties.
 
  
===Order of field and method/property declarations===
+
* '''Old behaviour:''' If a 64-bit value (''Int64'', ''QWord'') is assigned to an OleVariant its type is ''varInteger'' and only the lower 32-bit are available.
 +
* '''New behaviour:''' If a 64-bit value (''Int64'', ''QWord'') is assigned to an OleVariant its type is either ''varInt64'' or ''varQWord'' depending on the input type.
 +
* '''Reason for change:''' 64-bit values weren't correctly represented. This change is also Delphi compatible.
 +
* '''Remedy:''' Ensure that you handle 64-bit values correctly when using OleVariant.
 +
* '''svn:''' 41571
  
* '''Old behaviour''': Field declarations could appear anywhere inside an object or class definition.
+
==== Classes TCollection.Move ====
* '''New behaviour''': Per individual visibility block declaration (''public'', ''private'', ...), all fields must be declared before the property and method declarations.
+
* '''Old behaviour:''' If a TCollection.Descendant called Move() this would invoke System.Move.
* '''Example''':
+
* '''New behaviour:''' If a TCollection.Descendant called Move() this invokes TCollection.Move.
<delphi>
+
* '''Reason for change:''' New feature in TCollection: move, for consistency with other classes.
{$mode objfpc}
+
* '''Remedy:'''  prepend the Move() call with the system unit name: System.move().
 +
* '''svn:''' 41795
  
type
+
==== Math Min/MaxSingle/Double ====
  tc = class
+
* '''Old behaviour:''' MinSingle/MaxSingle/MinDouble/MaxDouble were set to a small/big value close to the smallest/biggest possible value.
    constructor create;
+
* '''New behaviour:''' The constants represent now the smallest/biggest positive normal numbers.
    a: longint;
+
* '''Reason for change:''' Consistency (this is also Delphi compatibility), see https://gitlab.com/freepascal.org/fpc/source/-/issues/36870.
  end;
+
* '''Remedy:'''  If the code really depends on the old values, rename them and use them as renamed.
 +
* '''svn:''' 44714
  
constructor tc.create;
+
==== Random generator ====
begin
+
* '''Old behaviour:''' FPC uses a Mersenne twister generate random numbers
end;
+
* '''New behaviour:''' Now it uses Xoshiro128**
 +
* '''Reason for change:''' Xoshiro128** is faster, has a much smaller memory footprint and generates better random numbers.
 +
* '''Remedy:''' When using a certain randseed, another random sequence is generated, but as the PRNG is considered as an implementation detail, this does not hurt.
 +
* '''git:''' 91cf1774
  
begin
+
==== Types.TPointF.operator * ====
end.
+
* '''Old behaviour:''' for <code>a, b: TPointF</code>, <code>a * b</code> is a synonym for <code>a.DotProduct(b)</code>: it returns a <code>single</code>, scalar product of two input vectors.
</delphi>
+
* '''New behaviour:''' <code>a * b</code> does a component-wise multiplication and returns <code>TPointF</code>.
The above code used to compile, but now it will cause an error due to the ''a'' field appearing after the constructor.
+
* '''Reason for change''': Virtually all technologies that have a notion of vectors use <code>*</code> for component-wise multiplication. Delphi with its <code>System.Types</code> is among these technologies.
* '''Reason''':
+
* '''Remedy:''' Use newly-introduced <code>a ** b</code>, or <code>a.DotProduct(b)</code> if you need Delphi compatibility.
<delphi>
+
* '''git:''' [https://gitlab.com/freepascal.org/fpc/source/-/commit/f1e391fb415239d926c4f23babe812e67824ef95 f1e391fb]
{$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;
+
==== CocoaAll ====
begin
+
===== CoreImage Framework Linking =====
end;
+
* '''Old behaviour''': Starting with FPC 3.2.0, the ''CocoaAll'' unit linked caused the ''CoreImage'' framework to be linked.
 +
* '''New behaviour''': The ''CocoaAll'' unit no longer causes the ''CoreImage'' framework to be linked.
 +
* '''Reason for change''': The ''CoreImage'' framework is not available on OS X 10.10 and earlier (it's part of ''QuartzCore'' there, and does not exist at all on some even older versions).
 +
* '''Remedy''': If you use functionality that is only available as part of the separate ''CoreImage'' framework, explicitly link it in your program using the ''{$linkframework CoreImage}'' directive.
 +
* '''svn''': 45767
  
begin
+
==== DB ====
end.
+
===== TMSSQLConnection uses TDS protocol version 7.3 (MS SQL Server 2008) =====
</delphi>
+
* '''Old behaviour:''' TMSSQLConnection used TDS protocol version 7.0 (MS SQL Server 2000).
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.
+
* '''New behaviour:''' TMSSQLConnection uses TDS protocol version 7.3 (MS SQL Server 2008).
 +
* '''Reason for change:''' native support for new data types introduced in MS SQL Server 2008 (like DATE, TIME, DATETIME2). FreeTDS client library version 0.95 or higher required.
 +
* '''svn''': 42737
  
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.
+
===== DB.TFieldType: new types added =====
* '''Remedy''': There are two possible remedies:
+
* '''Old behaviour:''' .
** Move the field declarations before the method/property declarations
+
* '''New behaviour:''' Some of new Delphi field types were added (ftOraTimeStamp, ftOraInterval, ftLongWord, ftShortint, ftByte, ftExtended) + corresponding classes TLongWordField, TShortIntField, TByteField; Later were added also ftSingle and TExtendedField, TSingleField
** Start a new visibility block before the field declaration:
+
* '''Reason for change:''' align with Delphi and open space for support of short integer and unsigned integer data types
<delphi>
+
* '''svn''': 47217, 47219, 47220, 47221; '''git''': c46b45bf
{$mode objfpc}
 
  
type
+
==== DaemonApp ====
  tc = class
+
===== TDaemonThread =====
    function getx(i: longint): longint;
+
* '''Old behaviour:''' The virtual method ''TDaemonThread.HandleControlCode'' takes a single ''DWord'' parameter containing the control code.
    property prop[i: longint]: longint read getx;
+
* '''New behaviour:''' The virtual method ''TDaemonThread.HandleControlCode'' takes three parameters of which the first is the control code, the other two are an additional event type and event data.
  public // added
+
* '''Reason for change:''' Allow for additional event data to be passed along which is required for comfortable handling of additional control codes provided on Windows.
    default: longint;
+
* '''svn''': 46327
  end;
 
</delphi>
 
 
 
===Local type definitions in parameter lists===
 
* '''Old behaviour''': Parameter lists and function result types could contain local type definitions.
 
* '''New behaviour''': Local type definitions are no longer allowed inside parameter lists and function results.
 
* '''Example''':
 
<delphi>
 
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;
 
</delphi>
 
All of the above subroutine definitions will now be rejected, because they all define new types inside their parameter lists or result type.
 
* '''Reason''': In Pascal, two parameters are only of the same type if their type refers to the same type definition. Allowing local type definitions inside a subroutine declaration therefore by definition causes errors in case the subroutine is declared globally in a unit. The reason is that the type definition in the interface and in the implementation definitions will differ (both times a new type is created), and hence the compiler will not be able to find the implementation of the interface definition. This change is also Delphi compatible.
 
* '''Remedy''': Move the type definitions into separate type blocks:
 
<delphi>
 
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;
 
</delphi>
 
  
===ppc386.cfg configuration file is no longer read===
+
===== TDaemon =====
 +
* '''Old behaviour:''' If an event handler is assigned to ''OnControlCode'' then it will be called if the daemon receives a control code.
 +
* '''New behaviour:''' If an event handler is assigned to ''OnControlCodeEvent'' and that sets the ''AHandled'' parameter to ''True'' then ''OnControlCode'' won't be called, otherwise it will be called if assigned.
 +
* '''Reason for change:''' This was necessary to implement the handling of additional arguments for control codes with as few backwards incompatible changes as possible.
 +
* '''svn''': 46327
  
* '''Old behaviour''': In addition to ''fpc.cfg'' and ''.fpc.cfg'', the compiler also looked for configuration files with the names ''ppc386.cfg'' and ''.ppc386.cfg''
+
==== FileInfo ====
* '''New behaviour''': The compiler only looks for configuration files with the names fpc.cfg and .fpc.cfg
+
* '''Old behaviour:''' The ''FileInfo'' unit is part of the ''fcl-base'' package.
* '''Reason''': The ''ppc386.cfg'' name stems from the time that the compiler only supported the i386 platform, which is no longer the case. Naming configuration files like that has also been deprecated since quite a while, and the compiler warned about this in previous versions.
+
* '''New behaviour:''' The ''FileInfo'' unit is part of the ''fcl-extra'' package.
* '''Remedy''': Rename any ''(.)ppc386.cfg'' files you have and are using to ''(.)fpc.cfg''
+
* '''Reason for change:''' Breaks up a cycle in build dependencies after introducing a RC file parser into ''fcl-res''. This should only affect users that compile trunk due to stale PPU files in the old location or that use a software distribution that splits the FPC packages (like Debian).
 +
* '''svn''': 46392
  
=== Almost all old 1.0.x socket unit functions have been removed ===
+
==== Sha1 ====
 +
* '''Old behaviour:''' Sha1file silently did nothing on file not found.
 +
* '''New behaviour:''' sha1file now raises sysconst.sfilenotfound exception on fle not found.
 +
* '''Reason for change:''' Behaviour was not logical, other units in the same package already used sysutils.
 +
* '''svn''': 49166
  
* '''Old behaviour''': Basic socket functions were available in both fp<name> and <name> flavours (e.g., both ''fpbind()'' and ''bind()'')
+
==== Image ====
* '''New behaviour''': All <name>-functions whose functionality was identical to that of the fp<name> variant have been removed. Some of the ''bind()'' variants did offer different functionality and therefore have been kept. This may result in "''can't determine which overloaded''" errors under certain circumstances.
+
===== FreeType: include bearings and invisible characters into text bounds =====
* '''Reason''':  These 1.0.x-era functions have been deprecated since 1.9.x times. Some errors in documenting this deprecation have lead to removing them only now. The reason for the deprecation was their behaviour not exactly matching the POSIX socket functions, even though they had the same name. E.g., some of these functions' abilities to signal errors were incomplete and some of the names deviated from the standard names (e.g., ''getsocketoption()'' vs. ''getsockopt()''). The fp<name> functions match the POSIX standard both in name and behaviour, except for the additional ''fp''-prefix.
+
* '''Old behaviour:''' When the bounds rect was calculated for a text, invisible characters (spaces) and character bearings (spacing around character) were ignored. The result of Canvas.TextExtent() was too short and did not include all with Canvas.TextOut() painted pixels.
* '''Remedy''': Use the fp* functions. Be aware of some differences in the argument types (pointer types vs. var-parameters), which may require an extra @-operator for certain parameters.
+
* '''New behaviour:''' the bounds rect includes invisible characters and bearings. Canvas.TextExtent() covers the Canvas.TextOut() area.
 +
* '''Reason for change:''' The text could not be correctly aligned to center or right, the underline and textrect fill could not be correctly painted.
 +
* '''svn''': 49629
  
=== Infozip based unzip renamed unzip51g ===
+
==== Generics.Collections & Generics.Defaults ====
+
* '''Old behaviour:''' Various methods had '''constref''' parameters.
* '''Old behaviour''':  The distribution contained two unzip units: ''paszlib/src/unzip.pp'' and ''unzip/src/unzip.pp''.
+
* '''New behaviour:''' '''constref''' parameters were changed to '''const''' parameters.
* '''New behaviour''': The ''unzip/src/unzip.pp'' unit has been renamed to ''unzip51g.pp''.
+
* '''Reason for change:'''
* '''Reason''': One of the two units had to be renamed to solve the name collision. The ''paszlib/'' version seemed more complete, so was given the base name "unzip.pp". The ''unzip/'' unit has been renamed to ''unzip51g'' because the source file says it is based on the 51g version of InfoZIP.
+
** Delphi compatibility
* '''Remedy''': In case you application depends on InfoZIP-specific functionality, use the ''unzip51g'' instead of the ''unzip'' unit.
+
** Better code generation especially for types that are smaller or equal to the ''Pointer'' size.
 +
* '''Remedy:''' Adjust parameters of method pointers or virtual methods.
 +
* '''git''': [https://gitlab.com/freepascal.org/fpc/source/-/commit/693491048bf2c6f9122a0d8b044ad0e55382354d 69349104]
  
== All Unix-based systems ==
+
== AArch64/ARM64 ==
 +
=== ''{''-style comments no longer supported in assembler blocks ===
 +
* '''Old behaviour''': The ''{'' character started a comment in assembler blocks, like in Pascal
 +
* '''New behaviour''': The ''{'' character now has a different meaning in the AArch64 assembler reader, so it can no longer be used to start comments.
 +
* '''Reason for change''': Support has been added for register sets in the AArch64 assembler reader (for the ld1/ld2/../st1/st2/... instructions), which also start with ''{''.
 +
* '''Remedy''': Use ''(*'' or ''//'' to start comments
 +
* '''svn''': 47116
  
===FindFirst/FindNext===
 
  
* '''Old behaviour''': If the search pattern did not contain any wildcards (such as '?' or '*'), then the search attributes (faDirectory, faHidden, ...) were ignored.
+
== Darwin/iOS ==
* '''New behaviour''': Regardless of the format of the search pattern, the search attributes are properly taken into account.
 
* '''Effect''': If you called ''FindFirst'' with a search pattern not containing any wildcards and no special attributes, such invocation would also return directories, hidden files, etc. Now only regular files will be returned, unless you specify the appropriate attributes.
 
* '''Reason''': Conforming with the documented behaviour, and the behaviour on other platforms.
 
* '''Remedy''': Specify the proper attributes if you also want to search for other things than regular files.
 
  
===Signals/exceptions in libraries===
+
== Previous release notes ==
 +
{{Navbar Lazarus Release Notes}}
  
* '''Old behaviour''': FPC always hooked the ''SIGFPE'', ''SIGSEGV'', ''SIGBUS'' and ''SIGILL'' Unix signals in the initialization code of the system unit.
+
[[Category:FPC User Changes by release]]
* '''New behaviour''': The aforementioned signals are no longer automatically hooked in the initialization code of libraries (or rather: unhooked once the system unit's initialization code has finished). In case of programs, these signals remain hooked as before.
+
[[Category:Release Notes]]
* '''Effect''': Catching exceptions resulting from the aforementioned signals will no longer work by default in FPC libraries, as the signals will no longer be caught by the library and hence not be translated into exceptions. Note that this never worked anyway for libraries that were dynamically linked against a program at compile time, because in that case the program's initialization code ran after the library's initialization code, thereby overriding its signal handlers. Proper support for this functionality requires Delphi-style packages support. The behaviour of Pascal language exceptions is not affected by this change.
+
[[Category:Troubleshooting]]
* '''Example''': See the test programs in the testsuite: [http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/webtbs/tw12704a.pp?view=markup the library] and [http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/webtbs/tw12704b.pp?view=markup  the host program]
 
* '''Reason''': Only one signal handler can be installed per signal. So if you dynamically loaded an FPC library at run time, then it would immediately install its signal handlers, thereby overriding any handlers the host program might already have installed. See http://bugs.freepascal.org/view.php?id=12704 for more information.
 
* '''Remedy''': You can use SysUtils' ''InquireSignal()'', ''HookSignal()'', ''UnhookSignal()'' and ''AbandonSignalHandler()'' routines to selectively hook/unhook particular signals in your library, and to restore previously installed handlers. See http://bugs.freepascal.org/view.php?id=12704 for more information on these routines.
 

Latest revision as of 18:32, 9 February 2024

About this page

Listed below are intentional changes made to the FPC compiler (trunk) since the previous release that may break existing code. The list includes reasons why these changes have been implemented, and suggestions for how you might adapt your code if you find that previously working code has been adversely affected by these recent changes.

The list of new features that do not break existing code can be found here.

Please add revision numbers to the entries from now on. This facilitates moving merged items to the user changes of a release.

All systems

Language Changes

Precedence of the IS operator changed

  • Old behaviour: The IS operator had the same precedence as the multiplication, division etc. operators.
  • New behaviour: The IS operator has the same precedence as the comparison operators.
  • Reason: Bug, see [1].
  • Remedy: Add parenthesis where needed.

Visibilities of members of generic specializations

  • Old behaviour: When a generic is specialized then visibility checks are handled as if the generic was declared in the current unit.
  • New behaviour: When a generic is specialized then visibility checks are handled according to where the generic is declared.
  • Reason: Delphi-compatibility, but also a bug in how visibilities are supposed to work.
  • Remedy: Rework your code to adhere to the new restrictions.

Implementation Changes

Disabled default support for automatic conversions of regular arrays to dynamic arrays

  • Old behaviour: In FPC and ObjFPC modes, by default the compiler could automatically convert a regular array to a dynamic array.
  • New behaviour: By default, the compiler no longer automatically converts regular arrays to dynamic arrays in any syntax mode.
  • Reason: When passing a dynamic array by value, modifications to its contents by the callee are also visible on the caller side. However, if an array is implicitly converted to a dynamic array, the result is a temporary value and hence changes are lost. This issue came up when adding TStream.Read() overloads.
  • Remedy: Either change the code so it no longer assigns regular arrays to dynamic arrays, or add {$modeswitch arraytodynarray}
  • Example: this program demonstrates the issue that appeared with the TStream.Read() overloads that were added (originally, only the the version with the untyped variable existed)
{$mode objfpc}
type
  tdynarray = array of byte;

procedure test(var arr); overload;
begin
  pbyte(arr)[0]:=1;
end;

procedure test(arr: tdynarray); overload;
begin
  test[0]:=1;
end;

var
  regulararray: array[1..1] of byte;
begin
  regulararray[1]:=0;
  test(arr);
  writeln(arr[0]); // writes 0, because it calls test(tdynarr)
end.
  • svn: 42118

Directive clause […] no longer useable with modeswitch PrefixedAttributes

  • Old behaviour: A function/procedure/method or procedure/method variable type could be followed by a directive clause in square brackets ([…]) that contains the directives for the routine or type (e.g. calling convention).
  • New behaviour: If the modeswitch PrefixedAttributes is enabled (which is the default in modes Delphi and DelphiUnicode) the directive clause in square brackets is no longer allowed.
  • Reason: As custom attributes are bound to a type/property in a way that looks ambiguous to a directive clause and this ambiguity is not easily solved in the parser it is better to disable this feature.
  • Remedy:
    • don't set (in non-Delphi modes) or disable modeswitch PrefixedAttributes (in Delphi modes) if you don't use attributes ({$modeswitch PrefixedAttributes-})
    • rework your directive clause:
// this
procedure Test; cdecl; [public,alias:'foo']
begin
end;

// becomes this
procedure Test; cdecl; public; alias:'foo';
begin
end;
  • svn: 42402

Type information contains reference to attribute table

  • Old behavior: The first field of the data represented by TTypeData is whatever the sub branch of the case statement for the type contains.
  • New behavior: The first field of the data represented by TTypeData is a reference to the custom attributes that are attributed to the type, only then the type specific fields follow.
  • Reason: Any type can have attributes, so it make sense to provide this is a common location instead of having to parse the different types.
  • Remedy:
    • If you use the records provided by the TypInfo unit no changes should be necessary (same for the Rtti unit).
    • If you directly access the binary data you need handle an additional Pointer field at the beginning of the TTypeData area and possibly correct the alignment for platforms that have strict alignment requirements (e.g. ARM or M68k).
  • svn: 42375

Explicit values for enumeration types are limited to low(longint) ... high(longint)

  • Old behavior: The compiler accepted every integer value as explicit enumeration value. The value was silently reduced to the longint range if it fell outside of that range
  • New behavior: The compiler throws an error (FPC mode) or a warning (Delphi mode) if an explicit enumeration value lies outside the longint range.
  • Reason: Type TEnum = (a = $ffffffff); resulted in an enum with size 1 instead of 4 as would be expected, because $ffffffff was interpreted as "-1".
  • Remedy: Add Longint typecasts to values outside the valid range of a Longint.

Comp as a type rename of Int64 instead of an alias

  • Old behavior: On non-x86 as well as Win64 the Comp type is declared as an alias to Int64 (Comp = Int64).
  • New behavior: On non-x86 as well as Win64 the Comp type is declared as a type rename of Int64 (Comp = type Int64).
  • Reason:
    • This allows overloads of Comp and Int64 methods/functions
    • This allows to better detect properties of type Comp
    • Compatibility with Delphi for Win64 which applied the same reasoning
  • Remedy: If you relied on Comp being able to be passed to Int64 variables/parameters either include typecasts or add overloads for Comp.
  • svn: 43775

Routines that only differ in result type

  • Old behaviour: It was possible to declare routines (functions/procedures/methods) that only differ in their result type.
  • New behaviour: It is no longer possible to declare routines that only differ in their result type.
  • Reason: It makes no sense to allow this as there are situations where the compiler will not be able to determine which function to call (e.g. a simple call to a function Foo without using the result).
  • Remedy: Correctly declare overloads.
  • Notes:
    • As the JVM allows covariant interface implementations such overloads are still allowed inside classes for the JVM target.
    • Operator overloads (especially assignment operators) that only differ in result type are still allowed.
  • svn: 45973

Open Strings mode enabled by default in mode Delphi

  • Old behaviour: The Open Strings feature (directive $OpenStrings or $P) was not enabled in mode Delphi.
  • New behaviour: The Open Strings feature (directive $OpenStrings or $P) is enabled in mode Delphi.
  • Reason: Delphi compatibility.
  • Remedy: If you have assembly routines with a var parameter of type ShortString then you also need to handle the hidden High parameter that is added for the Open String or you need to disable Open Strings for that routine.
  • git: 188cac3b

Unit changes

System - TVariantManager

  • Old behaviour: TVariantManager.olevarfromint has a source parameter of type LongInt.
  • New behaviour: TVariantManager.olevarfromint has a source parameter of type Int64.
  • Reason for change: 64-bit values couldn't be correctly converted to an OleVariant.
  • Remedy: If you implemented your own variant manager then adjust the method signature and handle the range parameter accordingly.
  • svn: 41570

System - buffering of output to text files

  • Old behaviour: Buffering was disabled only for output to text files associated with character devices (Linux, BSD targets, OS/2), or for output to Input, Output and StdErr regardless of their possible redirection (Win32/Win64, AIX, Haiku, BeOS, Solaris).
  • New behaviour: Buffering is disabled for output to text files associated with character devices, pipes and sockets (the latter only if the particular target supports accessing sockets as files - Unix targets).
  • Reason for change: The same behaviour should be ensured on all supported targets whenever possible. Output to pipes and sockets should be performed immediately, equally to output to character devices (typically console) - in case of console users may be waiting for the output, in case of pipes and sockets some other program is waiting for this output and buffering is not appropriate. Seeking is not attempted in SeekEof implementation for files associated with character devices, pipes and sockets, because these files are usually not seekable anyway (instead, reading is performed until the end of the input stream is reached).
  • Remedy: Buffering of a particular file may be controlled programmatically / changed from the default behaviour if necessary. In particular, perform TextRec(YourTextFile).FlushFunc:=nil immediately after opening the text file (i.e. after calling Rewrite or after starting the program in case of Input, Output and StdErr) and before performing any output to this text to enable buffering using the default buffer, or TextRec(YourTextFile).FlushFunc:=TextRec(YourTextFile).FileWriteFunc to disable buffering.
  • svn: 46863

System - type returned by BasicEventCreate on Windows

  • Old behaviour: BasicEventCreate returns a pointer to a record which contains the Windows Event handle as well as the last error code after a failed wait. This record was however only provided in the implementation section of the System unit.
  • New behaviour: BasicEventCreate returns solely the Windows Event handle.
  • Reason for change: This way the returned handle can be directly used in the Windows Wait*-functions which is especially apparent in TEventObject.Handle.
  • Remedy: If you need the last error code after a failed wait, use GetLastOSError instead.
  • svn: 49068

System - Ref. count of strings

  • Old behaviour: Reference counter of strings was a SizeInt
  • New behaviour: Reference counter of strings is now a Longint on 64 Bit platforms and SizeInt on all other platforms.
  • Reason for change: Better alignment of strings
  • Remedy: Call System.StringRefCount instead of trying to access the ref. count field by pointer operations or other tricks.
  • git: ee10850a57

System.UITypes - function TRectF.Union changed to procedure

  • Old behaviour: function TRectF.Union(const r: TRectF): TRectF;
  • New behaviour: procedure TRectF.Union(const r: TRectF);
  • Reason for change: Delphi compatibility and also compatibility with TRect.Union
  • Remedy: Call class function TRectF.Union instead.
  • git: 5109f0ba

64-bit values in OleVariant

  • Old behaviour: If a 64-bit value (Int64, QWord) is assigned to an OleVariant its type is varInteger and only the lower 32-bit are available.
  • New behaviour: If a 64-bit value (Int64, QWord) is assigned to an OleVariant its type is either varInt64 or varQWord depending on the input type.
  • Reason for change: 64-bit values weren't correctly represented. This change is also Delphi compatible.
  • Remedy: Ensure that you handle 64-bit values correctly when using OleVariant.
  • svn: 41571

Classes TCollection.Move

  • Old behaviour: If a TCollection.Descendant called Move() this would invoke System.Move.
  • New behaviour: If a TCollection.Descendant called Move() this invokes TCollection.Move.
  • Reason for change: New feature in TCollection: move, for consistency with other classes.
  • Remedy: prepend the Move() call with the system unit name: System.move().
  • svn: 41795

Math Min/MaxSingle/Double

  • Old behaviour: MinSingle/MaxSingle/MinDouble/MaxDouble were set to a small/big value close to the smallest/biggest possible value.
  • New behaviour: The constants represent now the smallest/biggest positive normal numbers.
  • Reason for change: Consistency (this is also Delphi compatibility), see https://gitlab.com/freepascal.org/fpc/source/-/issues/36870.
  • Remedy: If the code really depends on the old values, rename them and use them as renamed.
  • svn: 44714

Random generator

  • Old behaviour: FPC uses a Mersenne twister generate random numbers
  • New behaviour: Now it uses Xoshiro128**
  • Reason for change: Xoshiro128** is faster, has a much smaller memory footprint and generates better random numbers.
  • Remedy: When using a certain randseed, another random sequence is generated, but as the PRNG is considered as an implementation detail, this does not hurt.
  • git: 91cf1774

Types.TPointF.operator *

  • Old behaviour: for a, b: TPointF, a * b is a synonym for a.DotProduct(b): it returns a single, scalar product of two input vectors.
  • New behaviour: a * b does a component-wise multiplication and returns TPointF.
  • Reason for change: Virtually all technologies that have a notion of vectors use * for component-wise multiplication. Delphi with its System.Types is among these technologies.
  • Remedy: Use newly-introduced a ** b, or a.DotProduct(b) if you need Delphi compatibility.
  • git: f1e391fb

CocoaAll

CoreImage Framework Linking
  • Old behaviour: Starting with FPC 3.2.0, the CocoaAll unit linked caused the CoreImage framework to be linked.
  • New behaviour: The CocoaAll unit no longer causes the CoreImage framework to be linked.
  • Reason for change: The CoreImage framework is not available on OS X 10.10 and earlier (it's part of QuartzCore there, and does not exist at all on some even older versions).
  • Remedy: If you use functionality that is only available as part of the separate CoreImage framework, explicitly link it in your program using the {$linkframework CoreImage} directive.
  • svn: 45767

DB

TMSSQLConnection uses TDS protocol version 7.3 (MS SQL Server 2008)
  • Old behaviour: TMSSQLConnection used TDS protocol version 7.0 (MS SQL Server 2000).
  • New behaviour: TMSSQLConnection uses TDS protocol version 7.3 (MS SQL Server 2008).
  • Reason for change: native support for new data types introduced in MS SQL Server 2008 (like DATE, TIME, DATETIME2). FreeTDS client library version 0.95 or higher required.
  • svn: 42737
DB.TFieldType: new types added
  • Old behaviour: .
  • New behaviour: Some of new Delphi field types were added (ftOraTimeStamp, ftOraInterval, ftLongWord, ftShortint, ftByte, ftExtended) + corresponding classes TLongWordField, TShortIntField, TByteField; Later were added also ftSingle and TExtendedField, TSingleField
  • Reason for change: align with Delphi and open space for support of short integer and unsigned integer data types
  • svn: 47217, 47219, 47220, 47221; git: c46b45bf

DaemonApp

TDaemonThread
  • Old behaviour: The virtual method TDaemonThread.HandleControlCode takes a single DWord parameter containing the control code.
  • New behaviour: The virtual method TDaemonThread.HandleControlCode takes three parameters of which the first is the control code, the other two are an additional event type and event data.
  • Reason for change: Allow for additional event data to be passed along which is required for comfortable handling of additional control codes provided on Windows.
  • svn: 46327
TDaemon
  • Old behaviour: If an event handler is assigned to OnControlCode then it will be called if the daemon receives a control code.
  • New behaviour: If an event handler is assigned to OnControlCodeEvent and that sets the AHandled parameter to True then OnControlCode won't be called, otherwise it will be called if assigned.
  • Reason for change: This was necessary to implement the handling of additional arguments for control codes with as few backwards incompatible changes as possible.
  • svn: 46327

FileInfo

  • Old behaviour: The FileInfo unit is part of the fcl-base package.
  • New behaviour: The FileInfo unit is part of the fcl-extra package.
  • Reason for change: Breaks up a cycle in build dependencies after introducing a RC file parser into fcl-res. This should only affect users that compile trunk due to stale PPU files in the old location or that use a software distribution that splits the FPC packages (like Debian).
  • svn: 46392

Sha1

  • Old behaviour: Sha1file silently did nothing on file not found.
  • New behaviour: sha1file now raises sysconst.sfilenotfound exception on fle not found.
  • Reason for change: Behaviour was not logical, other units in the same package already used sysutils.
  • svn: 49166

Image

FreeType: include bearings and invisible characters into text bounds
  • Old behaviour: When the bounds rect was calculated for a text, invisible characters (spaces) and character bearings (spacing around character) were ignored. The result of Canvas.TextExtent() was too short and did not include all with Canvas.TextOut() painted pixels.
  • New behaviour: the bounds rect includes invisible characters and bearings. Canvas.TextExtent() covers the Canvas.TextOut() area.
  • Reason for change: The text could not be correctly aligned to center or right, the underline and textrect fill could not be correctly painted.
  • svn: 49629

Generics.Collections & Generics.Defaults

  • Old behaviour: Various methods had constref parameters.
  • New behaviour: constref parameters were changed to const parameters.
  • Reason for change:
    • Delphi compatibility
    • Better code generation especially for types that are smaller or equal to the Pointer size.
  • Remedy: Adjust parameters of method pointers or virtual methods.
  • git: 69349104

AArch64/ARM64

{-style comments no longer supported in assembler blocks

  • Old behaviour: The { character started a comment in assembler blocks, like in Pascal
  • New behaviour: The { character now has a different meaning in the AArch64 assembler reader, so it can no longer be used to start comments.
  • Reason for change: Support has been added for register sets in the AArch64 assembler reader (for the ld1/ld2/../st1/st2/... instructions), which also start with {.
  • Remedy: Use (* or // to start comments
  • svn: 47116


Darwin/iOS

Previous release notes