User Changes Trunk

From Lazarus wiki
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

Static keyword is enabled without switches and directives

  • Old behaviour: To allow use of 'static' keyword it was needed to pass the -St switch to the compiler or use {$STATIC} directive.
  • New behaviour: Usage of 'static'keyword is now enabled without switches or directives.
  • Effect: -St switch is deprecated and {$STATIC} directive does not exists anymore.
  • Reason: There is no reasons in the switch/directives after compiler restrictions were added to reject fields after methods in the class/object declaration. And moreover recent versions of delphi implements 'static' class method support.
  • Remedy: Adjust your build scripts and code to remove -St and {$STATIC} from them.

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.

Sizes of sets in TP/Delphi mode

  • Old behaviour: {$packset fixed} was the default for all language modes. This packs a set of up to 32 elements in 4 bytes, and all other sets in 32 bytes.
  • New behaviour: The default in TP/Delphi mode is now {$packset 1}
  • Effect: In those language modes the size of sets with 1..8 elements will now be 1 byte, and the size of sets with 9..16 elements will be two bytes. Sets with 17..32 elements will remain 4 bytes, but after that every additional 8 elements the size will increase by 1 byte up to 249..256 elements, which will result in a set of 32 bytes.
  • Reason: TP/Delphi compatibility.
  • Remedy: If you have code written in TP/Delphi mode that depends on the old packset setting, add {$packset fixed} to the source (after setting the syntax mode to Delphi/TP, since the mode switching changes the packset setting). This is backward compatible with at least FPC 2.2.4 and later.

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>

MacOSAll unit: changed parameter types

  • Old behavior: The old headers were a combination of the original Apple-written Pascal headers and translated C headers. The Pascal headers were written for compilers that did not support unsigned 32 bit types, and in many cases used "var" parameters where the actual parameter was an array in C.
  • New behaviour: The new headers have all been translated from the latest Mac OS X 10.6 headers for 64 bit and iPhoneOS support. As a result, several parameters types have changed.
  • Remedy: Either adjust your code, or file bug reports asking to revert to the old signatures (especially for deprecated routines that won't be updated in the future anymore anyway, this should be no problem).
  • Changes:
    • Many cases where signed parameters were turned into unsigned parameters and vice versa, too many to list (due to differences between the classic Pascal headers and the new C headers)
    • ATSFontFindFromContainer: ioArray var -> ptr because array
    • ATSFontGetFileSpecification: oFile FSSpec -> ATSFSSpec (was translation error?)
    • CFNetworkCopyProxiesForAutoConfigurationScript: got extra CFErrorRef para
    • CMGetDeviceFactoryProfiles: defaultProfID var -> ptr, because can be nil
    • CMIterateColorDevices: seed and count var -> ptr, because can be nil
    • CMIterateDeviceProfiles: seed and count var -> ptr, because can be nil
    • CMSetDeviceProfiles: profileScope and deviceProfiles const -> ptr, because can be nil
    • ConvertFromUnicodeToScriptCodeRun: oScriptCodeRuns var -> ptr because array
    • ConvertFromUnicodeToTextRun: oEncodingRuns var -> ptr because array
    • CreateUnicodeToTextRunInfo: iUnicodeMappings var -> ptr because array
    • DCMCreateFieldInfoRecord: findMethods var -> ptr because array
    • DCMGetFieldFindMethods: findMethods var -> ptr because array
    • GetIconRefFromFileInfo: outlabel var -> ptr because can be nil
    • HIImageViewCreate: last parameter ControlRef -> HIViewRef
    • HIViewNewTrackingArea: outRef var -> ptr because can be nil in 10.5+
    • LAGetEnvironmentList: environmentList var -> ptr because array
    • LAListAvailableDictionaries: dictionaryList and opened var -> ptr because array
    • LSGetApplicationForURL: outAppRef and outAppURL var -> ptr because can be nil
    • LocaleOperationGetLocales: localeVariantList var -> ptr because can be nil
    • MPWaitOnQueue: param1-3 value -> var because "void **" in C
    • QTVRSetBackBufferImagingProc: areasOfInterest var -> ptr because array
    • QueryUnicodeMappings: oReturnedMappings var -> ptr because array
    • TECConvertTextToMultipleEncodings: outEncodingsBuffer var -> ptr because array
    • TECFlushMultipleEncodings: outEncodingsBuffer var -> ptr because array
    • TECSniffTextEncoding: numErrsArray and numFeaturesArray var -> ptr because array
    • FSCreateResFile: catalogInfo const -> ptr because can be nil