# User Changes Trunk

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

### Implementation Changes

#### Dynamic array parameters are passed like pointers

• Old behaviour: When using the default calling convention, dynamic array parameters were passed on the stack.
• New behaviour: When using the default calling convention, dynamic array parameters are now passed like a pointer (which may be in a register).
• Reason: Delphi compatibility, ensuring that SetPointerProp can be used with dynamic arrays.
• Remedy: Adjust pure assembler routines that have dynamic array parameters.
• svn: 30870, 30878, 31622

#### VMT Interface table uses private variable FPC_EMPTYINTF

• Old behaviour: The vIntfTable field has three possible values:
• Nil if the class doesn't implement any interface (but an ancestor might)
• A pointer to an interface table (with count <> 0) if the class implements any interface
• A pointer to FPC_EMPTYINTF if neither the class itself nor any ancestor implements an interface
• New behaviour: The vIntfTable field has two possible values:
• Nil if neither the class nor any ancestor implements an interface
• A pointer to an interface table in any other case
• Reason: FPC_EMPTYINTF had to be removed due to dynamic packages support on PE-based systems
• Remedy: Adjust code accordingly
• svn: 34087

### Language Changes

#### Visibility of generic type parameters

• Old behaviour: Type parameters of generics had public visibility.
• New behaviour: Type parameters of generics now have strict private visibility.
• Reason: With the previous visibility it was possible to create code that leads to infinite loops during compilation or other hard to debug errors. In addition there is no real possibility to work around this issue (for an example see this bug report). Also the fix is Delphi compatible.
• Remedy: Declare a type alias for the type parameter with the desired visibility.
• Example: In the following example T is declared as strict private, while TAlias is declared as public and thus can be used as before the change.
type
generic TTest<T> = class
public type
TAlias = T;
end;

#### Parsing of specialize has been changed

• Old behaviour: specialize was used to initialize a specialization and was followed by a type name that might contain a unit name and parent types.
• New behaviour: specialize is now considered part of the specialized type, just as generic is. This means that unit names and parent types need to be used before the part containing the specialize.
• Reason: This allows for a more logical usage of specialize in context with nested types (especially if multiple specializations are involved) and more importantly generic functions and methods.
• Remedy: Put the specialize directly in front of the type which needs to be specialized.

### RTTI changes

#### RTTI for Interfaces (published property count)

• Old behavior: The property RTTI data of an interface (both COM and Corba) immediately followed the TTypeData record without any count.
• New behavior: Before the property RTTI data is now a Word count field that specifies the amount of properties
• Reason: Both user request and usability.
• Remedy: Adjust pointer offsets accessing the property data accordingly.

#### RTTI for COM Interfaces (IID String)

• Old behavior: COM interfaces contain an undocumented IIDStr between the unit name IntfUnit and the property data.
• New behavior: The undocumented field has been removed.
• Reason: The IID of COM interfaces can always be represented as GUID, thus the undocumented IIDStr field is redundant.
• Remedy: Use the GUID field and convert that to a String.

#### RTTI Binary format change

• Old behavior: References to other types are designated by PTypeInfo.
• New behavior: References to other types are designated by PPTypeInfo.
• Reason: While the change in the binary format is Delphi-compatible the reason for this is the introduction of the support for dynamic packages and the rules of the PE file format (Windows) that need to be played by.
• Remedy: If you don't access the binary data directly then there should be no change necessary. Otherwise you need to add in a further derefentiation.
• Note:
• The PPTypeInfo value itself will be Nil if there's no reference, not the PTypeInfo reference stored in it.
• This does not apply to TObject.ClassInfo which still returns a PTypeInfo

#### RTTI for Corba Interfaces (IID String)

• Old behavior: IIDStr is a field of TTypeData.
• New behavior: IIDStr is a property of TTypeData.
• Reason: The compiler assumes the RawIntfUnit field immediately preceding IIDStr is a ShortString of length 255 despite the corresponding binary data only having the length of the string it contains, thus accessing incorrect data.
• Remedy: If you merely accessed the data nothing changes, but the data following IIDStr needs to be accessed differently as RawIntfUnit is the last visible field.
• svn: 35026

#### Reference to Record Init Information

• Old behavior: Field RecSize follows directly after start of TTypeData record.
• New behavior: Field RecSize is preceeded by pointer field RecInitInfo which points to a TTypeInfo for the record init information (the TTypeInfo for that is followed by TRecInitData).
• Reason: With the record init information one can more quickly decide whehther a record needs to be classed as managed or not which is among others useful for the IsManaged() function of the Rtti unit.
• Remedy: If you relied on the relative position of RecSize in TTypeData you'll need to adjust your code.
• Note: The TRecInitData shares its first three fields with a record's TTypeData with the difference that the pointer to the init information is Nil.
• svn: 35125, 35134

#### TOrdType extended

• Old behavior: TOrdType contains entries for 8-, 16- and 32-bit widths.
• New behavior: TOrdType contains entries for 8-, 16-, 32- and 64-bit widths.
• Reason: Without extending TOrdType it wouldn't be possible to correctly represent Boolean type of 64-bit width as they couldn't be differentiated from ordinary Integers with a minimum of 0 and maximum of 1 for the Pascal Boolean type and minium of -1 and maximum of 0 for the Windows Boolean type.
• Remedy: Adjust arrays that have TOrdType as index.
• svn: 35135

#### New OrdType field for tkInt64 and tkQWord

• Old behavior: MinInt64Value and MinQWordValue follow directly after start of TTypeData record.
• New behavior: MinInt64Value and MinQWordValue are preceeded by a OrdType field which explicitely designates them as otSQWord or otUQword respectively.
• Reason: To allow for 64-bit Booleans to be represented correctly the tkInt64 and tkQWord branches of TTypeData had to become part of the tkInteger (aka Ordinal) branch and thus they gained the OrdType field.
• Remedy: If your code relied on the relative position of MinInt64Value and MinQWordValue towards the start of the TTypeData record it needs to be adjusted.
• svn: 35135

#### First field of TProcedureParam changed

• Old behavior: First field of TProcedureParam is called Flags and has type Byte.
• New behavior: First field of TProcedureParam is called ParamFlags and has type TParamFlags and there is a property called Flags of type Byte.
• Reason: Since TParamFlags is a set it might grow beyond the size of a Byte if more values are added to TParamFlag.
• Remedy: Most code should be able to use the backwards and Delphi compatible Flags property (at least if it only wants to check TParamFlag values of which the ordinal value is less than 8) other code should switch to using ParamFlags.
• svn: 35174

#### TParamFlag extended for constref

• Old behavior: TParamFlag has no entry for constref parameters.
• New behavior: TParamFlag has entry pfConstRef for constref parameters.
• Reason: To correctly detect constref parameters they need to be marked accordingly.
• Remedy: Adjust code that relies on the amount of elements contained in TParamFlag (e.g. case-statements or array indices).
• svn: 35175

#### Ranges of Boolean types adjusted

• Old behavior: ByteBool, WordBool and LongBool have a range of 0..-1.
• New behavior: ByteBool, WordBool and LongBool have a range of Low(LongInt) to High(LongInt).
• Reason: The old behavior simply cut the Low(Int64) and High(Int64) values used as ranges for the Boolean types which was wrong. That the ranges are not size dependant is Delphi compatible.
• Remedy: Adjust code that might have relied on the range being invalid.
• svn: 35184

#### OrdType of Boolean64 and QWordBool adjusted

• Old behavior: Boolean64 has OrdType otUByte and QWordBool has OrdType otSByte and their ranges are in MinValue and MaxValue.
• New behavior: Boolean64 has OrdType otUQWord with the range being in MinQWordValue and MaxQWordValue and QWordBool has OrdType otSQWord with the range being in MinInt64Value and MaxInt64Value.
• Reason: Both types have a size of 64-bit thus using a smaller size is incorrect.
• Remedy: Use the correct fields to retrieve the range boundaries of the types.
• svn: 35185

#### All Boolean types have TypeKind tkBool

• Old behavior: Boolean has TypeKind tkBool while the other Boolean types (Boolean16, Boolean32, Boolean64, ByteBool, WordBool, LongBool, QWordBool) have TypeKind tkInteger.
• New behavior: Boolean, Boolean16, Boolean32, Boolean64, ByteBool, WordBool, LongBool and QWordBool have TypeKind tkBool.
• Reason: Consistency and possibility to differentiate ordinary subranges from the real Boolean types.
• Remedy: Check for TypeKind tkBool instead of some "magic" to detect Boolean types.
• Note: Since fields can only appear once in a record the tkBool branch of TTypeData was not adjusted. This has no practical consequences however as all fields of a variant record are always accessible.
• svn: 35186, 35187

#### TParamFlag extended for hidden parameters

• Old behavior: TParamFlag has no entries for the hidden parameters (Array High, Self, Vmt, Result) of a function; SizeOf(TParamFlags) = 1
• New behavior: TParamFlag has entry pfHidden for hidden parameters in general and pfHigh for the high parameter of open array, pfSelf for the instance or class type, pfVmt for constructor's VMT parameter and pfResult if the result is passed as a parameter; SizeOf(TParamFlags) = 2
• Reason: As the plan is to use a manager based approach for Invoke() the RTL glue code should need as less knowledge as possible about calling conventions; due to this the locations of the hidden parameters needs to be known.
• Remedy: Adjust code that relies on the amount of elements contained in TParamFlag (e.g. case-statements or array indices) and also code that relies on the size of TParamFlags being 1 (SizeOf(TParamFlags) should be used instead).
• svn: 35267, 35286, 35291

### Unit changes

#### SysUtils

• Old behaviour: faSymlink had the numerical value $40. This was wrong on windows, and not compatible with Delphi. • New behaviour: faSymlink has the numerical value$400. Correct on windows.
• Reason for change: Wrong functionality and Delphi compatibility.
• Remedy: If you are using the old numerical constant $40, simply use faSymlink instead. #### Classes • Old behaviour: ISTreamAdaptor Interface (classes unit and jwa units) used Int64 for various out parameters. • New behaviour: ISTreamAdaptor Interface (classes unit and jwa units) use QWord for various out parameters. • Reason for change: The MS Headers use largeUint, which translates to QWord. The headers were for an old version of Delphi, which didn't know QWord. • Remedy: If a class implementing this interface no longer compiles, adapt the signature of the interface's methods so they conform to the new definition. #### DB ##### TParam.LoadFromFile sets share mode to fmShareDenyWrite • Old behaviour: TFileStream.Create(FileName, fmOpenRead) was used, which has blocked subsequent access (also read-only) to same file • New behaviour: TFileStream.Create(FileName, fmOpenRead+fmShareDenyWrite) is used, which does not block read access to same file • Remedy: If your application requires exclusive access to file specify fmShareExclusive ## Linux/Android platforms ### GNU Binutils 2.19.1 or later are required by default • Old behaviour: The compiler invocation of the linker always resulted in a warning stating "did you forget -T?" • New behaviour: The compiler now uses a different way to invoke the linker, which prevents this warning, but this requires functionality that is only available in GNU Binutils 2.19 and later. • Reason: Get rid of the linker warning, which was caused by the fact that we used the linker in an unsupported way (and which hence occasionally caused issues). • Remedy: If you have a system with an older version of GNU Binutils, you can use the new -X9 command line parameter to make the compiler revert to the old behaviour. You will not be able to (easily) bootstrap the new version of FPC on such a system though, so use another system with a more up-to-date version of GNU Binutils for that. ## i386 platforms ### -Ooasmcse/{$optimization asmcse} has been removed

• Old behaviour: The compiler contained an assembler common subexpression elimination pass for the i386 platform.
• New behaviour: This optimisation pass has been removed from the compiler.
• Reason: That pass has been disabled by default since several releases because it hadn't been maintained, and it generated buggy code when combined with newer optimisation passes.
• Remedy: Don't use -Ooasmcse/{\$optimization asmcse} anymore.