User Changes Trunk

From Lazarus wiki
Revision as of 16:13, 10 May 2013 by HowardPC (talk | contribs) (typo corrected)


About this page

Listed below are intentional changes made to the FPC compiler (trunk) since the previous release, with 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 can be found here.

All systems

Implementation changes

Exception type for object reference checking changed

  • Old behaviour: When object reference checking (-CR or {$OBJECTCHECKS ON}) is enabled and the unit SysUtils is used then an exception of class Exception with localizeable message Unknown runtime error 210 is created.
  • New behaviour: Now an exception of class EObjectCheck with localizeable message Object reference is Nil is created.
  • Reason: All other runtime errors in the 2xx range have appropriate exception types, so it is only natural to have an explicit type for runtime error 210 as well.
  • Remedy: If your code previously checked an exception for the message Unknown runtime error 210 you should now check for the exception class EObjectCheck.

Literal storage memory has been made read-only

  • Old behaviour: read-only data segments were de-facto not supported, all data could be modified at runtime even if it was not intended for modification (except in some cases on Darwin). This could cause nasty side-effects, e.g the following code:
uses sysutils;
   s: ansistring;
   s := 'ansi string';
   s := 'ansi string';

would modify the content of data segment and print

  • New behaviour: Data that is not intended to be modified at runtime is put into read-only segment. This includes literal constants used in expressions and typed constants declared in {$J-} state. The code which modifies such data, like the example above, will now crash.
  • Reason: This is consistent with the way other compilers, including Delphi, work. Keeping as much as possible data read-only improves loading speed of programs because read-only pages can be mapped directly on executable file, and also improves security of programs.
  • Remedy: Depends on the code. In the example above, it is sufficient to call UniqueString(s) before AnsiStrUpper

UNICODE is defined depending on the mode switch

  • Old behaviour: When the modeswitch was changed the definition of UNICODE was not changed.
  • New behaviour: If the modeswitch is changed to delphiunicode the UNICODE will be defined otherwise it will be undefined.
  • Reason: In Delphi 2009 and newer the type String is defined as UnicodeString and UNICODE is defined there by default as well. For improved Delphi compatibility UNICODE will be automatically defined if the String type is set to be equal to UnicodeString.
  • Remedy: Don't rely on checks for UNICODE before the mode switches. Also compile time checks for UNICODE that appear after a modeswitch like objfpc or delphi will no longer be evaluated to true.

RTTI changes

RTTI for Pointers and Class References

  • Old behavior: Pointers and Class References had tkUnknown RTTI.
  • New behavior: Pointers now have tkPointer and Class References tkClassRef RTTI types. They now contain a reference to a type they point to.
  • Reason: Both user requests and Delphi compatibility.
  • Remedy: TTypeKind enumeration has more members than before. Adjust your code which depends on TTypeKind.

RTTI for AnsiStrings

  • Old behavior: AnsiString RTTI did not have CodePage information.
  • New behavior: New CodePage member is added for tkAString type.
  • Reason: Requires for serializing/deserializing of AnsiString published properties. Delphi compatibility.
  • Remedy: not known

RTTI for Arrays

  • Old behavior: tkArray had no member in TTypeData record but internally compiler stored the next members: first dimension size, first dimension element count and first dimension element type. So for 2 dimension array element type was array for the second dimension.
  • New behavior: tkArray now has TArrayTypeData structure in TTypeData. It has the next members: total array size including all dimensions, total element count, last dimension element type, number of dimensions, type information for each dimension range.
  • Reason: more informative RTTI. Delphi compatibility.
  • Remedy: If your code internally used old RTTI array information you will need to adopt it.

RTTI for Records

  • Old behavior: Records RTTI stored field Offsets as 32bit integers.
  • New behavior: Records RTTI stores field Offsets as platform dependent integers (the same size as pointers).
  • Reason: Internally compiler stored Offsets as platform dependent integers. Delphi compatibility.
  • Remedy: You need to adjust your code if you used field offsets of record RTTI. This is also true if you manually processed vInitTable field of class VMT.

RTTI for Procedural Variables

  • Old behavior: tkProcVar had no member in TTypeData record and compiler stored no info the this type.
  • New behavior: tkProcVar now has TProcedureSignature structure in TTypeData which contains information about calling convention, result type and parameters information.
  • Reason: User request. More informative RTTI. Delphi compatibility.
  • Remedy: not known

Use example

program RTTIInfo;

{$mode objfpc}{$H+}

  CP866String = type AnsiString(866);
  TProc = procedure(var A: Integer; S: String); stdcall;
  TColor = (red, green, blue);
  TArr = array[TColor,0..3] of Integer;
  PArr = ^TArr;

procedure DescribeProcedure(Info: PTypeInfo);
  ParamFlagToStr: array[TParamFlag] of AnsiString = (
  CallConvToStr: array[TCallConv] of AnsiString = (
  Data: PTypeData;
  Param: PProcedureParam;
  ParamFlag: TParamFlag;
  I: Integer;
  Res, S, TypeName: String;
  if Info^.Kind <> tkProcedure then
  Data := GetTypeData(Info);
  if Data^.ProcSig.CC <> ccStdCall then
  if Data^.ProcSig.ResultType <> nil then
    Res := 'function ' + Info^.Name;
    TypeName := ': ' + Data^.ProcSig.ResultType^.Name;
    Res := 'procedure ' + Info^.Name;
    TypeName := '';
  if Data^.ProcSig.ParamCount > 0 then
    Res := Res + '(';
    for I := 0 to Data^.ProcSig.ParamCount - 1 do
      Param := Data^.ProcSig.GetParam(I);
      S := '';
      for ParamFlag in TParamFlags(Param^.Flags) do
        S := S + ParamFlagToStr[ParamFlag] + ' ';
      S := S + Param^.Name + ': ' + Param^.ParamType^.Name;
      if I > 0 then
        Res := Res + '; ';
      Res := Res + S;
    Res := Res + ')';
  Res := Res + TypeName + '; ' + CallConvToStr[Data^.ProcSig.CC] + ';';

procedure DescribeAnsiString(Info: PTypeInfo);
  Data: PTypeData;
  if Info^.Kind <> tkAString then
  Data := GetTypeData(Info);
  if Data^.CodePage = 0 then
    WriteLn('type AnsiString(',Data^.CodePage,');');

procedure DescribeArray(Info: PTypeInfo);
  Data: PTypeData;
  Res: String;
  I: Integer;
  if Info^.Kind <> tkArray then
  Data := GetTypeData(Info);
  Res := 'array[';
  for I := 0 to Data^.ArrayData.DimCount - 1 do
    if I > 0 then
      Res := Res + ', ';
    Res := Res + Data^.ArrayData.Dims[I]^.Name;
  Res := Res + '] of ' + Data^.ArrayData.ElType^.Name + ';';

procedure DescribePointer(Info: PTypeInfo);
  Data: PTypeData;
  if Info^.Kind <> tkPointer then
  Data := GetTypeData(Info);
  if Data^.RefType = nil then
    WriteLn('^', Data^.RefType^.Name, ';');


Unit changes

TBookmark TBookmarkstr and TDataset.Bookmark change to Delphi2009+ compatible definitions

  • Old behaviour: TDataset.Bookmark was of type TBookmarkstr, TBookmarkstr=string, Tbookmark=pointer
  • New behaviour: TDataset.Bookmark is of type TBookmark, TBookmarkstr=ansistring, TBookmark=TBytes. TBookmarkstr will trigger a deprecated warning.
  • Reason: D2009+ compatibility, where probably the fact that string became a 2-byte encoding was the trigger.
  • Remedy: Adjust typing in descendents and using code accordingly.

FileNameCaseSensitive and FileNameCasePreserving in unit System

  • Old behaviour: There was only one constant (FileNameCaseSensitive) which signalized behaviour of the respective target platform with regard to the case in filenames. This was often set to true also on platforms not really treating filenames in case sensitive manner (e.g. Win32 and Win64).
  • New behaviour: FileNameCaseSensitive is set to true only on platforms which really treat filenames in case sensitive manner and FileNameCasePreserving constant is added to unit system of all platforms to signalize whether the case in filenames supplied when creating or renaming them is preserved or not. This might possibly break existing user code relying on the previous (sometimes incorrect) value of FileNameCaseSensitive.
  • Reason: In reality, there are two distinct types of behaviour. If a platform is case sensitive, searching for file "a" will never result in finding file "A" whereas case insensitive platform will happily return "A" if such a file is found on the disk. If a platform is case preserving, it will store file "a" as "a" on disk whereas case non-preserving platform may convert the filenames to uppercase before storing them on disk (i.e. file "a" is in reality stored as "A"). Case non-preserving platforms are never case sensitive, but case preserving platforms may or may not be case sensitive at the same time.
  • Remedy: Review your existing code using FileNameCaseSensitive, check which of the two properties described above fit the particular purpose in your case and change to FileNameCasePreserving where appropriate.

Some longtime deprecated functions in unit Unix have been removed.

  • Old behaviour: Unix.(f)statfs, and Unix.fsync symbols existed in unit Unix
  • New behaviour: Unix.(f)statfs, and Unix.fsync were removed
  • Reason: These were helper functions and leftovers from the 1.0.x->2.0.0 conversion, deprecated since 2007. Shell had non standarized conventions
  • Remedy: All but shell: use the same functions with a "fp" prefix. Shell: use fpsystem. If you checked the return value for other values than -1, a modification of the errorchecking might be necessary. Refer to your *nix documention, or have a look at the transformfpsystemtoshell function in tests/util/redir.pp in the FPC sources to see what a quick fix looks like.

statfs has been renamed to fpstatfs

  • Old behaviour: One overload of fpstatfs was not renamed from statfs to fpstatfs (around 2.4.0)
  • New behaviour: The function has been renamed.
  • Reason: Should have been done in 2.4.0 to begin with, but was postponed several times to coincide with a major version change.
  • Remedy: Use fpstatfs

RTLeventsync has been removed

  • Old behaviour: The thread manager record contained an rtleventsync field, and the RTL had an RTLeventsync routine. No functionality for this routine was implemented in the FPC-supplied thread manager for any platform.
  • New behaviour: The field and routine have been removed.
  • Reason: The functionality was not available on any platform by default, and we're not aware of any third party thread manager that implemented them or third party code that relied on it. Additionally, the routine was documented as "Obsolete. Don't use.", without any explanation of what it was supposed to do.
  • Remedy: Remove any such calls from your code.

TODBCConnection (odbcconn) No longer autocommit

  • Old behaviour: Autocommit was enabled: Every change was committed to the database at once.
  • New behaviour: Changes must be committed explicitly using Transaction.Commit
  • Reason: Transactions are useless if everything is autocommitted: in particular; rollback is not possible.
  • Remedy: You can enable autocommit by specifying AUTOCOMMIT=1 in the params of TODBCConnection.

FPCanvas Strikethough property spelling fixed to StrikeThrough

  • Old behaviour: Fonts had a Striketrough property which is a typo.
  • New behaviour: The property has been changed to Strikethrough.
  • Reason: Spelling fix.
  • Remedy: Please rename property calls in your code. FPC 2.6.2 contains both versions so there is a window for adaptation.

TVersionInfo (fileinfo unit) re-implemented in a platform independent way

  • Old behaviour: GetVersionSetting method would read file information.
  • New behaviour: The ReadFileInfo call will read the information. The global GetProgramVersion call will extract the program major/minor/revision/build version in 1 single call.
  • Reason: The unit now uses FPC resources on all platforms, and can now be used to read external resources.
  • Remedy: Use the ReadFileInfo call to get the version information. Add relevant units for desired resource support to your uses clause; e.g. if you need to read Windows .exe file info, add winpeimagereader

TDBF unit deprecation removed

  • Old behaviour: the TDBF units were marked deprecated because the original maintainer of the upstream project stopped maintenance. However, the unit remained in fcl-db and patches were still accepted.
  • New behaviour: the deprecation warning is removed. There is a new upstream project maintainer and FPC database devs support this unit again. Note: there is a known problem: TDBF will not work on ARM processors due to alignment issues ( This will only be fixed if a patch is provided, and proven to not produce regressions (e.g. by tests in the FPC db test framework)
  • Remedy: N/A

shlobj symbols removed from unit Windows

  • Old behaviour: When unit windows was splitted between unit windows and shlobj, not all shlobj symbols were removed from Windows. Currently these are being deprecated, and will be removed in next major version.
  • New behaviour: shlobj symbols won't be in Windows, code relying on that will fail to compile if it doesn't import shlobj
  • Reason: shlobj and windows versions were not compatible and lead to errors.
  • Remedy: put shlobj in your uses, if not there already.

Language Changes

Variant overload preference for string types

  • Old behaviour: Preference for string types was (from better to worse): ShortString, AnsiString, WideString, UnicodeString
  • New behaviour: Preference for string types now (from better to worse): WideString, UnicodeString, AnsiString, ShortString
  • Reason: Unicode characters and codepage information will not lose during the conversion and unicode Delphi compatibility.
  • Remedy: Use explicit conversion (e.g. ShortString(V)) if it is needed to pass variant to routine with paticular string type argument.

Default values in implementation but not in interface/forward declaration

  • Old behaviour: The implementation of a routine could declare default values even if the interface declaration did not have any.
  • New behaviour: Default values, if any, must be specified in the interface. They can be repeated in the implementation, but that is not required (just like it was not in the past).
  • Reason: Default parameters specified only in the implementation are not, and cannot, be propagated to the interface since a unit's interface can be used before the implementation has been parsed (see, Delphi compatibility.
  • Remedy: Always specify default parameter values (also) in the interface/forward declaration of a routine.

Default values are now properly typechecked

  • Old behaviour: The compiler did not detect default values for parameters of which the type did not in any way correspond to the parameter type.
  • New behaviour: The compiler now properly checks whether the type of the constant matches the parameter's type when parsing default values.
  • Reason: Proper type checking is one of the fundamental properties of the Pascal language; Delphi compatibility.
  • Remedy: Add a typecast around default values that now result in compiler errors, or correct the type of such parameters.

Recursive parameterless function calls in MacPas mode

  • Old behaviour: When using the name of a function inside its own body on the right hand side of an expression, the compiler treated this as a read of the last value assigned to the function result in MacPas mode.
  • New behaviour: The compiler will now treat such occurrences of the function name as recursive function calls in MacPas mode.
  • Reason: Compatibility with Mac Pascal compilers.
  • Remedy: If you wish to read the current function result value, compile the code with {$modeswitch result}, after which you can use the result alias for that value. Note that the use of this mode switch can also result in different behaviour compared to traditional Mac Pascal compilers.

"strict protected" visibility modifier

  • Old behaviour: strict protected did not correctly limit the visibility of symbols declared in different units.
  • New behaviour: strict protected symbols can now only be accessed from descendent classes, regardless of where they are defined.
  • Reason: Fix behaviour to conform to specification/documentation, Delphi compatibility.
  • Remedy: Use protected or public if less strict accessibility checks are desired.

support for type helpers added

  • Old behaviour: In modes ObjFPC and MacPas it was possible to declare a unique type of a type helper.
  • New behaviour: The compiler now interprets the keyword helper as a helper type if it immediately follows the type keyword (but only if the mode is ObjFPC or MacPas or the mode switch Class is set).
  • Example:
{$mode objfpc}
  helper = LongInt;

  otherhelper = type helper;

The above code will no longer compile.

  • Reason: type helper is a more logical way to declare helpers for primitive types than Delphi's record helper is.
  • Remedy: Escape the keyword helper using a &. E.g.:
{$mode objfpc}
  helper = LongInt;

  otherhelper = type &helper;

"strict protected" and "protected" visibility modifier in extended records

  • Old behaviour: strict protected and protected could be used used in extended records.
  • New behaviour: strict protected and protected are no longer allowed in extended records.
  • Reason: The only difference between (strict) protected and (strict) private is that the former allows you to access members of a parent class or object. As records don't support inheritence it makes no sense to support (strict) protected in them. This is also Delphi-compatible.
  • Remedy: Use private instead of protected and strict private instead of strict protected.

"static" directive on non-class methods

  • Old behaviour: It was possible to use the static on normal, non-class methods
  • New behaviour: The compiler now generates an error if static is used on normal, non-class methods (except in object types)
  • Reason: It is only correct to leave out the Self parameter if it is a class method. This is also Delphi compatible.
  • Remedy: Prepend the class keyword to the method.

"static" directive on class operators

  • Old behaviour: It was possible to use the static on class operators.
  • New behaviour: The compiler now generates an error if static is used on class operators.
  • Reason: Class operators are by definition static, thus the static would be redundant. This is also Delphi compatible.
  • Remedy: Remove the static keyword from class operators.

Classes implementing forward-declared interfaces

  • Old behaviour: It was possible to declare classes as implementing a forward-declared interface.
  • New behaviour: Classes can no longer implement forward-declared interfaces.
  • Reason: This occasionally caused crashes, the compiler did not check in such a case whether the class actually implemented the methods of that interface. Recent versions of Delphi also reject such constructs.
  • Remedy: If there is a cyclic dependency between a class and an interface, use a forward declaration for the class instead.

Using the function name as alias for loading its current result value in MacPas mode

  • Old behaviour: Inside a function the name of the function could be used on the right hand side (RHS) of an expression in order to refer to the current value of the function result.
  • New behaviour: Using the name of a function on the RHS of an expression inside that function's body now always results in a recursive function call.
  • Reason: The old behaviour existed because under some circumstances CodeWarrior behaved that way. Under other circumstances it however behaves according to the new rule and there appears to be no definition available of when it does what. Since it is easier to fix a compilation error than to find out where an intended recursive function call is not doing anything, we opted to change the behaviour.
  • Remedy: Either use a temporary local variable to hold the function result if you want to reuse it on the RHS of other expressions, or add {$modeswitch result} and use the result pseudo-variable as an alias for the function result.

Unix platforms

cthreads: critical sections and recursive mutex support

  • Old behaviour: If the cthreads unit thread manager was used on a platform without recursive mutex support, critical sections were non-reentrant.
  • New behaviour: Initialising a critical section under the above circumstances will now result in a run time error.
  • Reason: One of the basic properties of (Delphi/Windows-compatible) critical sections is that they are reentrant, and that is how they are generally used in Pascal code.
  • Remedy: Use an RTLEvent instead if reentrancy is not required.

Darwin/i386 and iPhoneSim/i386

Location of certain function result types

  • Old behaviour: Small records and method pointers were always returned according to the official ABI.
  • New behaviour: When a calling convention other than cdecl, cppdecl or mwpascal is used, the same convention as on other platforms is now used.
  • Reason: Better compatibility with assembler code written for other platforms.
  • Remedy: Update your assembler code, or better: if possible, convert it to Pascal.

All Darwin/Mac OS X/iOS

MacOSAll unit: changed parameter and opaque types

  • Change: The headers have been updated to the Mac OS X 10.8 SDK, and in this process a number of signatures have been changed/corrected, and several opaque types have been changed from ^SInt32 into pointers to different/incompatible empty records.
  • Reason: The reasons for the signature changes are detailed below. The opaque types have been made incompatible so that the compiler can give error messages when trying to use one opaque type instead of another (e.g., in the past the compiler did not complain when passing a ControlRef to a routine that expected a WindowPtr).
  • Remedy: Adjust your code to conform to the new signatures. Regarding the opaque types, that means that these types are no longer assignment-compatible. Some of the more prominent ones that may affect existing, correct, code are HIObject and ControlRef=HIViewRef. This may require adding typecasts to keep code compiling (the same typecasts are required in C)
  • Changes: (apart from the opaque type changes)
    • CGGLContextCreate : fixed first parameter (was "var", now is value parameter)
    • CFHostGetAddressing: var hasBeenResolved: boolean -> booleanptr because can be nil
    • CFHostGetNames: var hasBeenResolved: boolean -> booleanptr because can be nil
    • ColorSyncIterateInstalledProfiles: var seed: UInt32 -> UInt32Ptr because can be nil
    • AudioStreamGetPropertyInfo: outSize and outWritable changed to pointer because can be nil
    • cblas (several var-parametes changed to pointers because they represent arrays):
      • cblas_sswap, cblas_dswap: X, Y
      • cblas_scopy, cblas_dcopy: Y
      • cblas_saxpy, cblas_daxpy: Y
      • catlas_saxpby, catlas_daxpby: Y
      • catlas_sset, catlas_dset: X
      • cblas_sscal, cblas_dscal: X
      • cblas_sgemv, cblas_dgemv: X
      • cblas_strmv, cblas_dtrmv: X
      • cblas_stbmv, cblas_dtbmv: X
      • cblas_stpmv, cblas_dtpmv: Ap, X
      • cblas_strsv, cblas_dtrsv: X
      • cblas_stbsv, cblas_dtbsv: X
      • cblas_stpsv, cblas_dtpsv: Ap, X
      • cblas_ssymv, cblas_dsymv: X
      • cblas_ssbmv, cblas_dsbmv: Y
      • cblas_sspmv, cblas_dspmv: Ap, Y
      • cblas_sger, cblas_dger: A
      • cblas_ssyr, cblas_dsyr: A
      • cblas_sspr, cblas_dspr: Ap
      • cblas_ssyr2, cblas_dsyr2: A
      • cblas_sspr2, cblas_dspr2: A
      • cblas_sgemm, cblas_sgemm: C
      • cblas_ssymm, cblas_Dsymm: C
      • cblas_ssyrk, cblas_dsyrk: C
      • cblas_ssyr2k, cblas_dsyr2k: C
      • cblas_strmm, cblas_dtrmm: B
      • cblas_strsm, cblas_strsm: B
    • vBLAS (idem)
      • SDOT: X, Y
      • SNRM2: X
      • SASUM: X
      • ISAMAX: X
      • SSWAP: X, Y
      • SCOPY: X, Y
      • SAXPY: X, Y
      • SROT: X, Y
      • SSCAL: X
      • SGEMV, A, X, Y
      • SGEMM: A, B, C
    • vDSP (idem)
      • vDSP_sve_svesq, vDSP_sve_svesqD: __vDSP_A
      • vDSP_normalize, vDSP_normalizeD: __vDSP_A, __vDSP_C


Exception handling has been changed to be ABI-conformant

  • Old behaviour: Exceptions were handled using platform-independent mechanism based on SetJmp/LongJmp.
  • New behaviour: Exceptions are handled using OS-provided means. The most important differences from generic handling are as follows:
    • Every executable contains a .pdata section describing layout of function stack frames. This data is used to perform stack back-tracing. As a consequence, the backtraces generated when exception occurs are no longer dependent of code optimization settings. However, they may be different from ones produced by gdb.
    • GNU binutils have troubles creating executables with .pdata sections. In particular, ld version < 2.22 crashes at such executables, and using GNU as together with internal linker will strip all .pdata, resulting in a non-working executable.
    • An exception is handled in two phases. First phase determines the target frame (i.e. the 'except' statement that will handle the exception), the second phase does actual stack unwinding and executing code in 'finally' statements. In contrast, the generic mechanism is single-phase: it starts unwinding immediately and proceeds until an 'except' statement handles the exception or the stack runs out.
  • Reason: Multiple compatibility issues with Windows and third-party DLLs (see and related issues)
  • Remedy: No changes are necessary unless your code relies on specific exception handling details. Build programs using FPC's internal assembler and linker, do not use GNU binutils. The entire feature can be disabled by cycling the compiler with OPT=-dDISABLE_WIN64_SEH in command line.


Define UNICODE was changed to FPC_OS_UNICODE

  • Old behaviour: For arm-wince and i386-wince UNICODE was defined by default.
  • New behaviour: For arm-wince and i386-wince FPC_OS_UNICODE is defined by default.
  • Reason: For upcoming support for setting String to UnicodeString the define UNICODE now is defined if the type String is currently defined as UnicodeString. This is also in so far Delphi compatible that from Delphi 2009 on UNICODE is defined as well.
  • Remedy: Check for FPC_OS_UNICODE to decide whether the OS only provides a Unicode API (in the sense of Wide- or UnicodeString) and use UNICODE to decide whether the type String is currently defined as UnicodeString or not.


Stabs support has been disabled for 64 bit targets

  • Old behaviour: While the default debug information format for 64 bit targets was DWARF (except for AIX, where it's Stabx), it was possible to switch it to Stabs via the -gs command line parameter.
  • New behaviour: Only the DWARF debug format is still supported on 64 bit targets (except for AIX, where Stabx is used).
  • Reason: Stabs is not well-defined for 64 bit targets, nor well-supported by gdb on those same targets. This can lead to problems
  • Remedy: Do not use -gs when compiling for 64 bit targets. If you do so anyway, the compiler will display a warning and keep the previously set (supported) debug format.

See also