tdf#141201 - Round MOD literals to Integer values

(regression from commit I8dbfdf4bb2eceac0b5afbddd3f35e1dcde2db68b
"tdf#84435: Mod operator does not deal with decimals as described in help").

Change-Id: I74b231d3814148579a3be0a92b7602fa4387281f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113571
Tested-by: Jenkins
Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
diff --git a/basic/qa/basic_coverage/test_mod_operator.vb b/basic/qa/basic_coverage/test_mod_operator.vb
new file mode 100644
index 0000000..006d975
--- /dev/null
+++ b/basic/qa/basic_coverage/test_mod_operator.vb
@@ -0,0 +1,25 @@
'
' This file is part of the LibreOffice project.
'
' This Source Code Form is subject to the terms of the Mozilla Public
' License, v. 2.0. If a copy of the MPL was not distributed with this
' file, You can obtain one at http://mozilla.org/MPL/2.0/.
'

Function doUnitTest as Integer

    doUnitTest = 0

    Dim a As Double, b as Double
    a = 16.4
    b = 5.9

    ' tdf#141201 - MOD operands are rounded to Integer values before the operation is performed
    if (a MOD b <> 4) Then Exit Function
    if (16.4 MOD 5.9 <> 4) Then Exit Function
    if (15.9 MOD 6.4 <> 4) Then Exit Function
    if (2147483647.4 MOD 4 <> 3) Then Exit Function

    doUnitTest = 1

End Function
diff --git a/basic/source/comp/exprnode.cxx b/basic/source/comp/exprnode.cxx
index 02f8801..1771da0 100644
--- a/basic/source/comp/exprnode.cxx
+++ b/basic/source/comp/exprnode.cxx
@@ -27,6 +27,8 @@

#include <basic/sberrors.hxx>

#include <rtl/math.hxx>

SbiExprNode::SbiExprNode( std::unique_ptr<SbiExprNode> l, SbiToken t, std::unique_ptr<SbiExprNode> r ) :
    pLeft(std::move(l)),
    pRight(std::move(r)),
@@ -294,8 +296,13 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
    {
        double nl = pLeft->nVal;
        double nr = pRight->nVal;
        // tdf#141201 - round MOD literals to Integer values
        if (eTok == MOD)
        {
            nl = rtl::math::round(nl);
            nr = rtl::math::round(nr);
        }
        tools::Long ll = 0, lr = 0;
        tools::Long llMod = 0, lrMod = 0;
        if( ( eTok >= AND && eTok <= IMP )
           || eTok == IDIV || eTok == MOD )
        {
@@ -322,8 +329,6 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
                nr = SbxMINLNG;
            }
            ll = static_cast<tools::Long>(nl); lr = static_cast<tools::Long>(nr);
            llMod = static_cast<tools::Long>(nl);
            lrMod = static_cast<tools::Long>(nr);
            if( bErr )
            {
                pParser->Error( ERRCODE_BASIC_MATH_OVERFLOW );
@@ -388,7 +393,7 @@ void SbiExprNode::FoldConstantsBinaryNode(SbiParser* pParser)
                {
                    pParser->Error( ERRCODE_BASIC_ZERODIV ); nVal = HUGE_VAL;
                    bError = true;
                } else nVal = llMod - lrMod * (llMod/lrMod);
                } else nVal = ll - lr * (ll/lr);
                eType = SbxLONG; break;
            case AND:
                nVal = static_cast<double>( ll & lr ); eType = SbxLONG; break;