I am sorry to disappoint you but yes, its a bug and I say that because it seems we try to be Delphi compliant ..
Here is a more simplified chuck of code that breaks with 3.2.0 and maybe upwards..
This all works fine with 3.0.4 and a few down that I have used.
and to top it off, it also works in DELPHI and has for years..
So? It's still using undefined behaviour. That can be very nicely seen if the
inline is disabled:
program tinline;
{$mode objfpc}{$H+}
uses
SysUtils;
type
TForm1 = class
private
fCaption: String;
function GetCaption: String;
procedure SetCaption(const aValue: String);
published
property Caption: String read GetCaption write SetCaption;
end;
Procedure Ox(A:TForm1;Value:Integer);
Begin
A.Caption := value.Tostring;
End;
operator := (R:Integer):Tform1;{inline;}
Begin
Ox(Result,R);
end;
var
Form1: TForm1;
{ TForm1 }
function TForm1.GetCaption: String;
begin
Result := fCaption;
end;
procedure TForm1.SetCaption(const aValue: String);
begin
fCaption := aValue;
end;
begin
Form1 := TForm1.Create;
try
Form1 := 1;
finally
Form1.Free;
end;
end.
The generated assembly code on i386-win32 looks like this for the assignment operator:
.section .text.n_p$tinline_$$_assign$longint$$tform1,"x"
.balign 16,0x90
.globl P$TINLINE_$$_assign$LONGINT$$TFORM1
P$TINLINE_$$_assign$LONGINT$$TFORM1:
# [23] Begin
pushl %ebp
movl %esp,%ebp
leal -8(%esp),%esp
# Var R located at ebp-4, size=OS_S32
# Var $result located at ebp-8, size=OS_32
movl %eax,-4(%ebp)
# [24] Ox(Result,R);
movl -4(%ebp),%edx
movl -8(%ebp),%eax
call P$TINLINE_$$_OX$TFORM1$LONGINT
# [25] end;
movl -8(%ebp),%eax
movl %ebp,%esp
popl %ebp
ret
Here
-8(%ebp) contains the
Result value and as you can see it is not initialized in
any way, thus
Ox will access garbage. Now inlining has the restriction of not changing the behaviour of the code. Thus FPC 3.2.0 behaves correctly here. FPC 3.0.4 generates nearly identical code here if inlining is disabled.
That it behaves differently with active inlining on 3.0.4 or even Delphi is
no reason that the behaviour of these is
correct only that their code generators happen to generate the code in a way this works. This could behave totally different on a different platform, with different optimizations or e.g. on a LLVM-based backend which is known for aggressive optimizations (especially when undefined behaviour like this is involved).
Also depending on the code I can also get the same “incorrect” (from your PoV) behavior in FPC 3.0.4 which further shows that you're totally relying on circumstances that might change without any warning.
So, yeah, just don't do stuff like that.