Prof A Olowofoyeku wrote:
On 8 Mar 2005 at 5:09, Waldek Hebisch wrote:
Another problem with function types. Delphi and BP do not accept this program;
program bug1; {$X+} type tfunc = function : pointer; var bar : tfunc; function foo : integer; begin foo := 1024 * 2; end; begin bar := tfunc (foo); { this is where Delphi and BP barf } writeln (integer (bar)); end.
GPC compiles the code, and then the program proceeds to crash when it is run. FreePascal compiles the code, and runs it correctly without crashing. Delphi accepts this instead "bar := tfunc (@foo);", and GPC of course accepts it. Both run it correctly. BP does not accept it - but that is not imporant.
The question is: should GPC compile "bar := tfunc (foo);" only for the program to crash when it gets there? If GPC refuses to compile it, that would be consistent with both BP and Delphi. If GPC compiles it and the program runs correctly, that would be fine also. But if the program will crash, then perhaps GPC should refuse to compile the line. Any comments? Thanks.
The differences are: 1) GPC allows casting integers to function types 2) Inside a cast to function type GPC calls `foo'. It seems that FPC just uses adress of `foo'.
Concering 1: it is dangerous, but sometimes convenient. Usually we prefer safe constructs and implement unsafe versions only for compatibility. But casts are dangerous anyway... Of course, we could requrire double casts (which even now are sometimes necessary) like: tfunc (pointer(foo))
Concering 2: There is genuine ambiguity here. Namely, for parameterless function we can either call the function and cast the value or cast the reference to the function. Arguably, the second choice is more natural. But assuming that we need to mix functions and integers (say, in an interpreter for untyped language), then we may wish to write:
program bug1; {$X+} type tfunc = function : pointer; function baz : integer; begin baz := 1024 * 2; end; var bar : tfunc; function foo : integer; begin foo := integer(@baz); end; begin bar := tfunc (foo); { this is where Delphi and BP barf } writeln (integer (bar)); end.
For this program GPC gives "correct" result. In default mode FPC rejects it, in Delphi mode FPC accepts it but gives "wrong" result. BTW, when I write:
bar := tfunc (foo());
then my copy of FPC (1.9.4 on Debian) still gives wrong result.
As you can see there is real mess here. I agree that on your example FPC way is more usefull than GPC way. But before we change GPC we should know what _exact_ rules BP, Delphi and FPC use (BTW any dialect with casts and function types is worth checking (Mac ???)). Also, we need to distinguish intended behaviour and bugs (I consider FPC treatment of `tfunc (foo());' as an obvious bug).