Sign in Join
Wiki copytemporary

User Changes 3.0: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## About this page
22
33Listed below are intentional changes made to the FPC compiler (3.0) since the [[User Changes 2.6.4|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.
44
55## All systems
66
77### Implementation changes
88
99#### Exception type for object reference checking changed
1010
1111- **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.
1212- **New behaviour**: Now an exception of class *EObjectCheck* with localizeable message *Object reference is Nil* is created.
1313- **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.
1414- **Remedy**: If your code previously checked an exception for the message *Unknown runtime error 210* you should now check for the exception class *EObjectCheck*.
1515
1616#### Literal storage memory has been made read-only
1717
1818- **Old behaviour**: read-only data segments were *de facto* not supported, and 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:
1919
2020``` pascal
2121uses sysutils;
2222 var
2323 s: ansistring;
2424 begin
2525 s := 'ansi string';
2626 Writeln(AnsiStrUpper(pchar(s)));
2727 s := 'ansi string';
2828 Writeln(s);
2929 end.
3030```
3131
3232would modify the contents of data segment and print
3333
34-`ANSI STRING`\
35-`ANSI STRING`
34+```text
35+ANSI STRING
36+ANSI STRING
37+```
3638
3739- **New behaviour**: Data that is not intended to be modified at runtime is put into a read-only segment. This includes literal constants used in expressions and typed constants declared in {\$J-} state. Any code which modifies such data (as in the above example) will now crash.
3840- **Reason**: This is consistent with the way other compilers (including Delphi) work. Keeping data read-only as much as possible improves a program's loading speed because read-only pages can be mapped directly to the executable file. This also improves program security.
3941- **Remedy**: is very code-dependent. In the example above, it is sufficient to call `UniqueString(s)` before `AnsiStrUpper`
4042
4143#### *UNICODE* define depends on default string type instead of on target platform
4244
4345- **Old behaviour**: The compiler defined the preprocessor symbol *UNICODE* when targeting a Windows platforms that only has a unicode OS API (Windows CE and NativeNT).
4446- **New behaviour**: The *UNICODE* define is now only set if the default string type is *unicodestring* (as opposed to *shortstring* or *ansistring*). This happens when the new *{\$mode delphiunicode}* or *{\$modeswitch unicodestrings}* are active. The target platform no longer has any influence.
4547- **Reason**: In Delphi 2009 and newer the type *String* is defined as *UnicodeString*, and this can be determined by the fact that these Delphi versions also define the *UNICODE* symbol.
4648- **Remedy**: Use *{\$ifdef FPC_OS_UNICODE}* instead of *{\$ifdef UNICODE}* to determine whether or not the OS only supports a unicode (UTF-16) API.
4749
4850### RTTI changes
4951
5052#### RTTI for Pointers and Class References
5153
5254- **Old behavior**: Pointers and Class References had tkUnknown RTTI.
5355- **New behavior**: Pointers now have RTTI type tkPointer, and class references have the RTTI type tkClassRef. Each now contains a reference to a type they point to.
5456- **Reason**: Both user requests and Delphi compatibility.
5557- **Remedy**: The TTypeKind enumeration has more members than before. Adjust any code which uses TTypeKind accordingly.
5658
5759#### RTTI for AnsiStrings
5860
5961- **Old behavior**: AnsiString RTTI previously lacked CodePage information.
6062- **New behavior**: A new CodePage member has been added for the tkAString type.
6163- **Reason**: This is required for serializing/deserializing of published AnsiString properties, and is now compatible with Delphi.
6264- **Remedy**: not known
6365
6466#### RTTI for Arrays
6567
6668- **Old behavior**: tkArray had no member in the TTypeData record, although internally the compiler stored these members: first dimension size, first dimension element count and first dimension element type. So for a 2 dimension array element the type was array for the second dimension.
6769- **New behavior**: tkArray now has a TArrayTypeData structure in TTypeData. It has the following members: total array size including all dimensions, total element count, last dimension element type, number of dimensions, type information for each dimension range.
6870- **Reason**: This provides more comprehensive RTTI, and is compatible with Delphi.
6971- **Remedy**: If your code internally used the older RTTI array information you will need to adapt it to take account of the newly provided TArrayTypeData information.
7072
7173#### RTTI for Records
7274
7375- **Old behavior**: Records RTTI stored field Offsets as 32bit integers.
7476- **New behavior**: Records RTTI stores field Offsets as platform-dependent integers (the same size as pointers).
7577- **Reason**: Internally the compiler stores Offsets as platform-dependent integers. The new behaviour is Delphi-compatibile.
7678- **Remedy**: You need to adjust your code if you used field offsets of record RTTI. This is also true if your code processes any vInitTable field within the VMT of a class.
7779
7880#### RTTI for Procedural Variables
7981
8082- **Old behavior**: tkProcVar lacked any member in the TTypeData record and the compiler stored no information about procedural variables.
8183- **New behavior**: tkProcVar now has a new TProcedureSignature structure in TTypeData which contains information about the procedure's calling convention, result type and parameters (where applicable).
8284- **Reason**: User request. More informative RTTI. Delphi compatibility.
8385- **Remedy**: not known
8486
8587##### Usage example
8688
8789``` pascal
8890program RTTIInfo;
8991
9092{$mode objfpc}{$H+}
9193uses
9294 typinfo;
9395
9496type
9597 CP866String = type AnsiString(866);
9698 TProc = procedure(var A: Integer; S: String); stdcall;
9799 TColor = (red, green, blue);
98100 TArr = array[TColor,0..3] of Integer;
99101 PArr = ^TArr;
100102
101103procedure DescribeProcedure(Info: PTypeInfo);
102104const
103105 ParamFlagToStr: array[TParamFlag] of AnsiString = (
104106 'var',
105107 'const',
106108 'array',
107109 'address',
108110 'reference',
109111 'out'
110112 );
111113 CallConvToStr: array[TCallConv] of AnsiString = (
112114 'register',
113115 'cdecl',
114116 'pascal',
115117 'stdcall',
116118 'safecall',
117119 'cppdecl',
118120 'far16',
119121 'oldFPCcall',
120122 'internProc',
121123 'SysCall',
122124 'SoftFloat',
123125 'MWPascal'
124126 );
125127var
126128 Data: PTypeData;
127129 Param: PProcedureParam;
128130 ParamFlag: TParamFlag;
129131 I: Integer;
130132 Res, S, TypeName: String;
131133begin
132134 if Info^.Kind <> tkProcedure then
133135 Exit;
134136 Data := GetTypeData(Info);
135137 if Data^.ProcSig.CC <> ccStdCall then
136138 halt(2);
137139 if Data^.ProcSig.ResultType <> nil then
138140 begin
139141 Res := 'function ' + Info^.Name;
140142 TypeName := ': ' + Data^.ProcSig.ResultType^.Name;
141143 end
142144 else
143145 begin
144146 Res := 'procedure ' + Info^.Name;
145147 TypeName := '';
146148 end;
147149 if Data^.ProcSig.ParamCount > 0 then
148150 begin
149151 Res := Res + '(';
150152 for I := 0 to Data^.ProcSig.ParamCount - 1 do
151153 begin
152154 Param := Data^.ProcSig.GetParam(I);
153155 S := '';
154156 for ParamFlag in TParamFlags(Param^.Flags) do
155157 S := S + ParamFlagToStr[ParamFlag] + ' ';
156158 S := S + Param^.Name + ': ' + Param^.ParamType^.Name;
157159 if I > 0 then
158160 Res := Res + '; ';
159161 Res := Res + S;
160162 end;
161163 Res := Res + ')';
162164 end;
163165 Res := Res + TypeName + '; ' + CallConvToStr[Data^.ProcSig.CC] + ';';
164166 WriteLn(Res);
165167end;
166168
167169procedure DescribeAnsiString(Info: PTypeInfo);
168170var
169171 Data: PTypeData;
170172begin
171173 if Info^.Kind <> tkAString then
172174 Exit;
173175 Data := GetTypeData(Info);
174176 if Data^.CodePage = 0 then
175177 WriteLn('AnsiString')
176178 else
177179 WriteLn('type AnsiString(',Data^.CodePage,');');
178180end;
179181
180182procedure DescribeArray(Info: PTypeInfo);
181183var
182184 Data: PTypeData;
183185 Res: String;
184186 I: Integer;
185187begin
186188 if Info^.Kind <> tkArray then
187189 Exit;
188190 Data := GetTypeData(Info);
189191 Res := 'array[';
190192 for I := 0 to Data^.ArrayData.DimCount - 1 do
191193 begin
192194 if I > 0 then
193195 Res := Res + ', ';
194196 Res := Res + Data^.ArrayData.Dims[I]^.Name;
195197 end;
196198 Res := Res + '] of ' + Data^.ArrayData.ElType^.Name + ';';
197199 WriteLn(Res);
198200end;
199201
200202procedure DescribePointer(Info: PTypeInfo);
201203var
202204 Data: PTypeData;
203205begin
204206 if Info^.Kind <> tkPointer then
205207 Exit;
206208 Data := GetTypeData(Info);
207209 if Data^.RefType = nil then
208210 WriteLn('Pointer;')
209211 else
210212 WriteLn('^', Data^.RefType^.Name, ';');
211213end;
212214
213215begin
214216 DescribeProcedure(TypeInfo(TProc));
215217 DescribeAnsiString(TypeInfo(CP866String));
216218 DescribeArray(TypeInfo(TArr));
217219 DescribePointer(TypeInfo(PArr));
218220 DescribePointer(TypeInfo(Pointer));
219221end.
220222```
221223
222224### Unit changes
223225
224226#### DB
225227
226228##### TBookmark TBookmarkstr and TDataset.Bookmark change to Delphi2009+ compatible definitions
227229
228230- **Old behaviour**: TDataset.Bookmark was of type TBookmarkstr, TBookmarkstr=string, Tbookmark=pointer
229231- **New behaviour**: TDataset.Bookmark is of type TBookmark, TBookmarkstr=ansistring, TBookmark=TBytes. TBookmarkstr will trigger a deprecated warning.
230232- **Reason**: D2009+ compatibility, where probably the fact that string became a 2-byte encoding was the trigger.
231233- **Remedy**: Adjust typing in descendents and using code accordingly.
232234
233235##### TBufDataset.SaveToFile, SaveToStream: Binary Format (dfBinary) of saved data changes
234236
235237- **Old behaviour**: Record data was saved to stream just as they exist in the TBufDataset memory record buffer.
236238- **New behaviour**: Record data are saved field by field. Each variable length field begins with a 4 byte length indicator followed by data. Fixed length fields are stored without prefixed length indicator. LoadFromFile, LoadFromStream support both formats (OLD and NEW).
237239- **Reason**: BLOBs were not saved correctly in the OLD format: instead of BLOB data, a pointer to memory where BLOB data resided was saved.
238240- **Remedy**: if you need the OLD behavior in saving, you must register your own DataPacketReader using RegisterDatapacketReader procedure.
239241
240242``` pascal
241243unit OldBinaryDatapacketReader;
242244
243245{$mode objfpc}{$H+}
244246
245247interface
246248
247249uses
248250 Classes, SysUtils, BufDataset;
249251
250252type
251253
252254 { TOldFpcBinaryDatapacketReader }
253255
254256 TOldFpcBinaryDatapacketReader = class(TFpcBinaryDatapacketReader)
255257 public
256258 constructor Create(AStream : TStream); override;
257259 end;
258260
259261implementation
260262
261263{ TOldFpcBinaryDatapacketReader }
262264
263265constructor TOldFpcBinaryDatapacketReader.Create(AStream: TStream);
264266begin
265267 inherited;
266268 FVersion := 10;
267269end;
268270
269271initialization
270272 RegisterDatapacketReader(TOldFpcBinaryDatapacketReader, dfBinary);
271273end.
272274```
273275
274276##### TDataPacketReader class structure changes
275277
276278- **Old behaviour**:
277279- **New behaviour**: reference to TCustomBufDataset is passed only once in constructor of TDataPacketReader and stored in instance TDataPacketReader.
278280- **Reason**: simplify design and make it more flexible
279281- **Remedy**: if you use your own TDataPacketReader descendant update method signatures
280282
281283##### TSQLScript supports :, backtick quotes and explicit COMMIT/COMMIT RETAIN
282284
283285- **Old behaviour**:
284286 - [[TSQLScript]] parsed words starting with : in SQL as if they were sqldb parameters; running the resulting statements would very likely fail, making the class unusable.
285287 - With UseCommit set, once a COMMIT directive was found, CommitRetaining is run instead of Commit. This lead to problems with scripts that need a hard commit (e.g. Firebird DDL followed by DML).
286288 - TSQLScript did not support backtick quotes (\`), e.g. for MySQL
287289- **New behaviour**:
288290- Parser improvement: comments starting with -- are detected as comments
289291 - words starting with : are not parsed as sqldb parameters.
290292 - if UseCommit is set, COMMIT WORK or COMMIT leads to Commit; the new directive COMMIT RETAIN (or no directive) leads to CommitRetaining being executed
291293 - TSQLScript supports backtick quotes (\`), e.g. for MySQL
292294- **Reason**: usability, compatibility with scripts generated by 3rd party packages.
293295- **Remedy**:
294296 - if your code depended on : parameter parsing, you could use a TSQLEventScript class and manipulate the SQL.
295297 - commit behaviour: check your scripts for any unexpected COMMIT RETAIN statements.
296298
297299##### TMySQLxxConnection (mysqlconn.inc) VARCHAR columns are always mapped to TStringFields
298300
299301- **Old behaviour**: varchar columns with length \> 8192 (dsMaxStringSize) were re-mapped to TMemoFields
300302- **New behaviour**: varchar columns are always mapped to TStringFields
301303- **Reason**: Honour server definition and map column data types as reported by server
302304- **Remedy**: If you use varchar with length \> 8192 and you have field definitions stored in lfm, update them.
303305
304306##### TSQLite3Connection INTEGER PRIMARY KEY columns are mapped to TAutoIncFields
305307
306308- **Old behaviour**: INTEGER columns, which are also PRIMARY KEY were mapped to TIntegerField
307309- **New behaviour**: INTEGER columns, which are also PRIMARY KEY are now mapped to TAutoIncField
308310- **Reason**: Tables with INTEGER columns, which are also PRIMARY KEY are in SQLite alias for ROWID. And ROWID columns have autoincrement capability. For more details see: <http://www.sqlite.org/lang_createtable.html#rowid> and <http://www.sqlite.org/autoinc.html>
309311- **Remedy**:
310312
311313##### TSQLite3Connection: Boolean True values are stored as 1 not as -1
312314
313315- **Old behaviour**: Boolean True parameters was bind as integer = -1.
314316- **New behaviour**: Boolean True parameters are bind as integer = 1. As expected by SQLite: "SQLite does not have a separate Boolean storage class. Instead, Boolean values are stored as integers 0 (false) and 1 (true)."
315317- **Reason**: Align with SQLite specification and also with others DB components (like SQLite3DataSet), which expect True=1
316318- **Remedy**: Check your applications and if your tables contain boolean columns which are part of primary key or you use in WHERE clause constructs like "boolean_column=:boolean_param" then you must take attention to fix database or use construct like: "ABS(boolean_column)=:boolean_param"
317319
318320#### FileNameCaseSensitive and FileNameCasePreserving in unit System
319321
320322- **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).
321323- **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.
322324- **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.
323325- **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.
324326
325327#### Some longtime deprecated functions in unit Unix have been removed.
326328
327329- **Old behaviour**: Unix.(f)statfs, Unix.shell and Unix.fsync symbols existed in unit Unix
328330- **New behaviour**: Unix.(f)statfs, Unix.shell and Unix.fsync were removed
329331- **Reason**: These were helper functions and leftovers from the 1.0.x-\>2.0.0 conversion, deprecated since 2007. Shell had non standarized conventions
330332- **Remedy**: All but shell: use the same functions with an "fp" prefix. Shell: use fpsystem. If you checked the return value for other values than -1, a modification of the error checking 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.
331333
332334#### statfs has been renamed to fpstatfs
333335
334336- **Old behaviour**: One overload of fpstatfs was not renamed from statfs to fpstatfs (around 2.4.0)
335337- **New behaviour**: The function has been renamed.
336338- **Reason**: Should have been done in 2.4.0 to begin with, but was postponed several times to coincide with a major version change.
337339- **Remedy**: Use fpstatfs
338340
339341#### RTLeventsync has been removed
340342
341343- **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.
342344- **New behaviour**: The field and routine have been removed.
343345- **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.
344346- **Remedy**: Remove any such calls from your code.
345347
346348#### TVersionInfo (fileinfo unit) re-implemented in a platform independent way
347349
348350- **Old behaviour**: GetVersionSetting method would read file information.
349351- **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.
350352- **Reason**: The unit now uses FPC resources on all platforms, and can now be used to read external resources.
351353- **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
352354
353355#### shlobj symbols removed from unit Windows
354356
355357- **Old behaviour**: When unit windows was split between the windows and shlobj units, not all shlobj symbols were removed from Windows.
356358- **New behaviour**: shlobj symbols has been removed from the windows unit. Code relying on that will fail to compile if it doesn't import shlobj.
357359- **Reason**: shlobj and windows versions were not compatible and lead to errors.
358360- **Remedy**: put shlobj in your uses clause, if not there already.
359361
360362#### process OnForkEvent implementation
361363
362364- **Old behaviour**: Signature was a simple procedure.
363365- **New behaviour**: TNotifyEvent -compatible signature for the call.
364366- **Reason**: It was impossible to know the TProcess instance for which the fork was called, and hence impossible to parametrize the procedure.
365367- **Remedy**: Change the signature of your callback to match a TNotifyEvent
366368
367369#### Extention -\> Extension typo fix
368370
369371- **Old behaviour**: The incorrect term Extention (typo) was used in the interface of several units: fpimage, sndfile.
370372- **New behaviour**: The correct term Extension is now used.
371373- **Reason**: Why have code with incorrect English?
372374- **Remedy**: Change extention to extension.
373375
374376#### SysUtils: File names starting with a period are not considered to be extensions
375377
376378- **Old behaviour**: File names that start with a period were considered to only have an extension and no base file name by `ExtractFileExt()` and `ChangeFileExt()`
377379- **New behaviour**: By default, the portion of the filename starting with the period up till the next period (if any) or end of the file name is now considered to be the file name, and the rest is considered by the extension. Note that this behaviour is **not** Delphi-compatible.
378380- **Reason**: Change behaviour to match file system/OS conventions.
379381- **Remedy**: There is a new a variable `FirstDotAtFileNameStartIsExtension`. By default, it is set to *false*, which corresponds to the new behaviour. If it is set to *true*, the aforementioned routines revert to the old behaviour.
380382
381383#### System: Error messages are now written to stderr
382384
383385- **Old behaviour**: On error, the binaries halted and wrote an error message to standard output.
384386- **New behaviour**: On error, the binaries halt and write an error message to standard error .
385387- **Reason**: Change behaviour to match OS conventions. Diagnostic output should be written to standard error.
386388- **Remedy**: A system unit variable WriteErrorsToStdErr can be set to 'False' and then the output is written to standard output, as it was.
387389
388390#### TZipper: writes zip files with zip standard / instead of \\ directory separators
389391
390392- **Old behaviour**: on Windows (only), TZipper would write \\ to the zip file when paths were used. This does not conform to the zip standard though many utilities would accept this. However, it is not according to the standard and leads to problems with e.g. LibreOffice reading .xlsx files generated by fpspreadsheet.
391393- **New behaviour**: TZipper writes / when paths are used; it still accepts \\ for reading on Windows. Note: on Windows, TZipper still accepts / as path separator when reading zip files for compatibility with buggy third party code.
392394- **Reason**: standards compliance, interoperability.
393395- **Remedy**: if you need to interoperate with 3rd party tools that require zip files with \\, please copy all code in \packages\paszlib\src and edit procedures SetArchiveFileName, SetDiskFileName
394396
395397### Language Changes
396398
397399#### AnsiStrings are now codepage-aware
398400
399401- **Old behaviour**: The codepage of an *AnsiString* was always be assumed to be the default system (single byte) code page. The predefined *Utf8String* type was just an alias for *AnsiString* and did not behave differently in any way.
400402- **New behaviour**: Every *AnsiString* constant or variable now also has an associated code page, which governs how its data is interpreted. The predefined *Utf8String* type is now tagged with the UTF-8 codepage identifier.
401403- **Reason**: Delphi 2009+ compatibility.
402404- **Remedy**: This new feature generally works transparently, but there are some caveats:
403405 - Avoid using *AnsiString* variables to store data not encoded using the *DefaultSystemCodePage* encoding without also setting the corresponding code page (such as currently done in Lazarus). For example, assume an *AnsiString* with a [[FPC Unicode support|dynamic code page]] different from *CP_UTF8* (e.g. [[FPC Unicode support|CP_ACP]]) contains UTF-8 data. If it is then converted to a different code page, e.g. because it's passed to a routine expecting a *UnicodeString* or *Utf8String* parameter, then the UTF-8 data in the string will be "converted" from CP_ACP to UTF-8, thereby corrupting the string data (if CP_ACP is different from UTF-8).
404406 - Routines that are declared with a plain *AnsiString* parameter will cause passed custom code page strings to be converted to *DefaultSystemCodePage*, possibly resulting in data loss. We have [[FPC Unicode support|a list of RTL routines]] that have been updated to correctly handle strings encoded in any code page.
405407- **More information**: [[FPC Unicode support]]
406408
407409#### Variant overload preference for string types
408410
409411- **Old behaviour**: Preference for string types was (from better to worse): ShortString, AnsiString, WideString, UnicodeString
410412- **New behaviour**: Preference for string types now (from better to worse): WideString, UnicodeString, AnsiString, ShortString
411413- **Reason**: Unicode characters and codepage information will not be lost during the conversion; unicode Delphi compatibility.
412414- **Remedy**: Use explicit conversion (e.g. ShortString(V)) if it is needed to pass variant to routine with a particular string type argument.
413415
414416#### Variant conversion preference for widechar
415417
416418- **Old behaviour**: If a *widechar* was passed to a *variant* parameter, it would be wrapped as a *word* (D7 compatible).
417419- **New behaviour**: A *widechar* passed to a *variant* parameter is now convert it to a unicodestring (D2009+ compatible).
418420- **Reason**: Newer Delphi version compatibility.
419421- **Remedy**: Use explicit conversion (e.g. integer(V)) if needed. We decided against differentiating this behaviour between *{\$mode delphi}* and *{\$mode delphiunicode}* because the compatibility advantage does not outweigh implementation complexity.
420422
421423#### Default values in implementation but not in interface/forward declaration
422424
423425- **Old behaviour**: The implementation of a routine could declare default values even if the interface declaration did not have any.
424426- **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).
425427- **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 <http://bugs.freepascal.org/view.php?id=19434>), Delphi compatibility.
426428- **Remedy**: Always specify default parameter values (also) in the interface/forward declaration of a routine.
427429
428430#### Default values are now properly typechecked
429431
430432- **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.
431433- **New behaviour**: The compiler now properly checks whether the type of the constant matches the parameter's type when parsing default values.
432434- **Reason**: Proper type checking is one of the fundamental properties of the Pascal language; Delphi compatibility.
433435- **Remedy**: Add a typecast around default values that now result in compiler errors, or correct the type of such parameters.
434436
435437#### "*strict protected*" visibility modifier
436438
437439- **Old behaviour**: *strict protected* did not correctly limit the visibility of symbols declared in different units.
438440- **New behaviour**: *strict protected* symbols can now only be accessed from descendent classes, regardless of where they are defined.
439441- **Reason**: Fix behaviour to conform to specification/documentation, Delphi compatibility.
440442- **Remedy**: Use *protected* or *public* if less strict accessibility checks are desired.
441443
442444#### Support for type helpers added
443445
444446- **Old behaviour**: In modes *ObjFPC* and *MacPas* it was possible to declare a unique type of a type *helper*.
445447- **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).
446448- **Example**:
447449
448450``` pascal
449451{$mode objfpc}
450452type
451453 helper = LongInt;
452454
453455 otherhelper = type helper;
454456```
455457
456458The above code will no longer compile.
457459
458460- **Reason**: *type helper* is a more logical way to declare helpers for primitive types than Delphi's *record helper* is.
459461- **Remedy**: Escape the keyword *helper* using a *&*. E.g.:
460462
461463``` pascal
462464{$mode objfpc}
463465type
464466 helper = LongInt;
465467
466468 otherhelper = type &helper;
467469```
468470
469471#### "*strict protected*" and "*protected*" visibility modifier in extended records
470472
471473- **Old behaviour**: *strict protected* and *protected* could be used used in extended records.
472474- **New behaviour**: *strict protected* and *protected* are no longer allowed in extended records.
473475- **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.
474476- **Remedy**: Use *private* instead of *protected* and *strict private* instead of *strict protected*.
475477
476478#### "*static*" directive on non-class methods
477479
478480- **Old behaviour**: It was possible to use the *static* on normal, non-*class* methods
479481- **New behaviour**: The compiler now generates an error if *static* is used on normal, non-*class* methods (except in *object* types)
480482- **Reason**: It is only correct to leave out the *Self* parameter if it is a class method. This is also Delphi compatible.
481483- **Remedy**: Prepend the *class* keyword to the method.
482484
483485#### "*static*" directive on class operators
484486
485487- **Old behaviour**: It was possible to use the *static* on class operators.
486488- **New behaviour**: The compiler now generates an error if *static* is used on class operators.
487489- **Reason**: Class operators are by definition static, thus the *static* would be redundant. This is also Delphi compatible.
488490- **Remedy**: Remove the *static* keyword from class operators.
489491
490492#### Classes implementing forward-declared interfaces
491493
492494- **Old behaviour**: It was possible to declare classes as implementing a forward-declared interface.
493495- **New behaviour**: Classes can no longer implement forward-declared interfaces.
494496- **Reason**: This occasionally [caused crashes](http://bugs.freepascal.org/view.php?id=24184), 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.
495497- **Remedy**: If there is a cyclic dependency between a class and an interface, use a forward declaration for the class instead.
496498
497499#### Using the function name as alias for loading its current result value in MacPas mode
498500
499501- **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.
500502- **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.
501503- **Reason**: The old behaviour existed because under **some** circumstances CodeWarrior behaved that way. Under other circumstances [it however behaves according to the new rule](http://bugs.freepascal.org/view.php?id=22344) 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.
502504- **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.
503505
504506#### nostackframe forbidden for Pascal subroutines
505507
506508- **Old behaviour**: The nostackframe directive could be applied to all types of subroutines.
507509- **New behaviour**: The nostackframe directive is allowed only for pure assembler subroutines,
508510- **Reason**: Depending on the architecture, ABI and code of the subroutine, nostackframe might have worked or caused random crashes. This was unpredictable and makes no sense.
509511- **Remedy**: Remove the nostackframe from Pascal subroutines. In any case, if the compiler can omit the stack frame, it will do so.
510512
511513#### Conversion preference of pansichar to various string types
512514
513515- **Old behaviour**: In {\$h-} mode, the compiler preferred *pansichar*-\>*shortstring* to *pchar*-\>*ansistring* conversions, and gave *pansichar*-\>*ansistring* and *pchar*-\>*unicodestring* the same conversion preference.
514516- **New behaviour**: The compiler now always prefers *pansichar*-\>*ansistring* to *pansichar*-\>*shortstring*, and also prefers *pansichar*-\>*ansistring* to *pansichar*-\>*unicodestring* (which it in turn prefers to *pansichar*-\>*shortstring*).
515517- **Reason**: Prevent truncation of long pchars, make it easier to add unicodestring overloads to the RTL without causing *can't decide which overloaded function to call* errors when using pchars, Delphi compatibility.
516518- **Remedy**: Use *strpas()* to explicitly truncate pchars to shortstrings if desired.
517519
518520#### Comparative operators can have any result type
519521
520522- **Old behaviour**: Overloaded comparative operators could only have a *Boolean* result type.
521523- **New behaviour**: Overloaded comparative operators can have any result type.
522524- **Reason**: The result type is checked by the regular type checking mechanism. For example, overloaded comparative operators that return non-Boolean results cannot be used in IF, WHILE or UNTIL expressions, but it is still possible to use them in other situations. This is also Delphi compatible.
523525- **Example**:
524526
525527``` pascal
526528SQLResult := Database.Query(
527529 Select(
528530 [ PersonsTable.FirstName, PersonsTable.LastName ],
529531 [ PersonsTable ],
530532 [
531533 PersonsTable.Country = 'NL',
532534 PersonsTable.Age >= 25
533535 ]
534536 )
535537);
536538```
537539
538540- **Remedy**: Not applicable.
539541
540542#### True and False are not keywords anymore
541543
542544- **Old behaviour**: True and False were keywords and as a result it was not possible to use them as identifiers.
543545- **New behaviour**: True and False are now predefined constants in the system unit's scope and can be used as identifiers.
544546- **Example**:
545547
546548``` pascal
547549const
548550 False = 0;
549551 True = 1;
550552```
551553
552554- **Reason**: Compatibility with other Pascal compilers.
553555- **Remedy**: Not applicable.
554556
555557#### For-in loop variable cannot be assigned to anymore
556558
557559- **Old behaviour**: Inside a *for X in Y* loop it was possible to assign a value to X. This was different from the *for X:=A to B* loop, where assigning to the loop variable X was not allowed.
558560- **New behaviour**: The variable X of a *for X in Y* loop cannot be changed.
559561- **Reason**: Compatibility with for *X:=A to B* loop.
560562- **Remedy**: Use a temporary variable instead.
561563
562564#### Casting integer variables to floating point
563565
564566- **Old behaviour**: Explicitly typecasting an integer variable to a floating point type of the same size caused the bit pattern of the integer to be reinterpreted as a floating point value.
565567- **New behaviour**: Such explicit typecasts now result in a conversion of the integer value to an equal floating point value (to the extent that the floating point type can represent the integer value)..
566568- **Example**: The following program now prints twice " 1.3890388970000000E+009", while previously the first writeln printed " 6.86276399744918E-315"
567569
568570``` pascal
569571var
570572 i: int64;
571573begin
572574 i:=1389038897;
573575 writeln(Double(i))
574576 writeln(Double(1389038897))
575577end.
576578```
577579
578580- **Reason**: Consistency with the behaviour of a compile-time integer to floating point conversions, as demonstrated by the above example.
579581- **Remedy**: Add an intermediate typecast to a record type to reinterpret the actual bit pattern.
580582
581583## Unix platforms
582584
583585### cthreads: critical sections and recursive mutex support
584586
585587- **Old behaviour**: If the *cthreads* unit thread manager was used on a platform without recursive mutex support, critical sections were non-reentrant.
586588- **New behaviour**: Initialising a critical section under the above circumstances will now result in a run time error.
587589- **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.
588590- **Remedy**: Use an RTLEvent instead if reentrancy is not required.
589591
590592## Darwin platforms
591593
592594### Location of certain function result types on Darwin/i386 and iPhoneSim/i386
593595
594596- **Old behaviour**: Small records and method pointers were always returned according to the official ABI.
595597- **New behaviour**: When a calling convention other than *cdecl*, *cppdecl* or *mwpascal* is used, the same convention as on other platforms is now used.
596598- **Reason**: Better compatibility with assembler code written for other platforms.
597599- **Remedy**: Update your assembler code, or better: if possible, convert it to Pascal.
598600
599601### Default assembler for Darwin/i386/x86_64/ARM and iPhoneSimulator/i386/x86_64
600602
601603- **Old behaviour**: The default assembler for these platforms was the *as* binary.
602604- **New behaviour**: The default assembler for these platforms now is the *clang* binary.
603605- **Reason**: Xcode 7 no longer includes the old assembler, and the *as* binary now simply invokes *clang*. Additionally, Xcode 7 now requires the compiler to specify the OS variant (OS X, iOS) and version to the assembler, which was not possible with the *as* binary that shipped with older Xcode versions. In order to disambiguate between an assembler that does and that does not support these options, we now explicitly invoke *clang* with these options.
604606- **Remedy**: If you have an older version of Xcode and wish to use the old assembler, you can use the *-Aas-darwin* command line option.
605607
606608### Default debug format for Darwin/i386
607609
608610- **Old behaviour**: The default debug format for Darwin/i386 was *Stabs*.
609611- **New behaviour**: The default debug format for Darwin/i386 is *DWARF 2*.
610612- **Reason**: The assembler included with Xcode 7 and later no longer supports Stabs.
611613- **Remedy**: If you have an older version of Xcode and wish to use Stabs, you can use *-Aas-darwin -gs* to force the use of the old assembler in combination with Stabs.
612614
613615### MacOSAll unit: changed parameter and opaque types
614616
615617- **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.
616618- **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).
617619- **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)
618620- **Changes:** (apart from the opaque type changes)
619621 - CGGLContextCreate : fixed first parameter (was "var", now is value parameter)
620622 - CFHostGetAddressing: var hasBeenResolved: boolean -\> booleanptr because can be nil
621623 - CFHostGetNames: var hasBeenResolved: boolean -\> booleanptr because can be nil
622624 - ColorSyncIterateInstalledProfiles: var seed: UInt32 -\> UInt32Ptr because can be nil
623625 - AudioStreamGetPropertyInfo: outSize and outWritable changed to pointer because can be nil
624626 - cblas (several var-parametes changed to pointers because they represent arrays):
625627 - cblas_sswap, cblas_dswap: X, Y
626628 - cblas_scopy, cblas_dcopy: Y
627629 - cblas_saxpy, cblas_daxpy: Y
628630 - catlas_saxpby, catlas_daxpby: Y
629631 - catlas_sset, catlas_dset: X
630632 - cblas_sscal, cblas_dscal: X
631633 - cblas_sgemv, cblas_dgemv: X
632634 - cblas_strmv, cblas_dtrmv: X
633635 - cblas_stbmv, cblas_dtbmv: X
634636 - cblas_stpmv, cblas_dtpmv: Ap, X
635637 - cblas_strsv, cblas_dtrsv: X
636638 - cblas_stbsv, cblas_dtbsv: X
637639 - cblas_stpsv, cblas_dtpsv: Ap, X
638640 - cblas_ssymv, cblas_dsymv: X
639641 - cblas_ssbmv, cblas_dsbmv: Y
640642 - cblas_sspmv, cblas_dspmv: Ap, Y
641643 - cblas_sger, cblas_dger: A
642644 - cblas_ssyr, cblas_dsyr: A
643645 - cblas_sspr, cblas_dspr: Ap
644646 - cblas_ssyr2, cblas_dsyr2: A
645647 - cblas_sspr2, cblas_dspr2: A
646648 - cblas_sgemm, cblas_sgemm: C
647649 - cblas_ssymm, cblas_Dsymm: C
648650 - cblas_ssyrk, cblas_dsyrk: C
649651 - cblas_ssyr2k, cblas_dsyr2k: C
650652 - cblas_strmm, cblas_dtrmm: B
651653 - cblas_strsm, cblas_strsm: B
652654 - vBLAS (idem)
653655 - SDOT: X, Y
654656 - SNRM2: X
655657 - SASUM: X
656658 - ISAMAX: X
657659 - SSWAP: X, Y
658660 - SCOPY: X, Y
659661 - SAXPY: X, Y
660662 - SROT: X, Y
661663 - SSCAL: X
662664 - SGEMV, A, X, Y
663665 - SGEMM: A, B, C
664666 - vDSP (idem)
665667 - vDSP_sve_svesq, vDSP_sve_svesqD: __vDSP_A
666668 - vDSP_normalize, vDSP_normalizeD: __vDSP_A, __vDSP_C
667669
668670## Windows 9x series
669671
670672### Windows 9x series unsupported
671673
672674- **Old behaviour**: While 2.6.x formally didn't support the Windows 9x Series, 3rd party maintenance kept most FPC 2.6.x versions working with the Windows 9x series (Windows 95, 98/98SE, ME), and problems were the exception rather than the rule.
673675- **New behaviour**: Starting from this compiler version, the Windows 9x series is not supported anymore.
674676- **Reason**: the Windows 9x series has been discontinued for a long time; there is no support (including support for newer Windows features) and no Microsoft online documentation. Supporting this platform has been increasingly difficult due to this and the number of users/developers interested in performing the development/test work.
675677- **Remedy**: users that want to use FPC for Win9x development can continue to use earlier compiler versions (e.g. FPC 2.6.4).
676678
677679## Windows/x86_64
678680
679681### Exception handling has been changed to be ABI-conformant
680682
681683- **Old behaviour**: Exceptions were handled using platform-independent mechanism based on SetJmp/LongJmp.
682684- **New behaviour**: Exceptions are handled using OS-provided means. The most important differences from generic handling are as follows:
683685 - 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.
684686 - 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.
685687 - 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.
686688- **Reason**: Multiple compatibility issues with Windows and third-party DLLs (see <http://bugs.freepascal.org/view.php?id=12974> and related issues)
687689- **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.
688690
689691### *winwidestringalloc* has been deprecated
690692
691693- **Old behaviour**: The *winwidestringalloc* variable enabled switching the WideString behaviour on Windows between COM BSTR (if set to true) and an internal UnicodeString-like container (if set to false).
692694- **New behaviour**: The ''winwidestringalloc"" has been deprecated and will be removed completely from the RTL code in the future.
693695- **Reason**: This setting predates the availability of the separate *UnicodeString* types, and was meant to enable Windows targets to use reference counted long strings. Nowadays, the *UnicodeString* type is available as an alternative on all platforms.
694696- **Remedy**: Check whether you set `winwidestringalloc := false` in your program code and if so, replace all *WideString* declarations with *UnicodeString*.
695697
696698## WinCE
697699
698700### Define *UNICODE* was changed to *FPC_OS_UNICODE*
699701
700702- **Old behaviour**: For arm-wince and i386-wince *UNICODE* was defined by default.
701703- **New behaviour**: For arm-wince and i386-wince *FPC_OS_UNICODE* is defined by default.
702704- **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 increases Delphi compatibility, as *UNICODE* is defined from Delphi 2009 on.
703705- **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.
704706
705707## Other
706708
707709### Stabs support has been disabled for 64 bit targets
708710
709711- **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.
710712- **New behaviour**: Only the DWARF debug format is still supported on 64 bit targets (except for AIX, where Stabx is used).
711713- **Reason**: Stabs is not well-defined for 64 bit targets, nor well-supported by gdb on those same targets. This can lead to [problems](http://bugs.freepascal.org/view.php?id=23365)
712714- **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.
713715
714716## Previous release notes
715717
716718---
717719*From the Free Pascal wiki, page "User Changes 3.0", as it stood on 2020-03-01 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history