# User Changes 2.6.0

Below you can find a list of intentional changes since the previous 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. The list of new features can be found here.

## All systems

### Usage Changes

#### The Static modifier is now always enabled

• Old behaviour: Using the static modifier required using the -St command line switch or using the {$STATIC on} directive. • New behaviour: The static modifier is now always enabled. • Effect: The -St switch has been deprecated and the {$STATIC on/off} directive no longer exists.
• Reason: The compiler can now always correctly determine whether static is used as a modifier or as a field name, and recent Delphi versions also support static class methods without any special switches.
• Remedy: Adjust your build scripts and source code by removing all -St parameters and and {$STATIC on/off} statements. #### The POINTERARITHMETICS mode switch has been replaced with the POINTERMATH directive • Old behaviour: Pointer arithmetic was enabled in FPC/OBJFPC and partly (except using pointer as array) in DELPHI modes by default. To enable pointer arithmetic in other modes, {$MODESWITCH POINTERARITHMETICS} had to be enabled.
• New behaviour: Pointer arithmetic is enabled in FPC/OBJFPC modes and disabled in DELPHI mode. The new directive {$POINTERMATH ON/OFF} can be used to toggle pointer arithmetic support. Types declared while {$POINTERMATH ON} is in effect also support pointer arithmetic.
• Effect: {$MODESWITCH POINTERARITHMETICS} is no longer exists. Pointer arithmetic is disabled by default in DELPHI mode. • Reason: Delphi compatibility. • Remedy: Check your source code for {$MODESWITCH POINTERARITHMETICS} directives and replace them with {$POINTERMATH ON}. If your source files are using DELPHI mode and you use pointer arithmetic then add the {$POINTERMATH ON} directive to your source files.

#### Compiler no longer searches for utilities in the current directory

• Old behaviour: The compiler first searched the current directory for external utilities (the assembler, linker, resource compiler, ...) before other locations (directory containing the compiler binary, directories in the PATH).
• New behaviour: The compiler will no longer search the current directory for external utilities, except when explicitly instructed to do so (via -FD., or if the current directory is in the PATH)
• Reason: The old behaviour was a security issue, since a rogue binary with the same name as a helper utility in the current directory (e.g., /tmp on a Unix-based system) could compromise your account.
• Remedy: Put external utilities in a fixed location on your system and add that directory to the path. Note that on most systems this is the case by default, and no configuration changes will be required.

### 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:

#### Short/Ansistring typed constants containing widechars/unicodechars

• Old behaviour: The compiler accepted shortstring and ansistring typed constant declarations to which widestring or unicodestring constants were assigned (string constants containing widechars/unicodechars, i.e., character constants of the form #$xxx, #$xxxx or #yyy with yyy > 255, or character literals outside the ASCII range while the code page is different from the default one).
• New behaviour: The compiler will reject such declarations now.
• Example:
{$codepage utf8} { this example assumes that the source file has been saved using utf-8 encoding } const s1: shortstring = 'éà'; s2: ansistring = #$094#$06D; s3: ansistring = #267#543; begin end. All three declarations above used to be accepted, but are now rejected. The reasons are that • the string assigned to s1 has been encoded as an utf-8 string and contains non-ASCII characters • the string assigned to s2 contains hexadecimal character constants declared with more than 2 digits • the string assigned to s3 contains character values > 255 In all cases, the practical upshot is that the string on the right hand side of the assignment will be treated as a wide/unicodestring constant at compile time. • Reason: The encoding of shortstrings and ansistrings is always the system (ansi) encoding at run time. This system encoding can be different every time the program is run, and hence cannot be determined at compile time. It is therefore not possible for the compiler to convert a wide/unicodestring constant to an ansi/shortstring at compile time. See also bug report 16219. • Remedy: If you require the string's characters to contain particular ordinal values, declare the string constant as a sequence of byte-sized values (i.e., values <= 255, and in case of hexadecimal notation only use two digits), or do not use any {$codepage xxx} directive nor an UTF BOM. In all other cases, declare the typed constant as a widestring or unicodestring.

#### Implicit "result" variable in MacPas mode

• Old behaviour: In MacPas mode, all functions could automatically access the function result via the implicitly defined result alias (like in Delphi and ObjFPC mode).
• New behaviour: The result alias is no longer defined by default in MacPas mode.
• Reason: It is not available in Mac Pascal compilers either, and can mask other identifiers thereby changing the behaviour of code.
• Remedy: You can reenable the result alias by adding {$modeswitch result} to your program code (after any {$mode macpas} statements), or by using the -Mresult command line option (after any -Mmacpas parameter, and provided there are no {$mode xxx} directives in the source). #### Result type of the addr() operator • Old behaviour: The result type of the addr() operator was the same as that of the @ operator: plain pointer in case of {$t-}, and a pointer to the argument type in case of {$t+}. • New behaviour: The result type of the addr() operator is now always a plain pointer, regardless of the {$t+/-} state.
• Reason: Delphi compatibility.
• Remedy: Replace uses of addr() with @ in case your code is compiled with {$t+}, as this change may otherwise affect the selection of overloaded routines. #### Inaccessible symbols and properties • Old behaviour: The compiler allowed exposing normally inaccessible symbols, e.g. strict private fields from an inherited class, via properties. • New behaviour: Properties now obey the normal class visibility rules. • Reason: Consistency, Delphi compatibility. See http://bugs.freepascal.org/view.php?id=14650 • Remedy: Either change the parent class and make the field or method protected, or use accessors provided by the parent class. #### <Ordinal> in <Set type> is now forbidden • Old behaviour: Previous versions of FPC allowed type tset = 1...5; ... if i in tset then ... • New behaviour: This is now forbidden. • Reason: Probably implemented by accident, it is not considered being valid pascal neither any other pascal compiler supports it. • Remedy: Change the code into if i in [low(tset)..high(tset)] #### Support for class and record helpers • Old behaviour: It was possible to have helper fields immediately following the class or record keyword. • New behaviour: The compiler now interprets helper as a helper type if it immediately follows the class or record keyword (the latter one only if the mode is delphi or the modeswitch advancedrecords is active). • Example: {$mode delphi}
type
TSomeRecord = class
helper: integer;
end;

TSomeRecord = record
helper: integer;
end;

The above code will no longer compile.

• Reason: helper is the way helper types are specified, which is Delphi-compatible
• Remedy: Separate the helper field name from the class or record keyword with a visibility section (published, public, ...) or with another field declaration.

#### Taking the address of fields of record properties

• Old behaviour: It was possible to pass a field of a record property as a var-parameter and to take its address in another ways.
• New behaviour: Taking the address of fields of record properties is no longer allowed.
• Reason: If the property is implemented using a function, taking the address of such a field resulting in taking the address of a temporary location. Updating that location won't have any persistent consequences. In case of properties that map directly onto records, the new behaviour is consistent with the property changes introduced in FPC 2.4.0
• Remedy: Same as with the related changes in FPC 2.4.0

#### Generics syntax in Delphi mode

• Old behaviour: FPC's generics support was developed in parallel with Delphi's, and the FPC and Delphi teams came up with a different syntax. FPC supported FPC's syntax for generics in both Delphi and other syntax modes.
• New behaviour: Support for Delphi's syntax for generics has been added, and therefore in Delphi syntax mode FPC now only supports the Delphi generics syntax.
• Reason: Delphi compatibility
• Remedy: Either change the code to {$mode objfpc}, or change the syntax of generics code Delphi-compatible syntax ### 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.

#### Constants in mixed signed/unsigned 64 bit expressions

• Old behaviour: Some comparisons involving a negative 64 bit constant and a unsigned 64 bit variable were handled incorrectly by the compiler: the negative constant was internally explicitly typecasted to the unsigned type.
• New behaviour: The compiler will now correctly use the original value of the negative constant.
• Effect: Some comparisons that previously evaluated to "true" at run time, may now evaluate to "false" at compile time.
• Example:
const
// note that 64 bit hexadecimal constants are always parsed as int64
// (also by previous FPC releases)
BIG_A = $AB09CD87EF653412; var q : qword; begin q := qword(BIG_A); if (q = BIG_A) then writeln('same') else writeln('different'); end. The above program used to print 'same', but will now print 'different' • Reason: The compiler must not automatically convert negative constants to positive equivalents like that. • Remedy: Explicitly typecast any constants that are supposed to be unsigned 64 bit constants to qword. E.g., in the above example, use BIG_A = qword($AB09CD87EF653412).

#### Overflow/Rangechecking for floating point constants

• Old behavior: When a NaN floating point constant was assigned to a variable in {$R+} or {$Q+} mode, the compiler reported an error.
• New behaviour: {$R+} and {$Q+} no longer cause errors when assigning a NaN constant to a variable. The new $ieeeerrors setting can now be used to control whether or not such assignments should cause an error. • Reason: Consistency, Delphi compatibility (it does not support the {$ieeeerrors+/-} setting, but it does not give an error based on the {$r/q} settings either) . • Remedy: Add {$ieeeerrors+} to your code or add -C3 on the command line.

#### New element in TTypeKind enumeration

• Old behaviour: The TTypeKind enumeration contained 26 elements (tkUnknown to tkUChar).
• New behaviour: The TTypeKind enumeration now contains 27 elements (tkHelper was added at the end).
• Effect: A constant array that uses TTypeKind as an index will generate a compile error, because it now contains too few elements.
• Reason: Helper types needed their own type in the RTTI, because they were implemented differently than in Delphi.
• Remedy: Add a new element at the end of your array with a corresponding content for helper types.

• Old behaviour: While the size of records was padded to a multiple of their alignment requirements, this was not done for the instance size of objects and classes.
• New behaviour: The size of objects and classes (and the newly introduced objcclass) is now also padded to a multiple of their alignment requirements.
• Effect: In general, this should only affect code that blockwrites objects to disk and reads them back later. For those the same rules hold as for regular records: this is only supported across different FPC versions if they are packed.
• Reason: Delphi-compatibility, conforming to the Objective-C ABI.
• Remedy: Declare object types that you wish to save to/load from disk as packed. For class types, this change should not affect any code.

#### Mangling of variables, typed constants and internally used symbols

• Old behaviour: Variable a_varname of unit test had mangled symbol U_TEST_A_VARNAME.
• New behaviour: Variable a_varname of unit test has mangled symbol U$_TEST_A$_VARNAME.
• Reason: The old scheme did not generate unique symbol names: variable varname of unit test_a, and variable a_varname of unit test had the same mangled name. See also bug report 20093.
• Remedy: This change should not affect you unless you use mangled symbol name directly inside assembler code, which is strongly discouraged. You should explicitly declare an alias for variables that you wish to access by symbol name from assembler code.
• Notes: The new naming scheme has not yet stabilized.

#### Using resourcestrings to initialize typed string constants

• Old behaviour: A typed string constant initialized with a resourcestring holds the initial value of resourcestring and is not changed whenever the resourcestring is modified by calling SetResourceStrings or SetUnitResourceStrings.
• New behaviour: The value of AnsiString constants is now kept in sync with corresponding resourcestrings, causing them to change to current value of resourcestrings when SetResourceStrings or SetUnitResourceStrings is called. Behavior of ShortString constants stay unchanged.
• Reason: Delphi compatibility, issue 19651.
• Remedy: If new behavior is not desired, consider using a separate literal to initialize the constant:
{ before }
resourcestring
str1='foo';
const
str2: string=str1;

{ after }
const
str2: string='foo';

### Unit changes

#### SysUtils.GetAppConfigDir() now uses VendorName

• Old behaviour: The GetAppConfigDir function ignored the VendorName.
• New behaviour: GetAppConfigDir now also takes into account VendorName if it is set.
• Reason: This is in accordance with Microsoft guidelines for setting file locations.
• Remedy: If you want to migrate data from the old location to the new location, you may want to temporarily clear VendorName before calling GetAppConfigDir to get the path to the old location.

#### IniFiles.WriteString() no longer deletes empty values

• Old behaviour: WriteString() deleted the key if the value was empty.
• New behaviour: WriteString() writes an empty value.
• Reason: Compatibility with Delphi TMemIniFile and Windows IniFile behaviour.
• Remedy: Use DeleteKey() to delete a key

#### IniFiles.DeleteKey() no longer deletes empty sections

• Old behaviour: DeleteKey() deleted the section if the last key was deleted.
• New behaviour: DeleteKey() leaves the section intact.
• Reason: Compatibility with Delphi TMemIniFile and Windows IniFile behaviour.
• Remedy: Use EraseSection() to delete a section

#### xmlrpc unit and utils have been removed

• Old behaviour: There was an xmlrpc unit and a related demo program called mkxmlrpc.
• New behaviour: These sources have been removed in svn 2.6.0, and deprecated in the svn fixes branch.
• Reason: The code was unmaintained and had been broken for years, and has been replaced by new functionality in fcl-web and fcl-json.
• Remedy: Use fcl-web or, if adapting the source code is not feasible, obtain the xmlrpc-related sources from older FPC versions.

#### IInterface.QueryInterface, ._AddRef and ._Release definitions have been changed

• Old behaviour: The IInterface.QueryInterface, ._AddRef and ._Release methods were defined stdcall and the IID was passed as const.
• New behaviour: These methods are defined stdcall on Windows and cdecl on the other operating systems. The IID parameter has become a constref.
• Reason: These methods are used for communicating with COM on Windows. These changes make it possible to interface with XPCom from Mozilla, which is cross-platform and similar to COM/Corba.
• Remedy: If one of these methods is overridden, they have to be defined as follows:
function QueryInterface(constref IID: TGUID; out Obj): HResult; {$ifndef windows}cdecl{$else}stdcall{$ifend}; override; function _AddRef: Integer; {$ifndef windows}cdecl{$else}stdcall{$ifend}; override;
function _Release: Integer; {$ifndef windows}cdecl{$else}stdcall{$ifend}; override;  You can also use the following more verbose alternative, in case the code has to be compilable by older FPC versions as well: function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; override; function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; override;
function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{\$IFEND}; override;


#### thread_count removed from system unit (win32,win64,wince, symbian, nativent)

• Old behaviour: There was a variable called thread_count in the system unit of the targets win32,win64,wince, symbian, nativent
• New behaviour: The variable has been removed.
• Reason: The behaviour of the variable was wrong and cannot be fixed, see also http://bugs.freepascal.org/view.php?id=18089
• Remedy: Since the value of the variable was unpredictable, there was probably no use of it.

#### Locale global variables are deprecated

• Old behaviour: For every locale configuration a variable alias existed (currencystring, *dateformat) using an "absolute" modifier.
• New behaviour: These variable now have the "deprecated" modifier, and a warning is emitted if you use one.
• Reason: FPC has supported the use of these variables in a record since before 2000 called DefaultFormatSettings, Delphi XE now follows suit with "Formatsettings", and deprecated the old ones. In time this might remove the need for "absolute" usage.
• Remedy: Use (Default)Formatsettings as much as possible. Note that that it will still be quite some time before these are actually removed.

#### CustApp logging changes

• Old behaviour: TCustomApplication.Log was virtual and had to be overridden to actually implement logging.
• New behaviour: The Log procedure is now no longer virtual, but static.
• Reason: The new EventLogFilter property. This is a set of TEventType that determines which events are actually logged. Filtering is handled in the static Log procedure.
• Remedy: Descendents must override the DoLog procedure instead of Log to implement the actual logging.

#### fpweb T(Custom)FPWebModule.Template property

• Old behaviour: TFPWebModulehad a property Template.
• New behaviour: This property has been renamed into ModuleTemplate.
• Reason: The TCustomFPWebModule.Template property was renamed to ModuleTemplate to avoid confusion with the Template property of actions in event handlers of the actions.
• Remedy: Rename Template to ModuleTemplate in all code that uses it

#### HTTP (Apache) units changes

• Old behaviour: Header translations of version 1.3, 2.0, 2.2 were built and installed by default.
• New behaviour: Only Apache 2.2 versions of the headers are built and installed.
• Reason: Quite often, the compiled module ended up with the wrong units, causing crashes in Apache.
• Remedy: compile and install the needed headers manually : cd to the needed directory, execute make install, and then recompile fcl-web.

#### fcl-image has a different default compression when writing PNGs

• Old behaviour: The zlib compression of the PNG writer was set to best
• New behaviour: The zlib compression of the PNG writer was set to default
• Reason: Introduction of a compressionlevel property allowed reexamination of a sane default. The best compressionlevel is relatively a lot slower than default, for very little gains.
• Remedy: Reevaluate the need for maximal compression. Typically you will only use "max" for long term storage or when images are hand drawn, like diagrams (not photographic in origin). If this is the case, set the new writer.compressionlevel to desired compressionlevel (clnone,clfastest,cldefault,clbest).

#### Some fields of the generics in the fgl were public or protected by accident

• Old behaviour: Some fields of the generics in the fgl were public or protected, so they could be accessed by user programs.
• New behaviour: These fields are now private and not accessible anymore.
• Reason: Encapsulation.
• Remedy: All functionalty should be still available by the public methods.

#### regexpr.pp was renamed to oldregexpr.pp

• Old behaviour: There was a very small source file called packages/regexpr/src/regexpr.pp.
• New behaviour: This file was moved to packages/regexpr/src/oldregexpr.pp.
• Reason: Sorokins Delphi Regular Expressions was added, so we needed to clean up the namespace for the new regexpr library located in packages/regexpr/src/oldregexpr.pas.
• Remedy: If you use the unit regexpr, just rename any place where you add it to your uses clause to oldregexpr.

#### SQLDB/TSQLite3Connection now stores date[time] values as Julian day numbers

• Old behaviour: Date, DateTime and Time values was stored as real numbers, where 0="1899-12-30 00:00:00" (Object Pascal or Excel Epoch)
• New behaviour: Date, DateTime and Time values are now stored as real numbers, where 0="January 1, 4713 BC 12:00:00" (Julian Epoch)
• Reason: SQLite expect, that value is Julian day number, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar. (http://www.sqlite.org/datatype3.html#datetime)
• Remedy: update your database - shift datetime values. You can use: "update table_name set datetime_column=datetime_column+2415018.5 where datetime_column<1721059.5"

## Unix platforms

### SysUtils.FileAge no longer works for directories

• Old behaviour: SysUtils.FileAge worked for both files and directories on Unix platforms.
• New behaviour: This routine now only works for files.
• Reason: Consistency with other platforms, Delphi compatibility.
• Remedy: Call BaseUnix.fpstat() directly for directories. A patch adding a DirectoryAge() function to SysUtils for both Unices and Windows platforms is also welcome.

## x86 platforms

### Operation size of pushf/popf/pusha/popa in Intel-style inline assembly

• Old behaviour: The default operation size of the pushf/popf/pusha/popa in Intel-style inline assembly was the native size (32 bit on i386, 64 bit on x86-64).
• New behaviour: The default operation size of these opcodes is now always 16 bit in Intel-style inline assembly. In AT&T-style inline assembly, the size remains the native size.
• Reason: This is how the behaviour of these opcodes is defined in the Intel manuals, and it is also Delphi-compatible. The behaviour was not changed in AT&T-inline assembly because that dialect defines the default size of these operations as the native size.
• Remedy: Explicitly specify the size when using such operations, e.g. pushfd, popfq, pushad, ... Note that pusha*/popa* do not exist on x86-64, and neither do pushfd/popfd (the compiler previously however erroneously accepted these opcodes when compiling for x86-64).

## x86-64 platforms

### Parameter passing and returning results on x86-64 platforms (except for Win64)

• Old behaviour: The compiler did not correctly implement the official x86-64 ABI for passing parameters and returning function results in all cases. In particular, records were always either passed/returned via integer registers or memory.
• New behaviour: The compiler now correctly adheres to the official x86-64 ABI under all circumstances on platforms that require this. In particular, certain records are now passed/returned via SSE registers.
• Effect: Pure assembler routines based on the old conventions may no longer work on non-Win64 platforms. Win64 follows Microsoft's own variant of the x86-64 ABI and this one was already implemented correctly in the compiler, and hence has not been changed.
• Reason: Interoperability with code generated by other compilers.
• Remedy: Adjust your assembler code so it expects parameters to be passed conform to the official x86-64 ABI

### Const parameter passing on non-Win64 platforms

• Old behaviour: All record parameters defined as const were passed by value.
• New behaviour: For calling conventions other than cdecl and cppdecl, const record parameters are now passed by reference if they should be passed via memory according to the x86-64 ABI. Note that except for cdecl and cppdecl, the behaviour of const is not defined and may change at any time.
• Reason: Performance.
• Remedy: In most cases, this change will not require any changes to existing code. The only exception is if you have assembler routines with const record parameters. In this case, the assembler code may have to be modified to expect a pointer to the record under the circumstances mentioned above. A better modification would be to remove the const altogether from any assembler routines and either use a value parameter or constref, which respectively guarantee passing by value and passing by reference.