From b2825f24677fe84096cb5a82da55bf707473df44 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 17 Mar 2018 21:33:07 +0000 Subject: [PATCH] * scale constants if possible before currency multiplications to avoid overflows, resolves #33439 git-svn-id: trunk@38555 - --- .gitattributes | 1 + compiler/nadd.pas | 40 +++++++++++++++++++++++++++++++++++++--- tests/webtbs/tw33439.pp | 9 +++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 tests/webtbs/tw33439.pp diff --git a/.gitattributes b/.gitattributes index 0523ff2dae..7866dc5b8b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16084,6 +16084,7 @@ tests/webtbs/tw3334.pp svneol=native#text/plain tests/webtbs/tw3340.pp svneol=native#text/plain tests/webtbs/tw33414.pp svneol=native#text/pascal tests/webtbs/tw33417.pp svneol=native#text/pascal +tests/webtbs/tw33439.pp svneol=native#text/pascal tests/webtbs/tw3348.pp svneol=native#text/plain tests/webtbs/tw3349.pp svneol=native#text/plain tests/webtbs/tw3351.pp svneol=native#text/plain diff --git a/compiler/nadd.pas b/compiler/nadd.pas index f009ae9d88..02dfa24415 100644 --- a/compiler/nadd.pas +++ b/compiler/nadd.pas @@ -2355,11 +2355,45 @@ implementation end; muln : begin + hp:=nil; if s64currencytype.typ=floatdef then - hp:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,s64currencytype)) + begin + { if left is a currency integer constant, we can get rid of the factor 10000 } + { int64(...) causes a cast on currency, so it is the currency value multiplied by 10000 } + if (left.nodetype=realconstn) and (is_currency(left.resultdef)) and ((int64(trealconstnode(left).value_currency) mod 10000)=0) then + begin + { trealconstnode expects that value_real and value_currency contain valid values } + trealconstnode(left).value_currency:=trealconstnode(left).value_currency {$ifdef FPC_CURRENCY_IS_INT64}div{$else}/{$endif} 10000; + trealconstnode(left).value_real:=trealconstnode(left).value_real/10000; + end + { or if right is an integer constant, we can get rid of its factor 10000 } + else if (right.nodetype=realconstn) and (is_currency(right.resultdef)) and ((int64(trealconstnode(right).value_currency) mod 10000)=0) then + begin + { trealconstnode expects that value and value_currency contain valid values } + trealconstnode(right).value_currency:=trealconstnode(right).value_currency {$ifdef FPC_CURRENCY_IS_INT64}div{$else}/{$endif} 10000; + trealconstnode(right).value_real:=trealconstnode(right).value_real/10000; + end + else + begin + hp:=caddnode.create(slashn,getcopy,crealconstnode.create(10000.0,s64currencytype)); + include(hp.flags,nf_is_currency); + end; + end else - hp:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,s64currencytype,false)); - include(hp.flags,nf_is_currency); + begin + { if left is a currency integer constant, we can get rid of the factor 10000 } + if (left.nodetype=ordconstn) and (is_currency(left.resultdef)) and ((tordconstnode(left).value mod 10000)=0) then + tordconstnode(left).value:=tordconstnode(left).value div 10000 + { or if right is an integer constant, we can get rid of its factor 10000 } + else if (right.nodetype=ordconstn) and (is_currency(right.resultdef)) and ((tordconstnode(right).value mod 10000)=0) then + tordconstnode(right).value:=tordconstnode(right).value div 10000 + else + begin + hp:=cmoddivnode.create(divn,getcopy,cordconstnode.create(10000,s64currencytype,false)); + include(hp.flags,nf_is_currency); + end + end; + result:=hp end; end; diff --git a/tests/webtbs/tw33439.pp b/tests/webtbs/tw33439.pp new file mode 100644 index 0000000000..396b20e266 --- /dev/null +++ b/tests/webtbs/tw33439.pp @@ -0,0 +1,9 @@ +Var Cur : Currency ; + +Begin + Cur:=100000000000; + Cur:=Cur * 7 ; + if Cur<>700000000000 then + halt(1); + writeln('ok'); +End.