Recent

Author Topic: Can someone with trunk Compiler above 3.0.4 test this code please.  (Read 635 times)

jamie

  • Hero Member
  • *****
  • Posts: 1123
I am curious if they have fixed this  yet?

This works perfectly correct In Delphi as it always has for years but not up to the compiler I currently use,
 3.04.

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3.   W:Word;
  4. begin
  5.   W := $01FF;
  6.   Caption := Hi(W+1).ToString;   //or use writeln in console mode, does not matter.  
  7.  

 The answer should be 2, but you'll see different....
as I said works perfectly in Delphi. This also affects overloading of local functions, too.
I know how to force it to work but you shouldn't have to.

  Back a piece this bug caused me a few hours of debugging porting an app over from Delphi..
 
 Please be advised to not do any math within your parameters of functions. You'll see why after you
study this one.

btw, the isn't a HI function issue, its a combination of overloaded functions that have Integer input options
over WORD, the compiler takes the high road and screws up your code.

Blaazen

  • Hero Member
  • *****
  • Posts: 2731
  • POKE 54296,15
    • Eye-Candy Controls
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #1 on: January 14, 2019, 03:54:04 am »
FPC 3.3.1 writes out 0.
When I change it to
Code: Pascal  [Select]
  1. Caption := Hi(Word(W+1)).ToString;
it writes out 2.

EDIT: No difference in {$mode objfpc} and {$mode delphi}.
« Last Edit: January 14, 2019, 03:58:33 am by Blaazen »
Lazarus 2.1.0 r59757M FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.11.2, Plasma 5.14.2
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

jamie

  • Hero Member
  • *****
  • Posts: 1123
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #2 on: January 14, 2019, 04:02:30 am »
You shouldn't need to do that..

Why won't they make the compiler behave correctly is beyond me...

 Don't they realize what a disaster it becomes when dealing with lesser of types below integer and
doing math within?
   
  If you were to have two functions locally overloaded, one with a WORD input and the other INTEGER input and do
math like that, the compiler comes up and tells you it can't figure out which one to use..
   
  I think it should be obvious...

 Oh well, such for progress.


440bx

  • Sr. Member
  • ****
  • Posts: 427
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #3 on: January 14, 2019, 05:58:44 am »
You shouldn't need to do that..

Why won't they make the compiler behave correctly is beyond me...
Definitely a bug, did you report it ?    if the answer is yes, what was the feedback you got on that bug report ?

PascalDragon

  • Full Member
  • ***
  • Posts: 235
  • Compiler Developer
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #4 on: January 14, 2019, 09:37:37 am »
In FPC expressions are evaluated using the native width of the platform (e.g. LongInt on 32-bit and Int64 on 64-bit), thus "W + 1" becomes of type LongInt.
It's nowhere documented in Delphi that Word + Constant stays a Word and thus this is essentially an implementation detail and those are notoriously hard to get right as more often than not there pops up a situation where it will behave differently.
We already have a bug report about this where this is explained as well.

440bx

  • Sr. Member
  • ****
  • Posts: 427
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #5 on: January 14, 2019, 08:42:26 pm »
In FPC expressions are evaluated using the native width of the platform (e.g. LongInt on 32-bit and Int64 on 64-bit), thus "W + 1" becomes of type LongInt.
It's nowhere documented in Delphi that Word + Constant stays a Word and thus this is essentially an implementation detail and those are notoriously hard to get right as more often than not there pops up a situation where it will behave differently.
We already have a bug report about this where this is explained as well.
Your explanation is quite reasonable and, for the most part, it makes perfect sense.

The difference between when Delphi and Fpc choose to do type promotion can lead to some subtle, difficult to find to bugs, as @Jamie showed.  I would lean towards being as close to Delphi as possible when choosing when to do type promotion because, it is something that definitely affects compatibility.

Just for fun and for the record, the following code:
Code: Pascal  [Select]
  1. var w : word;
  2. ...
  3. begin
  4.   inc(w);  // doesn't do type promotion, it increments the word
  5.  
  6.   w += 1; // does type promotion to int32 and demotion (a good bit slower than inc, of course.)
  7. end.
  8.  
  9. // the first statement isn't treated as an expression while the second one is even though
  10. // they are semantically identical.
  11.  
  12. // I cannot think of a case when the difference would cause some unexpected side effect but,
  13. // obviously, that doesn't mean there isn't one.
  14.  

Bart

  • Hero Member
  • *****
  • Posts: 3247
    • Bart en Mariska's Webstek
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #6 on: January 14, 2019, 10:19:37 pm »
The point here is that Delphi's bejeviour is not documented at all, while FPC's is.
From the point of view of the fpc developers this behaviour in Delphi therefore is an implementation detail, which may alter at any given next Delphi.

Bart

440bx

  • Sr. Member
  • ****
  • Posts: 427
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #7 on: January 14, 2019, 10:33:38 pm »
... <snip> ... this behaviour in Delphi therefore is an implementation detail, which may alter at any given next Delphi.
It seems unlikely that Embarcadero would change that behavior because, first, it's hard to see any good reason to change it and, second, they know that such a change would very likely break some code leaving the code developers with some hard to find bugs.

It would also require changes in how Delphi generates code for overflow checking. 

I will grant you that, they can/could change it if they wanted to but, if they did, they would create a lot of headaches for themselves and the developers using their product.  Doesn't seem likely.

It would be quite "nice" if FPC was type-promotion compatible with Delphi.  It would definitely help in porting Delphi code to FPC.




Bart

  • Hero Member
  • *****
  • Posts: 3247
    • Bart en Mariska's Webstek
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #8 on: January 14, 2019, 10:41:01 pm »
It would be quite "nice" if FPC was type-promotion compatible with Delphi.  It would definitely help in porting Delphi code to FPC.

Wouldn't that break backwards compatibility for fpc programs?

Bart

440bx

  • Sr. Member
  • ****
  • Posts: 427
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #9 on: January 14, 2019, 10:52:28 pm »
It would be quite "nice" if FPC was type-promotion compatible with Delphi.  It would definitely help in porting Delphi code to FPC.

Wouldn't that break backwards compatibility for fpc programs?

Bart
I have to admit, it has that potential but, I am under the impression that Delphi compatibility is, so to speak, a "primordial" goal of FPC.


Blaazen

  • Hero Member
  • *****
  • Posts: 2731
  • POKE 54296,15
    • Eye-Candy Controls
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #10 on: January 14, 2019, 10:55:33 pm »
Quote
I have to admit, it has that potential but, I am under the impression that Delphi compatibility is, so to speak, a "primordial" goal of FPC.
In {$mode Delphi} only.
Lazarus 2.1.0 r59757M FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.11.2, Plasma 5.14.2
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

jamie

  • Hero Member
  • *****
  • Posts: 1123
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #11 on: January 14, 2019, 11:12:39 pm »
That would absolutely NOT break anything in FPC, in fact, it would most likely help make some of these
random bugs go away..

 The compiler has a problem and there is no getting around it. You can argue the point until the cows come
home and even then, the point is still valid.

 back in my college days pascal on the mainframe was one of the languages we were taught, kind of
archaic but at least is was something. Back then it was very clear how a CONSTANT is to be treated.

The argument on the left of a non constant dictates what the constant type is going to be for that case, unless
it can not be resolved then the system generates a fault at error check time.

 Delphi fallows this perfectly.

Now take this example

AWordVariable := AWordVarliable+1;

Fpc handles this correctly although doing the AWordVariable+1 will result in a integer in the background but
the compiler knows that it has to demote the type to a WORD, this is done correctly, why can't it do it for
parameters ?

Now this is where it falls apart.

 DOing these same steps with in a Function parameter (….) decides to not demote the type back to where it
should be but instead change it to a integer level and if you are calling system in a remote unit like the system
unit, it does not complain, just picks the wrong overload..

But if you do the math outside and the pass the results the compiler then keeps it as a WORD, that is obvious
since we showed that.

Are we starting to see the picture here?
---------------------------------------------
Another way this falls apart in your code.

Procedure Test(W:Word); overload;
Procedure Test(I:Integer);overload;

Test(SomeWord+1);
---
The last time I checked, the compiler will stop and tell you it can't figure out which one to use.
at least it knows there is a comflict, one that it is causing on its own.

Simply put, it needs to do a silent cast to prevent this and if the user decides to cast it to a higher level
then the compiler can take  route since it has already promoted it in the background.
« Last Edit: January 14, 2019, 11:26:18 pm by jamie »

440bx

  • Sr. Member
  • ****
  • Posts: 427
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #12 on: January 14, 2019, 11:25:48 pm »
In {$mode Delphi} only.
True but,  it would seem cumbersome and also undesirable to have two different type-promotion models, one for {$mode Delphi} and another for other modes when one consistent, compatible and unified, model should be sufficient.

It should be noted that the difference in the result between FPC and Delphi is due to the fact that "hi" is taking the "hi" of the promoted type instead of the base type.  if the compiler had demoted the result back to "word", the result would be the same as Delphi's.

it should also be noted that the programmer didn't ask for "hi" of a DWORD, the programmer asked for "hi" of a "word".  In the case of @Jamie's expression, if the programmer wanted the "hi" of a type different than the base type (word, in this case) then, the programmer is expected to cast the variable/result to the desired type.

... <snip> ... the compiler knows that it has to demote the type to a WORD

That's the real problem.  It applied a function ("hi" in this case) to a type that is not the programmer-specified type.


jamie

  • Hero Member
  • *****
  • Posts: 1123
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #13 on: January 14, 2019, 11:31:25 pm »
as I can remember back in my College days

A Pascal equation is evaluated at its highest level of procession types to use and then reduced to the
desired medium. In most cases the desired level is the integer;

fpc gets it right when not dealing with parameters but complains about constants with warnings when it
shouldn't...

 Constants are suppose to be fluid in type unless it is impossible to resolve, for example a decimal type
used with a integer variable.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 6674
Re: Can someone with trunk Compiler above 3.0.4 test this code please.
« Reply #14 on: January 15, 2019, 04:09:54 pm »
I have to admit, it has that potential but, I am under the impression that Delphi compatibility is, so to speak, a "primordial" goal of FPC.

IIRC the FPC behaviour dates from before Delphi compatibility. It was an attempt to keep 16-bits TP sources running with 32-bit datatypes.

However since FPC itself is written in its own mode, it was iirc decided to keep this. It was not considered a big deal because usage of such old 16-bits primitives in new Delphi code was considered old/deprecated.

However since then we have learned that Delphi devels use every dirty trick in the book till you get a "deprecated" warning. (and sometimes even then)