Delphi Tokyo exception prevents setting function result
The Tokyo behaviour is correct. A function that raises an exception does not return a value. You have hitherto been relying on implementation detail.
Consider this code:
Result:=FuncTest;
This executes as follows:
FuncTest
is called.Result
is assigned.
Now, because step 1 raises an exception, step 2 does not execute.
If anything, I would say that the behaviour you report from earlier versions is dubious. In this function:
function Test:integer;
begin
Result:=0;
try
Result:=FuncTest;
finally
ShowMessage(Result.ToString);
end;
end;
The statement Result:=FuncTest
raises an exception and so Result
should not be modified by that statement. Another way to think of it is that the function is called but the assignment is not executed.
One of the problems with the Delphi ABI is that function return values are sometimes implemented as implicit var
parameters. Which means that the assignment may or may not happen. To demonstrate:
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TRec1 = record
X1: NativeInt;
end;
TRec2 = record
X1: NativeInt;
X2: NativeInt;
end;
function GetRec1: TRec1;
begin
Result.X1 := 1;
raise Exception.Create('');
end;
function GetRec2: TRec2;
begin
Result.X1 := 1;
raise Exception.Create('');
end;
procedure Main;
var
Rec1: TRec1;
Rec2: TRec2;
begin
Rec1 := Default(TRec1);
Writeln(Rec1.X1);
try
Rec1 := GetRec1;
except
end;
Writeln(Rec1.X1);
Rec2 := Default(TRec2);
Writeln(Rec2.X1);
try
Rec2 := GetRec2;
except
end;
Writeln(Rec2.X1);
end;
begin
Main;
Readln;
end.
This outputs:
0 0 0 1
Which is rather disappointing. It should not be possible to modify the caller's variable, but the use of an implicit var
parameter rather than a value return allows this leakage. In my view this is a serious flaw in the design of the Delphi ABI, a flaw that you will not find in most other languages.
In your code, there is no var
parameter because the return type is transferred in a register. In which case any Delphi version that outputs 2
is broken.
Fundamentally though, your code is mistaken in its expectations. If a function raises an exception then you must assume that the return value is ill-defined.
Finally, your code outputs 0
in XE3 and XE7, so I wonder how far back you need to go to see a value of 2
.