Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2010-01

Compiler bug?

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Paul van Helden

Hi All,

I hope I'm doing something really dumb, but I have to say it is stuff like this that is really disheartening to me. I've been using FPC/Lazarus for a year now and I have to report that my rate of development (compared to Delphi) has slowed down significantly...

The following simple program shows that calling an overloaded method from its "twin" returns garbage:

program project1;
{$mode objfpc}{$H+}
type
   TMyClass = class
   public
     function GetValue_not_overloaded: Integer;
     function GetValue_overloaded: Integer; //overload; -- nice feature
not having to specify "overload"!
     function GetValue_overloaded(SomeValue: Integer): Integer; //overload;
   end;
function TMyClass.GetValue_not_overloaded: Integer;
begin
   Result:=1;
end;
function TMyClass.GetValue_overloaded: Integer;
begin
   Result:=2;
end;
function TMyClass.GetValue_overloaded(SomeValue: Integer): Integer;
begin
   case SomeValue of
     1: Result:=GetValue_overloaded; // compiler warning: "Function
result variable does not seem to be initialized" (!)
     2: Result:=GetValue_not_overloaded;
   else
     Result:=3;
   end;
end;
var
   C: TMyClass;
   R: Integer;
begin
   C:=TMyClass.Create;
   R:=C.GetValue_overloaded; // direct call works
   WriteLn('Correct value: ', R);
   R:=C.GetValue_overloaded(2); // overloaded function calls non
overloaded function, works
   WriteLn('Correct value: ', R);
   R:=C.GetValue_overloaded(1); // should return 2, I'm getting random
numbers starting with 422...
   WriteLn('Random value: ', R);
   ReadLn;
end.

I have tested this with Lazarus 0.9.28.2 (release) and its FPC 2.2.4, a fresh build of Lazarus from SVN and FPC 2.4.1 as well as FPC 2.5.1 from SVN. The only difference is the actual incorrect value returned! The value isn't really random, it is the same each time a specific binary is run and always start with 422...
FPC 2.2.4: 4221677
FPC 2.4.1: 4223590
FPC 2.5.1: 4220774

Now (assuming I'm not doing something dumb) if this had been a bug in FPC trunk I can understand, but how can such a (common?) use case not have been spotted over all these versions?

Perhaps it is bad form to use overloaded functions in such a way, and perhaps I'm just frustrated because I'm using an old version of Delphi to debug my code, then when I compile it in Lazarus my app implodes. I like the latest debugger improvements but I still cannot inspect an array element. (If there is a way, please let me know).

Regards,

Paul.

Reply by email

cobines
to Paul van Helden

2010/1/31 Paul van Helden :

Show quoted text 10 lines
function TMyClass.GetValue_overloaded(SomeValue: Integer): Integer; begin  case SomeValue of    1: Result:=GetValue_overloaded; // compiler warning: "Function result variable does not seem to be initialized" (!)    2: Result:=GetValue_not_overloaded;  else    Result:=3;  end; end;

Isn't the "GetValue_overloaded" in

  1: Result:=GetValue_overloaded

the return value of the function?

Maybe you should call it this way:

Result:= GetValue_overloaded()

That's why I think you get the warning.

The reason you might be getting random results is that the return value has not been initialized.

cobines

Reply by email

Paul van Helden
to cobines

Of course.... Thanks Cobines!

I have never used the function name instead of "Result", but of course you can. Using () after a function to me seems so C-like and un-Pascallish but it works.

But it is things like this that trip up people coming from Delphi, I guess. Isn't this a potential improvement to the compiler though: scan for overloaded functions before assuming that it is the result value (like Delphi does)? (Or warn about overloaded functions without parameters, similar to mode objfpc disallowing parameter names that are the same as methods?)

cobines wrote 17 lines
Isn't the "GetValue_overloaded" in 1: Result:=GetValue_overloaded the return value of the function? Maybe you should call it this way: Result:= GetValue_overloaded() That's why I think you get the warning. The reason you might be getting random results is that the return value has not been initialized.

Reply by email

cobines
to Paul van Helden

2010/1/31 Paul van Helden :

Show quoted text 6 lines
But it is things like this that trip up people coming from Delphi, I guess. Isn't this a potential improvement to the compiler though: scan for overloaded functions before assuming that it is the result value (like Delphi does)? (Or warn about overloaded functions without parameters, similar to mode objfpc disallowing parameter names that are the same as methods?)

Just checked that if you use {$mode delphi} instead of {$mode objfpc} then using:

Result:=GetValue_overloaded;

is correct.

cobines

Reply by email

Daniël Mantione
to Paul van Helden: Of course.... Thanks Cobines! I have never used the function name instead of "Result",…

Op Sun, 31 Jan 2010, schreef Paul van Helden:

Show quoted text 11 lines
Of course.... Thanks Cobines! I have never used the function name instead of "Result", but of course you can. Using () after a function to me seems so C-like and un-Pascallish but it works. But it is things like this that trip up people coming from Delphi, I guess. Isn't this a potential improvement to the compiler though: scan for overloaded functions before assuming that it is the result value (like Delphi does)? (Or warn about overloaded functions without parameters, similar to mode objfpc disallowing parameter names that are the same as methods?)

This behaviour is intentional to allow you to read instead of just write the function result. The incompatibility just affects recursive procedures without parameters, which seldomly occurs, because normally the parameters determine the behaviour of the function, and a recursive function without parameters would prevent you writing a mechanism that makes the recursive function terminate.

Only if the behaviour of the recursive function is controller by global variables, then you can actually write a recursive function without parameters. Because this is so seldom, and the desire to read from the function result is extremely common, there is a strong case for this behaviour.

Indeed Borland did invent "result" as a method to read from the function result, so FPC had to support that too.

Daniël

Reply by email

Paul van Helden
to Daniël Mantione
Daniël Mantione wrote 13 lines
This behaviour is intentional to allow you to read instead of just write the function result. The incompatibility just affects recursive procedures without parameters, which seldomly occurs, because normally the parameters determine the behaviour of the function, and a recursive function without parameters would prevent you writing a mechanism that makes the recursive function terminate. Only if the behaviour of the recursive function is controller by global variables, then you can actually write a recursive function without parameters. Because this is so seldom, and the desire to read from the function result is extremely common, there is a strong case for this behaviour.

OK, thanks. Also to Cobines for pointing out $mode delphi works as (I) expected. I'm deliberately writing new units to compile with $mode objfpc so I still have lots to learn. I do think a compiler hint would be nice, either at the method declaration ("Hint: Overloaded function without parameters may conflict with function result value.") or when using the function name as the result in code ("Hint: Ambiguous use of function name; use () if you wanted to call the overloaded function instead"). Or perhaps I must get used to using() for functions without parameters, and even better: give me another $mode where (like C++) MethodName; is equivalent to @MethodName, so I'd be forced to use (). :-)

Indeed Borland did invent "result" as a method to read from the function result, so FPC had to support that too.

I must say I prefer Result. It reads much easier, so I'd say it is more to the spirit of Pascal than to have to use () to disambiguate things. (So Borland /did/ actually invent some useful stuff....)

Being able to read the result is +1 Pascal, -1 C. If only I can have "var I, J: Integer;" anywhere between a begin and end and (inline) method implementations inside class definitions... sigh :-)

And to regain my productivity: to figure out how to debug with Lazarus the way I'm used to in Delphi...

Regards,

Paul.

Reply by email

Marco van de Voort
to Paul van Helden: Of course.... Thanks Cobines! I have never used the function name instead of "Result",…

In our previous episode, Paul van Helden said:

Show quoted text 10 lines
I have never used the function name instead of "Result", but of course you can. Using () after a function to me seems so C-like and un-Pascallish but it works. But it is things like this that trip up people coming from Delphi, I guess. Isn't this a potential improvement to the compiler though: scan for overloaded functions before assuming that it is the result value (like Delphi does)? (Or warn about overloaded functions without parameters, similar to mode objfpc disallowing parameter names that are the same as methods?)

For what Delphi does, there is $mode delphi. Mode objfpc has a significant part of the combined FPC/Lazarus dialect written in it, which might actually use the function result TP style.

Reply by email

Graeme Geldenhuys
to Paul van Helden: OK, thanks. Also to Cobines for pointing out $mode delphi works as (I) expected. I'm…
Paul van Helden wrote
And to regain my productivity: to figure out how to debug with Lazarus the way I'm used to in Delphi...

I miss this too, though recently there was a lot of improvements to debugging support. All I can say is, be thankful you didn't start 5 years ago with FPC where debugging was much worse. I now got so used to using log files for debugging, I actually forgot how easy and reliable it was to debug in Delphi 7 and Kylix 3 IDE's. Oh well, FPC brings many other features to the table which still makes it far better than using Delphi and Kylix.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email