From 14b95b3b9b7c3419e5c28b202e401f3826dda164 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 24 Oct 2010 14:55:48 +0000 Subject: [PATCH] * always force range checking for the upper and lower bounds of for-loops if they are constants (instead of only on 32 bit systems), and always use the actual upper/lower bound of the loop variable instead of hardcoding the bounds of longint (mantis #17646) git-svn-id: trunk@16213 - --- .gitattributes | 2 ++ compiler/defutil.pas | 7 +++-- compiler/ncnv.pas | 2 +- compiler/ncon.pas | 2 +- compiler/ninl.pas | 4 +-- compiler/pstatmnt.pas | 27 ++++++---------- compiler/ptconst.pas | 2 +- tests/webtbf/tw17646a.pp | 14 +++++++++ tests/webtbs/tw17646.pp | 68 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 tests/webtbf/tw17646a.pp create mode 100644 tests/webtbs/tw17646.pp diff --git a/.gitattributes b/.gitattributes index 383c08b3d8..8348f83492 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9958,6 +9958,7 @@ tests/webtbf/tw1681.pp svneol=native#text/plain tests/webtbf/tw17455.pp svneol=native#text/plain tests/webtbf/tw1754.pp svneol=native#text/plain tests/webtbf/tw1754b.pp svneol=native#text/plain +tests/webtbf/tw17646a.pp svneol=native#text/plain tests/webtbf/tw1782.pp svneol=native#text/plain tests/webtbf/tw1827.pp svneol=native#text/plain tests/webtbf/tw1830.pp svneol=native#text/plain @@ -10714,6 +10715,7 @@ tests/webtbs/tw1755.pp svneol=native#text/plain tests/webtbs/tw17550.pp svneol=native#text/plain tests/webtbs/tw1758.pp svneol=native#text/plain tests/webtbs/tw17604.pp svneol=native#text/plain +tests/webtbs/tw17646.pp svneol=native#text/plain tests/webtbs/tw1765.pp svneol=native#text/plain tests/webtbs/tw17675.pp svneol=native#text/plain tests/webtbs/tw17675a.pp svneol=native#text/plain diff --git a/compiler/defutil.pas b/compiler/defutil.pas index c23bbd4341..42398df4be 100644 --- a/compiler/defutil.pas +++ b/compiler/defutil.pas @@ -223,7 +223,7 @@ interface {# If @var(l) isn't in the range of todef a range check error (if not explicit) is generated and the value is placed within the range } - procedure testrange(todef : tdef;var l : tconstexprint;explicit:boolean); + procedure testrange(todef : tdef;var l : tconstexprint;explicit,forcerangecheck:boolean); {# Returns the range of def, where @var(l) is the low-range and @var(h) is the high-range. @@ -751,7 +751,7 @@ implementation { if l isn't in the range of todef a range check error (if not explicit) is generated and the value is placed within the range } - procedure testrange(todef : tdef;var l : tconstexprint;explicit:boolean); + procedure testrange(todef : tdef;var l : tconstexprint;explicit,forcerangecheck:boolean); var lv,hv: TConstExprInt; begin @@ -766,7 +766,8 @@ implementation { delphi allows range check errors in enumeration type casts FK } not(m_delphi in current_settings.modeswitches)) or - (cs_check_range in current_settings.localswitches) then + (cs_check_range in current_settings.localswitches) or + forcerangecheck then Message(parser_e_range_check_error) else Message(parser_w_range_check_error); diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index b2282d693e..2e720d9fa6 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -2266,7 +2266,7 @@ implementation {$endif VER2_2} end else - testrange(resultdef,tordconstnode(left).value,(nf_explicit in flags)); + testrange(resultdef,tordconstnode(left).value,(nf_explicit in flags),false); left.resultdef:=resultdef; tordconstnode(left).typedef:=resultdef; result:=left; diff --git a/compiler/ncon.pas b/compiler/ncon.pas index a839897383..a4df24adfd 100644 --- a/compiler/ncon.pas +++ b/compiler/ncon.pas @@ -669,7 +669,7 @@ implementation { only do range checking when explicitly asked for it and if the type can be range checked, see tests/tbs/tb0539.pp } if (resultdef.typ in [orddef,enumdef]) then - testrange(resultdef,value,not rangecheck) + testrange(resultdef,value,not rangecheck,false) end; function tordconstnode.pass_1 : tnode; diff --git a/compiler/ninl.pas b/compiler/ninl.pas index 5e0e2911f8..53f14b3592 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -1996,9 +1996,9 @@ implementation (index.left.nodetype = ordconstn) and not is_special_array(unpackedarraydef) then begin - testrange(unpackedarraydef,tordconstnode(index.left).value,false); + testrange(unpackedarraydef,tordconstnode(index.left).value,false,false); tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange; - testrange(unpackedarraydef,tempindex,false); + testrange(unpackedarraydef,tempindex,false,false); end; end; diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas index 4d8f53c8c2..b2cb394735 100644 --- a/compiler/pstatmnt.pas +++ b/compiler/pstatmnt.pas @@ -205,8 +205,8 @@ implementation CGMessage(parser_e_case_lower_less_than_upper_bound); if not casedeferror then begin - testrange(casedef,hl1,false); - testrange(casedef,hl2,false); + testrange(casedef,hl1,false,false); + testrange(casedef,hl2,false,false); end; end else @@ -234,7 +234,7 @@ implementation begin hl1:=get_ordinal_value(p); if not casedeferror then - testrange(casedef,hl1,false); + testrange(casedef,hl1,false,false); casenode.addlabel(blockid,hl1,hl1); end; end; @@ -321,20 +321,11 @@ implementation function for_statement : tnode; - procedure check_range(hp:tnode); + procedure check_range(hp:tnode; fordef: tdef); begin - {$ifndef cpu64bitaddr} - if hp.nodetype=ordconstn then - begin - if (tordconstnode(hp).valuehigh(longint)) then - begin - CGMessage(parser_e_range_check_error); - { recover, prevent more warnings/errors } - tordconstnode(hp).value:=0; - end; - end; - {$endif not cpu64bitaddr} + if (hp.nodetype=ordconstn) and + (fordef.typ<>errordef) then + testrange(fordef,tordconstnode(hp).value,false,true); end; function for_loop_create(hloopvar: tnode): tnode; @@ -447,8 +438,8 @@ implementation consume(_DO); { Check if the constants fit in the range } - check_range(hfrom); - check_range(hto); + check_range(hfrom,hloopvar.resultdef); + check_range(hto,hloopvar.resultdef); { first set the varstate for from and to, so uses of loopvar in those expressions will also diff --git a/compiler/ptconst.pas b/compiler/ptconst.pas index ca74ea64e9..15c32e5ff2 100644 --- a/compiler/ptconst.pas +++ b/compiler/ptconst.pas @@ -251,7 +251,7 @@ implementation begin if is_constintnode(n) then begin - testrange(def,tordconstnode(n).value,false); + testrange(def,tordconstnode(n).value,false,false); case def.size of 1 : list.concat(Tai_const.Create_8bit(byte(tordconstnode(n).value.svalue))); diff --git a/tests/webtbf/tw17646a.pp b/tests/webtbf/tw17646a.pp new file mode 100644 index 0000000000..f55ae0d67a --- /dev/null +++ b/tests/webtbf/tw17646a.pp @@ -0,0 +1,14 @@ +{ %fail } + +program forrangecheck; + +var + i1: Word; + i2: LongWord; + i3: QWord; + cnt: longint; +begin + cnt:=0; + for i1 := High(longword)-2 to High(longword) do + inc(cnt); +end. diff --git a/tests/webtbs/tw17646.pp b/tests/webtbs/tw17646.pp new file mode 100644 index 0000000000..f43b766cbb --- /dev/null +++ b/tests/webtbs/tw17646.pp @@ -0,0 +1,68 @@ +program forrangecheck; + +var + i1: Word; + i2: LongWord; + i3: QWord; + cnt: longint; +begin + cnt:=0; + for i1 := High(i1)-2 to High(i1) do + inc(cnt); + if cnt<>3 then + halt(1); + + cnt:=0; + for i2 := high(i2)-2 to High(i2) do + inc(cnt); + if cnt<>3 then + halt(2); + +{$ifdef cpu64} + cnt:=0; + for i3 := high(i3)-2 to High(i3) do + inc(cnt); + if cnt<>3 then + halt(3); +{$endif} + + cnt:=0; + for i1 := high(word)-2 to High(Word) do + inc(cnt); + if cnt<>3 then + halt(4); + + cnt:=0; + for i2 := high(longword)-2 to High(LongWord) do + inc(cnt); + if cnt<>3 then + halt(5); + +{$ifdef cpu64} + cnt:=0; + for i3 := high(qword)-2 to High(QWord) do + inc(cnt); + if cnt<>3 then + halt(6); +{$endif} + + cnt:=0; + for i1 := word($ffff)-2 to Word($FFFF) do + inc(cnt); + if cnt<>3 then + halt(7); + + cnt:=0; + for i2 := longword($ffffffff)-2 to LongWord($FFFFFFFF) do + inc(cnt); + if cnt<>3 then + halt(8); + +{$ifdef cpu64} + cnt:=0; + for i3 := QWord($FFFFFFFFFFFFFFFF)-2 to QWord($FFFFFFFFFFFFFFFF) do + inc(cnt); + if cnt<>3 then + halt(9); +{$endif} +end.