* fixed range checking for inc/dec when mixing unsigned and signed types

(mantis #14841)
   -> this also makes it impossible now to use constructs such as
    inc(qword_var,-1) with range checking enabled, because that would require
    a conversion to 128 bit for proper evaluation

git-svn-id: trunk@14260 -
This commit is contained in:
Jonas Maebe 2009-11-23 20:01:07 +00:00
parent d313fd272c
commit 2c3c6d27d3
5 changed files with 32 additions and 6 deletions

1
.gitattributes vendored
View File

@ -10083,6 +10083,7 @@ tests/webtbs/tw1477.pp svneol=native#text/plain
tests/webtbs/tw1479.pp svneol=native#text/plain
tests/webtbs/tw14798.pp svneol=native#text/plain
tests/webtbs/tw14812.pp svneol=native#text/plain
tests/webtbs/tw14841.pp svneol=native#text/plain
tests/webtbs/tw1485.pp svneol=native#text/plain
tests/webtbs/tw1489.pp svneol=native#text/plain
tests/webtbs/tw14958a.pp svneol=native#text/plain

View File

@ -491,11 +491,13 @@ implementation
{ Or someone has to rewrite the above to use a_op_const_reg_reg_ov }
{ and friends in case of overflow checking, and ask everyone to }
{ implement these methods since they don't exist for all cpus (JM) }
if (cs_check_overflow in current_settings.localswitches) then
{ Similarly, range checking also has to be handled separately, }
{ see mantis #14841 (JM) }
if ([cs_check_overflow,cs_check_range] * current_settings.localswitches <> []) then
internalerror(2006111010);
// cg.g_overflowcheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).resultdef);
cg.g_rangecheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,
tcallparanode(left).left.resultdef);
// cg.g_overflowcheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).resultdef);
// cg.g_rangecheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,
// tcallparanode(left).left.resultdef);
end;
end;

View File

@ -2205,7 +2205,14 @@ implementation
if is_integer(tcallparanode(left).right.resultdef) then
begin
set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
{ when range/overflow checking is on, we
convert this to a regular add, and for proper
checking we need the original type }
if ([cs_check_range,cs_check_overflow]*current_settings.localswitches=[]) then
if is_integer(tcallparanode(left).left.resultdef) then
inserttypeconv(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef)
else
inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
if assigned(tcallparanode(tcallparanode(left).right).right) then
{ should be handled in the parser (JM) }
internalerror(2006020901);

12
tests/webtbs/tw14841.pp Normal file
View File

@ -0,0 +1,12 @@
{$r+,o+}
var
b: byte;
s: shortint;
begin
b:=57;
s:=-1;
inc(b, s);
if b<>56 then
halt(1);
end.

View File

@ -1,7 +1,7 @@
{ Source provided for Free Pascal Bug Report 4152 }
{ Submitted by "C Western" on 2005-07-03 }
{ e-mail: mftq75@dsl.pipex.com }
{$R+}{$Q+}
{R+}{Q+}
var
p:^Byte;
c:Byte;
@ -13,7 +13,11 @@ var
{$endif}
begin
v:=100;
{$ifdef cpu32}
{ this gets translated into "v:=v+(-1)", and the compiler would require 128bit
arithmetic to calculate this when v is a qword and range checking is on }
inc(v,-1);
{$endif cpu32}
p:=@c;
Inc(p,-1); // Gives compile time error: range check error while evaluating constants
d:=2;