From 2c3c6d27d33dd3160f6c6051da1f109a74dfa3f5 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Mon, 23 Nov 2009 20:01:07 +0000 Subject: [PATCH] * 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 - --- .gitattributes | 1 + compiler/ncginl.pas | 10 ++++++---- compiler/ninl.pas | 9 ++++++++- tests/webtbs/tw14841.pp | 12 ++++++++++++ tests/webtbs/tw4152.pp | 6 +++++- 5 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 tests/webtbs/tw14841.pp diff --git a/.gitattributes b/.gitattributes index 7906b238fd..314962b528 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/compiler/ncginl.pas b/compiler/ncginl.pas index adfca377fc..c53bc14b91 100644 --- a/compiler/ncginl.pas +++ b/compiler/ncginl.pas @@ -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; diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 84f9279c03..c376d36e54 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -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); diff --git a/tests/webtbs/tw14841.pp b/tests/webtbs/tw14841.pp new file mode 100644 index 0000000000..e493c6a2f5 --- /dev/null +++ b/tests/webtbs/tw14841.pp @@ -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. + diff --git a/tests/webtbs/tw4152.pp b/tests/webtbs/tw4152.pp index 5be0c996e5..8a83bb2c30 100644 --- a/tests/webtbs/tw4152.pp +++ b/tests/webtbs/tw4152.pp @@ -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;