User Changes Trunk

From Lazarus wiki
Revision as of 17:41, 4 November 2009 by Paul Ishenin (talk | contribs)
Jump to navigationJump to search

About this page

Below you can find a list of intentional changes since the upcoming release branched off 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.

All systems

Usage Changes

Language changes

Passing derived classes to var- and out-parameters

  • Old behaviour: If a routine was declared with a var- or out-parameter of a certain class type, the compiler also allowed passing derived classes to this parameter.
  • New behaviour: The compile-time type of a class passed to a routine now has to match the declared parameter type exactly in case of var- and out-parameters.
  • Example:

<delphi> {$mode objfpc}

type

 ta = class
 end;
 tb = class(ta)
 end;

var

 b: tb;

procedure test(var a: ta); begin

 a:=ta.create;
 // now b contains an instance of type "ta"

end;

begin

 b:=nil;
 test(b);

end. </delphi> The compiler used to accept the above program, but now it will give an error at the call to test.

  • Reason: As the example above demonstrates, allowing this behaviour circumvents the language's type checking. This change is also Delphi-compatible.
  • Remedy: Rewrite the affected code so it that all var/out-parameters and the class types passed to them match exactly. There are ways to circumvent the type checking at the caller side by using explicit type conversions, but using such hacks is strongly discouraged since the resulting code is not type-safe.

Array of const parameters and cdecl routines

  • Old behaviour: It was possible to have non-external cdecl routines with an array of const parameter.
  • New behaviour: Cdecl routines with an array of const parameter now always must be external.
  • Reason: In FPC, adding an array of const parameter to a cdecl routine has the same effect as adding the varargs modifier. It means that the routine takes a C-style variable number of arguments. There is however no way in (Free) Pascal to access these arguments on the callee side. This change means that both varargs and array of const are treated consistently, since varargs routines already had to be external.
  • Remedy: Remove the cdecl specifier and use a Pascal-style array of const, or implement the routine in C and add external to the Pascal declaration.

Abstract and Sealed class modifiers

  • Old behaviour: It was possible to have abstract or sealed fields immediately following the class keyword.
  • New behaviour: The compiler now interprets abstract and sealed as class modifiers if they immediately follow the class keyword.
  • Example:

<delphi> {$mode objfpc} type

 TSomeClass1 = class
    abstract: integer;
 end;
 TSomeClass2 = class
    sealed: integer;
 end;

</delphi> The above code will no longer compile.

  • Reason: abstract and sealed are now the class modifiers, which is Delphi-compatible
  • Remedy: Separate the abstract or sealed field name from the class keyword with a visibility section (published, public, ...) or with another field declaration.

Implementation changes

Order of parameters in RTTI

  • Old behaviour: The order in which the parameter information for a function was stored in the RTTI depended on the function's calling convention. If the calling convention on i386 passed parameters from left-to-right, parameters were stored from left to right (regardless of the actual platform, which was a bug in itself), otherwise they were stored from right to left.
  • New behaviour: The parameters are always stored from left to right in the RTTI, i.e., as they appear in the source code.
  • Effect: Code parsing RTTI information for the purpose of figuring out in which order to pass the parameters will no longer work.
  • Reason: Delphi compatibility, making the information more useful for IDEs.
  • Remedy: Adjust your code so it always expects parameters to appear in the RTTI ordered from left to right. In the future, we will also add the calling convention itself to the RTTI (like Delphi), so you can use that information to reorder the parameters in case you want to use this information to call the routine.

Types changes

TObject class declaration

  • Old behaviour: TObject class did not have UnitName, Equals, GetHashCode, ToString methods.
  • New behaviour: Those methods were added to the TObject class.
  • Effect: Compiler produces warnings in delphi mode and errors in objfpc mode if user classes have the same identifier(s).
  • Reason: Delphi compatibility, these methods are present in the TObject class since Delphi 2009.
  • Remedy: Adjust your code so it does not conflict with the TObject class members. Override TObject method where is possible or rename/reintroduce identifier in other case.

Unit changes

Daemonapp unit moved to new fcl-extras package

  • Old behaviour: unit Daemonapp resided in package fcl-base.
  • New behaviour: unit Daemonapp resides in package fcl-extra.
  • Effect: On OSes that have a package for every directory in packages, daemonapp seems to be missing if fcl-extra is not installed.
  • Reason: Breaking dependency cycles in the FCL, most notably on Windows.
  • Remedy: On operating systems where a package in packages/ corresponds to a separate package to install (like on Debian), an additional package corresponding to fcl-extra must be installed

DOM unit: no longer uses avl_tree for node search optimization

Note: This is an implementation-only change. Nevertheless, it's worth documenting and explanation.

  • Old behaviour: each 'parent' DOM node (Elements and Attributes, in the first place) had an associated TAvgLvlTree object, that was used as child node node index, and intended to speed up the TDOMNode.FindNode method by replacing linear search by binary search.
  • New behaviour: the TAvgLvlTree is no longer used, and TDOMNode.FindNode method uses a linear search.
  • Effect: The XML parsing speed has increased about twice, and average memory usage of a DOM document has decreased by about 75%. The performance of the TDOMNode.FindNode method, and methods of TXMLConfig class (xmlcfg unit), may become lower in some scenarios.
  • Reason: The optimization offered by child node indexing was applicable only to one particular usage case: XML config files, which require all node names within a single parent to be unique. The memory/performance penalty caused for all other usage cases has become way too big.
  • Remedy: If you experience slowdown of your code using TXMLConfig class from xmlcfg unit, consider replacing xmlcfg with a newer xmlconf unit. Then, use OpenKey and CloseKey methods to limit the amount of searching in the DOM.
  • Example:

<delphi> // the code like this uses xmlcfg; ... begin

 config.WriteString('the/very/long/path/value1', string1);
 config.WriteString('the/very/long/path/value2', string2);
 config.WriteString('the/very/long/path/value3', string3);
 ...

end;

// can be changed to: uses xmlconf; ... begin

 config.OpenKey('the/very/long/path');
 config.WriteString('value1', string1);
 config.WriteString('value2', string2);
 config.WriteString('value3', string3);
 config.CloseKey;

end; // in this example, 'the/very/long/path' will be searched only once rather than 3 times, // which will improve the performance. </delphi>