Fix issue where statically-evaluated conversions from floating-point values to some integer types could yield wrong values.

This occurred because the values were being rounded rather than truncated when converted to long, unsigned long, or unsigned int.

This was causing problems in the C6.2.3.5.CC test case when compiled with optimization.

The below program demonstrates the problem:

#pragma optimize 1
#include <stdio.h>
int main (void)
{
   long L;
   unsigned int ui;
   unsigned long ul;
   L = -1.5;
   ui = 1.5;
   ul = 1.5;
   printf("%li %u %lu\n", L, ui, ul); /* should print "-1 1 1" */
}
This commit is contained in:
Stephen Heumann 2016-12-14 23:52:20 -06:00
parent f099222af6
commit 5c81d970b5

35
DAG.pas
View File

@ -1095,29 +1095,32 @@ case op^.opcode of {check for optimizations of this node}
lval := 0
else if rval > 65535.0 then
lval := 65535
else begin
rval := trunc4(rval);
lval := round4(rval);
end; {else}
else
lval := trunc4(rval);
op^.left^.rval := 0.0;
op^.left^.q := long(lval).lsw;
end;
cgLong,cgULong: begin
rval := op^.left^.rval;
if totype.optype = cgULong then begin
if rval < 0 then
rval := 0
else if rval > 2147483647.0 then
rval := rval - 4294967296.0
end; {if}
cgLong: begin
if rval < -2147483648.0 then
lval := $80000000
else if rval > 2147483647.0 then
lval := 2147483647
else begin
rval := trunc4(rval);
lval := round4(rval);
end; {else}
else
lval := trunc4(rval);
op^.left^.rval := 0.0;
op^.left^.lval := lval;
end;
cgULong: begin
if rval < 0.0 then
lval := 0
else if rval >= 4294967295.0 then
lval := $FFFFFFFF
else if rval > 2147483647.0 then begin
rval := rval - 2147483647.0;
lval := 2147483647 + trunc4(rval);
end {else if}
else
lval := trunc4(rval);
op^.left^.rval := 0.0;
op^.left^.lval := lval;
end;