Sign in Join

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

Mailing lists / fpc-devel / 2005-06

Bug 4004

13 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

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

Colin Western

Can I ask somebody to have another look at this bug - it was flagged unreproducable on the web system, but I still get it from the current svn as shown below.
(Note that the orginal report was on ppc but I have the same fault on i386) Colin

$ fpc ord.pas
Free Pascal Compiler version 2.1.1 [2005/06/04] for i386 Copyright (c) 1993-2005 by Florian Klaempfl
Target OS: Linux for i386
Compiling ord.pas
Linking ord
13 Lines compiled, 0.0 sec
$ ./ord
-1
Runtime error 215 at $080480C5
$080480C5
$0804813A

$ more ord.pas
{$R+}{$Q+}
function d(a,b:Char):Integer;
begin
  d := Ord(a)-Ord(b);
end;
var
  i: Integer;
begin
  i := Ord('0')-Ord('1');
  WriteLn(i);
  WriteLn(d('0','1'));
end.

Reply by email

Gerhard Scholz
to Colin Western

The check for overflow is obviously implemented different in 2.0.0 and 2.1.1

This is the line

    d := Ord(a)-Ord(b)

in the function, translation result to assembler:

with 2.0.0 (win32):

.Ll2:
.stabn 68,0,6,.Ll2 - P$TORD_D$CHAR$CHAR$$SMALLINT
# [6] d := Ord(a)-Ord(b);
movzbl -4(%ebp),%edx
movzbl -8(%ebp),%eax
subl %eax,%edx
jno .L8
call FPC_OVERFLOW
.L8:
movl %edx,%eax
subl $-32768,%eax
cmpl $65535,%eax
jbe .L9
call FPC_RANGEERROR
.L9:
movw %dx,-12(%ebp)
.Ll3:

with 2.1.1 (win32):

.Ll2:
.stabn 68,0,6,.Ll2 - P$TORD_D$CHAR$CHAR$$SMALLINT
# [6] d := Ord(a)-Ord(b);
movzbl -4(%ebp),%edx
movzbl -8(%ebp),%eax
subl %eax,%edx
jae .L8
call FPC_OVERFLOW
.L8:
movl %edx,%eax
cmpl $32767,%eax
jbe .L9
call FPC_RANGEERROR
.L9:
movw %dx,-12(%ebp)
.Ll3:

A solution would be to replace that line by:
    d := integer(Ord(a))-Ord(b)

It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - BYTE shall give a BYTE, and -1 is not in the range allowed for a BYTE.

The line " i := Ord('0')-Ord('1') " in the main program is not interesting,
since it contains a constant expression and is converted to " i := -1 " by
the compiler.

Greetings

gs

Earlier message 47 lines
----- Original Message ----- From: "Colin Western" To: "FPC developers' list" Sent: Saturday, June 04, 2005 1:38 PM Subject: [fpc-devel] Bug 4004 > Can I ask somebody to have another look at this bug - it was flagged > unreproducable on the web system, but I still get it from the current > svn as shown below. > (Note that the orginal report was on ppc but I have the same fault on i386) > Colin > > $ fpc ord.pas > Free Pascal Compiler version 2.1.1 [2005/06/04] for i386 > Copyright (c) 1993-2005 by Florian Klaempfl > Target OS: Linux for i386 > Compiling ord.pas > Linking ord > 13 Lines compiled, 0.0 sec > $ ./ord > -1 > Runtime error 215 at $080480C5 > $080480C5 > $0804813A > > $ more ord.pas > {$R+}{$Q+} > function d(a,b:Char):Integer; > begin > d := Ord(a)-Ord(b); > end; > > var > i: Integer; > begin > i := Ord('0')-Ord('1'); > WriteLn(i); > WriteLn(d('0','1')); > end. > > > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel >

Reply by email

Colin Western
to Gerhard Scholz

Gerhard Scholz wrote:
<snip>

It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - BYTE shall give a BYTE, and -1 is not in the range allowed for a BYTE.

Thanks for taking a am reasonably sure that this
beheviour is wrong, (otherwise you could never take the difference between unsigned values) but I was concerned that as it was flagged unreproducable on the bug tracker I had messed up my compilation of fpc in some way. As it seems I havn't, perhaps I should re-submit it.

Show quoted text 5 lines
The line " i := Ord('0')-Ord('1') " in the main program is not interesting, since it contains a constant expression and is converted to " i := -1 " by the compiler.

... though this should have given a compile time range check error because the types are the same

Colin

Reply by email

Hans-Peter Diettrich
to Gerhard Scholz: The check for overflow is obviously implemented different in 2.0.0 and 2.1.1 This is the…
Gerhard Scholz wrote
The check for overflow is obviously implemented different in 2.0.0 and 2.1.1

I'm not sure, at least

.L9: movw %dx,-12(%ebp) .Ll3:

suggests that the target is not an integer, but instead is a (possibly unsigned) word type. Please check again!

Show quoted text 5 lines
A solution would be to replace that line by: d := integer(Ord(a))-Ord(b) It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - BYTE shall give a BYTE, and -1 is not in the range allowed for a BYTE.

Differences always should be interpreted as signed values, the error message IMO comes from the final assignment.

The line " i := Ord('0')-Ord('1') " in the main program is not interesting, since it contains a constant expression and is converted to " i := -1 " by the compiler.

Now you assume that the difference can exceed the range of Ord(char), when computed at compile time? Or is it only the different type of the target variable?

DoDi

Reply by email

Peter Vreman
to Hans-Peter Diettrich
Show quoted text 23 lines
Gerhard Scholz wrote: > > The check for overflow is obviously implemented different in 2.0.0 and > 2.1.1 I'm not sure, at least > .L9: > movw %dx,-12(%ebp) > .Ll3: suggests that the target is not an integer, but instead is a (possibly unsigned) word type. Please check again! > A solution would be to replace that line by: > d := integer(Ord(a))-Ord(b) > > It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - > BYTE > shall give a BYTE, and -1 is not in the range allowed for a BYTE. Differences always should be interpreted as signed values, the error message IMO comes from the final assignment.

What with cardinal-cardinal and pointer-cardinal or pointer-byte? Those can't be represented by a longint (the native singed type of pascal). In 2.0.0 the those were converted to int64 values, but users were complaining about the warnings that were generated.

Reply by email

Gerhard Scholz
to Colin Western: <snip> Thanks for taking a am reasonably sure that this beheviour is wrong, (otherwise…

There are two philosophies behind that.

One philosophy is that <type> <op> <type> produces a <type> again (for <op> out of [ + - * / div and or mod]) ("/" for reals only; "div" and "mod" of ints only of course). "Widening" is done when the 2 types are not identical but compatible, e.g. "byte + integer" would be done as "integer(byte) + integer".

The other philosophy is to wide every operand to a reasonable size (for example Longint) and do the computation then.

Both philosophies can be found in different compilers. For keeping your code transportable you should anyhow obey the first philosophy. If neccessary, as in your code, do the typecast yourself, as I showed you:

   i := INTEGER ( Ord(a) ) - Ord(b)

Then you are on the safe side of life.

Your "constant" line, which compiled "correct":

  i := Ord('0')-Ord('1')

seems to be a little compiler "weakness".

Gerhard

Earlier message 37 lines
----- Original Message ----- From: "Colin Western" To: "FPC developers' list" Sent: Monday, June 06, 2005 10:24 PM Subject: Re: [fpc-devel] Bug 4004 > Gerhard Scholz wrote: > <snip> > > >It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - BYTE > >shall give a BYTE, and -1 is not in the range allowed for a BYTE. > > > > > Thanks for taking a am reasonably sure that this > beheviour is wrong, (otherwise you could never take the difference > between unsigned values) but I was concerned that as it was flagged > unreproducable on the bug tracker I had messed up my compilation of fpc > in some way. As it seems I havn't, perhaps I should re-submit it. > > >The line " i := Ord('0')-Ord('1') " in the main program is not interesting, > >since it contains a constant expression and is converted to " i := -1 " by > >the compiler. > > > > > ... though this should have given a compile time range check error > because the types are the same > > Colin > > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel >

Reply by email

Gerhard Scholz
to Hans-Peter Diettrich: I'm not sure, at least suggests that the target is not an integer, but instead is a…

...

Show quoted text 8 lines
I'm not sure, at least > .L9: > movw %dx,-12(%ebp) > .Ll3: suggests that the target is not an integer, but instead is a (possibly unsigned) word type. Please check again!

...

This is the result of the compilation: "ppc386 tord -al" (shortened of course).

Since "MOVW" moves 16-bit values, it does not matter if it's signed or not, it just has to be 16 bit of something.

That "MOVW" occurs with range/overflow check on or off, doesn't matter.

The complete pascal program, as compiled by me:

{$R+}{$Q+}
program tord ;
function d(a,b:Char):Integer;
begin
  d := integer(Ord(a))-Ord(b);
end;
var
  i: Integer;
begin
  i := Ord('0')-Ord('1');
  WriteLn(i);
  WriteLn(d('0','1'));
end.

Gerhard

Reply by email

Hans-Peter Diettrich
to Gerhard Scholz
Gerhard Scholz wrote 17 lines
... > I'm not sure, at least > > > .L9: > > movw %dx,-12(%ebp) > > .Ll3: > > suggests that the target is not an integer, but instead is a (possibly > unsigned) word type. Please check again! ... This is the result of the compilation: "ppc386 tord -al" (shortened of course). Since "MOVW" moves 16-bit values, it does not matter if it's signed or not, it just has to be 16 bit of something.

The MOVW is not the offending instruction, the range/overflow checks are implemented in separate code. That code will reflect the precise data type of the two bytes, moved by MOVW.

I'm not very experienced in reading Intel assembler code, so somebody else should explain what data type is assumed in the checking code.

DoDi

Reply by email

Colin Western
to Peter Vreman: What with cardinal-cardinal and pointer-cardinal or pointer-byte? Those can't be…
Peter Vreman wrote 39 lines
>Gerhard Scholz wrote: > > >>The check for overflow is obviously implemented different in 2.0.0 and >>2.1.1 >> >> >I'm not sure, at least > > > >>.L9: >> movw %dx,-12(%ebp) >>.Ll3: >> >> >suggests that the target is not an integer, but instead is a (possibly >unsigned) word type. Please check again! > > > >>A solution would be to replace that line by: >> d := integer(Ord(a))-Ord(b) >> >>It seems that the compiler now sees a "ord(c)" to be a BYTE, and BYTE - >>BYTE >>shall give a BYTE, and -1 is not in the range allowed for a BYTE. >> >> >Differences always should be interpreted as signed values, the error >message IMO comes from the final assignment. > > What with cardinal-cardinal and pointer-cardinal or pointer-byte? Those can't be represented by a longint (the native singed type of pascal). In 2.0.0 the those were converted to int64 values, but users were complaining about the warnings that were generated.

For that matter Integer-Integer can't (in general) be represented by an Integer, which I suppose is why we have range checks. The documenation I can find is a little vague as to what the general result of +/- operations should be - it just seems to say integer which suggests that a difference between ordinals should be signed. (I think pointers are a slightly different case)

Colin

Reply by email

Michael Van Canneyt
to Colin Western

Hi,

A warning:

As of revision 335, the following ("temporary") macros are no longer defined by the 2.1.1 and 2.0.1 compiler:

HASWIDECHAR
HASWIDESTRING
HASOUT
HASGLOBALPROPERTY
FPC_HASPREFETCH
FPC_LINEEND_IN_TEXTREC
FPC_ALIGNSRTTI
FPC_HASNOFARPOINTER
FPC_HASUSERDATA32
INTERNSETLENGTH
INTERNLENGTH
INTERNCOPY
INT64FUNCRESOK
HAS_ADDR_STACK_ON_STACK
NOBOUNDCHECK
HASCOMPILERPROC
INTERNCONSTINTF
VALUEGETMEM
VALUEFREEMEM
HASCURRENCY
HASTHREADVAR
HAS_GENERICCONSTRUCTOR
NOCLASSHELPERS
DECRREFNOTNIL
HAS_INTERNAL_INTTYPES
STR_USES_VALINT
NOSAVEREGISTERS
SHORTSTRCOMPAREINREG
HASGETHEAPSTATUS
HASGETFPCHEAPSTATUS
HASFUNCTIONCOPYDYNARR
HASOVERLOADASSIGNBYUNIQUERESULT
HASINTF
HASVARIANT

The RTL, FCL and Packages have been cleaned so they no longer use these defines. (and they look much better this way ;-) )

Under normal circumstances, you should not have used these defines. These defines were meant for internal use by the compiler team.

If you need to fix code, keep the part of the code that was included when the above macros were defined.

At the same time, the {$IFDEF VER1_X_Y} defines have been removed from the RTL, FCL and Packages. As a result, the FPC source tree will now no longer compile with the 1.X compilers.

Michael.

Reply by email

L505
to Michael Van Canneyt

For all the keyboard wussies out there:

Note, for all you that are afraid of long reduntant begin/end typing, you could go

{$define beg:=begin}
Or
program Project1;
{$mode objfpc}{$H+}
{$define b:= begin }
{$define e:= end }
{$define e:=end }
var
 iLoc:integer;
b
 b
  for iLoc:= 1 to 60 do
   writeln('test');
 e;
e.

But.. for all the C wussies out there.. this won't work :

program Project1;
{$mode objfpc}{$H+}
{$define {:= begin} //this works
{$define }:= end. }  //this doesn't work
{$define }:= end; }  //this doesn't work
var
 iLoc:integer;

{
for iLoc:= 1 to 60 do
writeln('test')
}

........So how do you escape the } in a define?

Reply by email

Hans-Peter Diettrich
to L505
L505 wrote
{$define {:= begin} //this works {$define }:= end. } //this doesn't work {$define }:= end; } //this doesn't work

Are you sure that the first example really works? It might do somehting unexpected, even if the compiler doesn't complain.

The problem with "{" and "}" is the conflict between these characters as delimiters of comments (the whole directive), and their use as identifiers inside the directives.

As soon as you've redefined the meaning of "{" in the first line, it most probably becomes impossible to add any further compiler directive, because these start with exactly that redefined character!

DoDi

Reply by email

L505
to Hans-Peter Diettrich
| > {$define {:= begin} //this works
| > {$define }:= end. }  //this doesn't work
| > {$define }:= end; }  //this doesn't work
|
| Are you sure that the first example really works? It might do somehting
| unexpected, even if the compiler doesn't complain.

I just tried it on short code, and it worked. Maybe not on longer code with other comments further down, who knows. I don't really care though because I find parenthesis hard to read on my monitors on hi res. I'd rather do somethingelse useful with the macros.

| The problem with "{" and "}" is the conflict between these characters as | delimiters of comments (the whole directive), and their use as | identifiers inside the directives.
|
| As soon as you've redefined the meaning of "{" in the first line, it | most probably becomes impossible to add any further compiler directive, | because these start with exactly that redefined character!

Well that's why I was asking if any way to escape it like in a regex where you go \escape , but again it's really not important for my needs.

Reply by email