[Libreoffice-commits] core.git: sc/inc sc/source

Eike Rathke erack at redhat.com
Thu Aug 25 10:20:49 UTC 2016


 sc/inc/column.hxx                    |    2 
 sc/inc/document.hxx                  |    2 
 sc/inc/scmatrix.hxx                  |   10 +++-
 sc/inc/table.hxx                     |    2 
 sc/source/core/data/column2.cxx      |    4 -
 sc/source/core/data/documen8.cxx     |    2 
 sc/source/core/data/table1.cxx       |    2 
 sc/source/core/inc/interpre.hxx      |   21 +++++----
 sc/source/core/inc/jumpmatrix.hxx    |    2 
 sc/source/core/tool/formulagroup.cxx |    2 
 sc/source/core/tool/interpr1.cxx     |   42 ++++++++----------
 sc/source/core/tool/interpr2.cxx     |   59 ++++++++++++++------------
 sc/source/core/tool/interpr4.cxx     |   79 ++++++++++++++++++++++-------------
 sc/source/core/tool/interpr5.cxx     |   16 ++++---
 sc/source/core/tool/interpr6.cxx     |    2 
 sc/source/core/tool/interpr8.cxx     |    8 +--
 sc/source/core/tool/scmatrix.cxx     |    9 +++
 17 files changed, 153 insertions(+), 111 deletions(-)

New commits:
commit db8c3afe8c5a5756537d16cf0399e3b46876cc8b
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Aug 25 11:02:50 2016 +0200

    let ScInterpreter::pStack contain const formula::FormulaToken*
    
    For two reasons:
    * introduce a new PushTokenRef() to push an already existing token,
      which can be used in several places that currently unnecessarily
      copy-construct a new token to be pushed
    * prevent unwanted side effects in case a token on the stack would be
      fiddled with, which was possible but just by convention wasn't done
    
    Change-Id: I715d81bcba8bdb415af45e889e9f9db1e0ac4888
    Reviewed-on: https://gerrit.libreoffice.org/28377
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index a73f7c4..bb7a2b9 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -574,7 +574,7 @@ public:
     void FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2, svl::SharedStringPool* pPool = nullptr ) const;
     formula::VectorRefArray FetchVectorRefArray( SCROW nRow1, SCROW nRow2 );
     void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen );
-    void SetFormulaResults( SCROW nRow, const formula::FormulaTokenRef* pResults, size_t nLen );
+    void SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
 
     void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat );
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index b2f9753..749eab2 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1983,7 +1983,7 @@ public:
      */
     void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen );
 
-    void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const formula::FormulaTokenRef* pResults, size_t nLen );
+    void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen );
 
     /**
      * Transfer a series of contiguous cell values from specified position to
diff --git a/sc/inc/scmatrix.hxx b/sc/inc/scmatrix.hxx
index 62cddee..b565335 100644
--- a/sc/inc/scmatrix.hxx
+++ b/sc/inc/scmatrix.hxx
@@ -113,7 +113,7 @@ struct ScMatrixValue
 class SC_DLLPUBLIC ScMatrix
 {
     mutable size_t  nRefCnt;    // reference count
-    bool            mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
+    mutable bool    mbCloneIfConst; // Whether the matrix is cloned with a CloneIfConst() call.
 
     ScMatrix( const ScMatrix& ) = delete;
     ScMatrix& operator=( const ScMatrix&) = delete;
@@ -219,9 +219,13 @@ public:
         return _this_ matrix, to be assigned to a ScMatrixRef. */
     ScMatrix* CloneIfConst();
 
-    /** Set the matrix to (im)mutable for CloneIfConst(), only the interpreter
+    /** Set the matrix to mutable for CloneIfConst(), only the interpreter
         should do this and know the consequences. */
-    void SetImmutable( bool bVal );
+    void SetMutable();
+
+    /** Set the matrix to immutable for CloneIfConst(), only the interpreter
+        should do this and know the consequences. */
+    void SetImmutable() const;
 
     /**
      * Resize the matrix to specified new dimension.
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index bd63446..708e535 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -918,7 +918,7 @@ public:
     void InterpretDirtyCells( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
 
     void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen );
-    void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaTokenRef* pResults, size_t nLen );
+    void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
 
     /**
      * Either start all formula cells as listeners unconditionally, or start
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index cae1ff5..9faf724 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2752,7 +2752,7 @@ void ScColumn::SetFormulaResults( SCROW nRow, const double* pResults, size_t nLe
     }
 }
 
-void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaTokenRef* pResults, size_t nLen )
+void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen )
 {
     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     sc::CellStoreType::iterator it = aPos.first;
@@ -2768,7 +2768,7 @@ void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaTokenRef* pR
     sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
     std::advance(itCell, aPos.second);
 
-    const formula::FormulaTokenRef* pResEnd = pResults + nLen;
+    const formula::FormulaConstTokenRef* pResEnd = pResults + nLen;
     for (; pResults != pResEnd; ++pResults, ++itCell)
     {
         ScFormulaCell& rCell = **itCell;
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index a84c2d0..ca158fd 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -419,7 +419,7 @@ void ScDocument::SetFormulaResults( const ScAddress& rTopPos, const double* pRes
 }
 
 void ScDocument::SetFormulaResults(
-    const ScAddress& rTopPos, const formula::FormulaTokenRef* pResults, size_t nLen )
+    const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen )
 {
     ScTable* pTab = FetchTable(rTopPos.Tab());
     if (!pTab)
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index feac296..f770c7e 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2257,7 +2257,7 @@ void ScTable::SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults,
 }
 
 void ScTable::SetFormulaResults(
-    SCCOL nCol, SCROW nRow, const formula::FormulaTokenRef* pResults, size_t nLen )
+    SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen )
 {
     if (!ValidCol(nCol))
         return;
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index f1b8e0d..c6987f8 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -76,7 +76,7 @@ class ScTokenStack
 {
 public:
     DECL_FIXEDMEMPOOL_NEWDEL( ScTokenStack )
-    formula::FormulaToken* pPointer[ MAXSTACK ];
+    const formula::FormulaToken* pPointer[ MAXSTACK ];
 };
 
 enum ScIterFunc {
@@ -121,7 +121,7 @@ struct FormulaTokenRef_less
     bool operator () ( const formula::FormulaConstTokenRef& r1, const formula::FormulaConstTokenRef& r2 ) const
         { return r1.get() < r2.get(); }
 };
-typedef ::std::map< const formula::FormulaConstTokenRef, formula::FormulaTokenRef, FormulaTokenRef_less> ScTokenMatrixMap;
+typedef ::std::map< const formula::FormulaConstTokenRef, formula::FormulaConstTokenRef, FormulaTokenRef_less> ScTokenMatrixMap;
 
 class ScInterpreter
 {
@@ -187,7 +187,7 @@ private:
     ScDocument* pDok;
     sfx2::LinkManager* mpLinkManager;
     svl::SharedStringPool& mrStrPool;
-    formula::FormulaTokenRef  xResult;
+    formula::FormulaConstTokenRef  xResult;
     ScJumpMatrix*   pJumpMatrix;        // currently active array condition, if any
     ScTokenMatrixMap* pTokenMatrixMap;  // map FormulaToken* to formula::FormulaTokenRef if in array condition
     ScFormulaCell* pMyFormulaCell;      // the cell of this formula expression
@@ -196,7 +196,7 @@ private:
     const formula::FormulaToken*
                 pCur;                   // current token
     ScTokenStack* pStackObj;            // contains the stacks
-    formula::FormulaToken**   pStack;   // the current stack
+    const formula::FormulaToken ** pStack;  // the current stack
     sal_uInt16  nGlobalError;           // global (local to this formula expression) error
     sal_uInt16  sp;                     // stack pointer
     sal_uInt16  maxsp;                  // the maximal used stack pointer
@@ -262,7 +262,7 @@ void Push( formula::FormulaToken& r );
 /** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set.
     Used to push RPN tokens or from within Push() or tokens that are already
     explicit formula::FormulaErrorToken. Increments RefCount. */
-void PushWithoutError( formula::FormulaToken& r );
+void PushWithoutError( const formula::FormulaToken& r );
 
 /** Clones the token to be pushed or substitutes with formula::FormulaErrorToken if
     nGlobalError is set and the token passed is not formula::FormulaErrorToken. */
@@ -276,13 +276,18 @@ void PushTempToken( const formula::FormulaToken& );
     deleted in case of an errStackOverflow or if substituted with formula::FormulaErrorToken! */
 void PushTempToken( formula::FormulaToken* );
 
+/** Pushes the token or substitutes with formula::FormulaErrorToken in case
+    nGlobalError is set and the token passed is not formula::FormulaErrorToken.
+    Increments RefCount of the original token if not substituted. */
+void PushTokenRef( const formula::FormulaConstTokenRef& );
+
 /** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set.
     Used to push tokens from within PushTempToken() or tokens that are already
     explicit formula::FormulaErrorToken. Increments RefCount.
     ATTENTION! The token had to be allocated with `new' and must not be used
     after this call if no RefCount was set because possibly it gets immediately
     decremented again and thus deleted in case of an errStackOverflow! */
-void PushTempTokenWithoutError( formula::FormulaToken* );
+void PushTempTokenWithoutError( const formula::FormulaToken* );
 
 /** If nGlobalError is set push formula::FormulaErrorToken.
     If nGlobalError is not set do nothing.
@@ -316,7 +321,7 @@ inline bool IfErrorPushError()
 void PushCellResultToken( bool bDisplayEmptyAsString, const ScAddress & rAddress,
         short * pRetTypeExpr, sal_uLong * pRetIndexExpr, bool bFinalResult = false );
 
-formula::FormulaTokenRef PopToken();
+formula::FormulaConstTokenRef PopToken();
 void Pop();
 void PopError();
 double PopDouble();
@@ -976,7 +981,7 @@ public:
     formula::StackVar           GetResultType() const       { return xResult->GetType(); }
     svl::SharedString GetStringResult() const;
     double                      GetNumResult() const        { return xResult->GetDouble(); }
-    const formula::FormulaTokenRef& GetResultToken() const      { return xResult; }
+    const formula::FormulaConstTokenRef& GetResultToken() const { return xResult; }
     short                       GetRetFormatType() const    { return nRetFmtType; }
     sal_uLong                   GetRetFormatIndex() const   { return nRetFmtIndex; }
 };
diff --git a/sc/source/core/inc/jumpmatrix.hxx b/sc/source/core/inc/jumpmatrix.hxx
index ed98e53..4ef4f87 100644
--- a/sc/source/core/inc/jumpmatrix.hxx
+++ b/sc/source/core/inc/jumpmatrix.hxx
@@ -27,7 +27,7 @@
 #include "types.hxx"
 #include "address.hxx"
 
-typedef ::std::vector< formula::FormulaToken*> ScTokenVec;
+typedef ::std::vector< const formula::FormulaToken*> ScTokenVec;
 
 struct ScJumpMatrixEntry
 {
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 15ce590..e165e0c 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -158,7 +158,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
     // the group.
 
     ScAddress aTmpPos = rTopPos;
-    std::vector<formula::FormulaTokenRef> aResults;
+    std::vector<formula::FormulaConstTokenRef> aResults;
     aResults.reserve(xGroup->mnLength);
     CachedTokensType aCachedTokens;
 
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 52db341..85f443f 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -97,7 +97,7 @@ void ScInterpreter::ScIfJump()
                 PushIllegalParameter();
             else
             {
-                FormulaTokenRef xNew;
+                FormulaConstTokenRef xNew;
                 ScTokenMatrixMap::const_iterator aMapIter;
                 // DoubleError handled by JumpMatrix
                 pMat->SetErrorInterpreter( nullptr);
@@ -108,8 +108,7 @@ void ScInterpreter::ScIfJump()
                     PushIllegalArgument();
                     return;
                 }
-                else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
-                                    pCur)) != pTokenMatrixMap->end()))
+                else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
                     xNew = (*aMapIter).second;
                 else
                 {
@@ -178,7 +177,7 @@ void ScInterpreter::ScIfJump()
                     PushIllegalArgument();
                     return;
                 }
-                PushTempToken( xNew.get());
+                PushTokenRef( xNew);
                 // set endpoint of path for main code line
                 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
             }
@@ -250,7 +249,7 @@ void ScInterpreter::ScIfError( bool bNAonly )
         return;
     }
 
-    FormulaTokenRef xToken( pStack[ sp - 1 ] );
+    FormulaConstTokenRef xToken( pStack[ sp - 1 ] );
     bool bError = false;
     sal_uInt16 nOldGlobalError = nGlobalError;
     nGlobalError = 0;
@@ -333,7 +332,7 @@ void ScInterpreter::ScIfError( bool bNAonly )
                 if (!bError)
                     break;  // switch, we're done and have the result
 
-                FormulaTokenRef xNew;
+                FormulaConstTokenRef xNew;
                 ScTokenMatrixMap::const_iterator aMapIter;
                 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
                 {
@@ -380,7 +379,7 @@ void ScInterpreter::ScIfError( bool bNAonly )
                     GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur, xNew ));
                 }
                 nGlobalError = nOldGlobalError;
-                PushTempToken( xNew.get() );
+                PushTokenRef( xNew );
                 // set endpoint of path for main code line
                 aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
                 return;
@@ -398,7 +397,7 @@ void ScInterpreter::ScIfError( bool bNAonly )
     {
         // no error, push 1st argument and continue
         nGlobalError = nOldGlobalError;
-        PushTempToken( xToken.get());
+        PushTokenRef( xToken);
         aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
     }
 }
@@ -420,7 +419,7 @@ void ScInterpreter::ScChooseJump()
                 PushIllegalParameter();
             else
             {
-                FormulaTokenRef xNew;
+                FormulaConstTokenRef xNew;
                 ScTokenMatrixMap::const_iterator aMapIter;
                 // DoubleError handled by JumpMatrix
                 pMat->SetErrorInterpreter( nullptr);
@@ -479,7 +478,7 @@ void ScInterpreter::ScChooseJump()
                 }
                 if (xNew.get())
                 {
-                    PushTempToken( xNew.get());
+                    PushTokenRef( xNew);
                     // set endpoint of path for main code line
                     aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
                     bHaveJump = true;
@@ -768,8 +767,7 @@ bool ScInterpreter::JumpMatrix( short nStackLevel )
             const ScTokenVec* pParams = pJumpMatrix->GetJumpParameters();
             if ( pParams )
             {
-                for ( ScTokenVec::const_iterator i = pParams->begin();
-                        i != pParams->end(); ++i )
+                for ( ScTokenVec::const_iterator i = pParams->begin(); i != pParams->end(); ++i )
                 {
                     // This is not the current state of the interpreter, so
                     // push without error, and elements' errors are coded into
@@ -1814,7 +1812,7 @@ void ScInterpreter::ScIsEmpty()
     {
         case svEmptyCell:
         {
-            FormulaTokenRef p = PopToken();
+            FormulaConstTokenRef p = PopToken();
             if (!static_cast<const ScEmptyCellToken*>(p.get())->IsInherited())
                 nRes = 1;
         }
@@ -2478,7 +2476,7 @@ void ScInterpreter::ScIsRef()
         break;
         case svRefList :
         {
-            FormulaTokenRef x = PopToken();
+            FormulaConstTokenRef x = PopToken();
             if ( !nGlobalError )
                 bRes = !x.get()->GetRefList()->empty();
         }
@@ -7720,7 +7718,7 @@ void ScInterpreter::ScIndex()
                     bool bRowArray = false;
                     if (GetStackType() == svRefList)
                     {
-                        FormulaTokenRef xRef = PopToken();
+                        FormulaConstTokenRef xRef = PopToken();
                         if (nGlobalError || !xRef)
                         {
                             PushIllegalParameter();
@@ -7805,21 +7803,21 @@ void ScInterpreter::ScAreas()
         {
             case svSingleRef:
                 {
-                    FormulaTokenRef xT = PopToken();
+                    FormulaConstTokenRef xT = PopToken();
                     ValidateRef( *xT.get()->GetSingleRef());
                     ++nCount;
                 }
                 break;
             case svDoubleRef:
                 {
-                    FormulaTokenRef xT = PopToken();
+                    FormulaConstTokenRef xT = PopToken();
                     ValidateRef( *xT.get()->GetDoubleRef());
                     ++nCount;
                 }
                 break;
             case svRefList:
                 {
-                    FormulaTokenRef xT = PopToken();
+                    FormulaConstTokenRef xT = PopToken();
                     ValidateRef( *(xT.get()->GetRefList()));
                     nCount += xT.get()->GetRefList()->size();
                 }
@@ -8316,10 +8314,10 @@ void ScInterpreter::ScText()
                 break;
             default:
                 {
-                    FormulaTokenRef xTok( PopToken());
+                    FormulaConstTokenRef xTok( PopToken());
                     if (!nGlobalError)
                     {
-                        PushTempToken( xTok.get());
+                        PushTokenRef( xTok);
                         // Temporarily override the ConvertStringToValue()
                         // error for GetCellValue() / GetCellValueOrZero()
                         sal_uInt16 nSErr = mnStringNoValueError;
@@ -8330,7 +8328,7 @@ void ScInterpreter::ScText()
                         {
                             // Not numeric.
                             nGlobalError = 0;
-                            PushTempToken( xTok.get());
+                            PushTokenRef( xTok);
                             aStr = GetString();
                             bString = true;
                         }
@@ -8471,7 +8469,7 @@ sal_uInt16 ScInterpreter::GetErrorType()
     {
         case svRefList :
         {
-            FormulaTokenRef x = PopToken();
+            FormulaConstTokenRef x = PopToken();
             if (nGlobalError)
                 nErr = nGlobalError;
             else
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 6581198..b71d1ba 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -1268,7 +1268,7 @@ void ScInterpreter::ScNPV()
     {
         double nVal = 0.0;
         //We turn the stack upside down!
-        FormulaToken* pTemp[ 31 ];
+        const FormulaToken* pTemp[ 31 ];
         for( short i = 0; i < nParamCount; i++ )
             pTemp[ i ] = pStack[ sp - i - 1 ];
         memcpy( &pStack[ sp - nParamCount ], pTemp, nParamCount * sizeof( FormulaToken* ) );
@@ -2357,8 +2357,8 @@ void ScInterpreter::ScMod()
 
 void ScInterpreter::ScIntersect()
 {
-    formula::FormulaTokenRef p2nd = PopToken();
-    formula::FormulaTokenRef p1st = PopToken();
+    formula::FormulaConstTokenRef p2nd = PopToken();
+    formula::FormulaConstTokenRef p1st = PopToken();
 
     if (nGlobalError || !p2nd || !p1st)
     {
@@ -2375,14 +2375,14 @@ void ScInterpreter::ScIntersect()
         return;
     }
 
-    formula::FormulaToken* x1 = p1st.get();
-    formula::FormulaToken* x2 = p2nd.get();
+    const formula::FormulaToken* x1 = p1st.get();
+    const formula::FormulaToken* x2 = p2nd.get();
     if (sv1 == svRefList || sv2 == svRefList)
     {
         // Now this is a bit nasty but it simplifies things, and having
         // intersections with lists isn't too common, if at all..
         // Convert a reference to list.
-        formula::FormulaToken* xt[2] = { x1, x2 };
+        const formula::FormulaToken* xt[2] = { x1, x2 };
         StackVar sv[2] = { sv1, sv2 };
         for (size_t i=0; i<2; ++i)
         {
@@ -2390,14 +2390,16 @@ void ScInterpreter::ScIntersect()
             {
                 ScComplexRefData aRef;
                 aRef.Ref1 = aRef.Ref2 = *xt[i]->GetSingleRef();
-                xt[i] = new ScRefListToken;
-                xt[i]->GetRefList()->push_back( aRef);
+                formula::FormulaToken* p = new ScRefListToken;
+                p->GetRefList()->push_back( aRef);
+                xt[i] = p;
             }
             else if (sv[i] == svDoubleRef)
             {
                 ScComplexRefData aRef = *xt[i]->GetDoubleRef();
-                xt[i] = new ScRefListToken;
-                xt[i]->GetRefList()->push_back( aRef);
+                formula::FormulaToken* p = new ScRefListToken;
+                p->GetRefList()->push_back( aRef);
+                xt[i] = p;
             }
         }
         x1 = xt[0];
@@ -2445,11 +2447,11 @@ void ScInterpreter::ScIntersect()
                 PushTempToken( new ScDoubleRefToken( rRef));
         }
         else
-            PushTempToken( xRes.get());
+            PushTokenRef( xRes);
     }
     else
     {
-        formula::FormulaToken* pt[2] = { x1, x2 };
+        const formula::FormulaToken* pt[2] = { x1, x2 };
         StackVar sv[2] = { sv1, sv2 };
         SCCOL nC1[2], nC2[2];
         SCROW nR1[2], nR2[2];
@@ -2503,25 +2505,28 @@ void ScInterpreter::ScIntersect()
 
 void ScInterpreter::ScRangeFunc()
 {
-    formula::FormulaTokenRef x2 = PopToken();
-    formula::FormulaTokenRef x1 = PopToken();
+    formula::FormulaConstTokenRef x2 = PopToken();
+    formula::FormulaConstTokenRef x1 = PopToken();
 
     if (nGlobalError || !x2 || !x1)
     {
         PushIllegalArgument();
         return;
     }
-    FormulaTokenRef xRes = extendRangeReference( *x1, *x2, aPos, false);
+    // We explicitly tell extendRangeReference() to not reuse the token,
+    // casting const away spares two clones.
+    FormulaTokenRef xRes = extendRangeReference(
+            const_cast<FormulaToken&>(*x1), const_cast<FormulaToken&>(*x2), aPos, false);
     if (!xRes)
         PushIllegalArgument();
     else
-        PushTempToken( xRes.get());
+        PushTokenRef( xRes);
 }
 
 void ScInterpreter::ScUnionFunc()
 {
-    formula::FormulaTokenRef p2nd = PopToken();
-    formula::FormulaTokenRef p1st = PopToken();
+    formula::FormulaConstTokenRef p2nd = PopToken();
+    formula::FormulaConstTokenRef p1st = PopToken();
 
     if (nGlobalError || !p2nd || !p1st)
     {
@@ -2538,25 +2543,25 @@ void ScInterpreter::ScUnionFunc()
         return;
     }
 
-    formula::FormulaToken* x1 = p1st.get();
-    formula::FormulaToken* x2 = p2nd.get();
+    const formula::FormulaToken* x1 = p1st.get();
+    const formula::FormulaToken* x2 = p2nd.get();
 
     ScTokenRef xRes;
     // Append to an existing RefList if there is one.
     if (sv1 == svRefList)
     {
-        xRes = x1;
+        xRes = x1->Clone();
         sv1 = svUnknown;    // mark as handled
     }
     else if (sv2 == svRefList)
     {
-        xRes = x2;
+        xRes = x2->Clone();
         sv2 = svUnknown;    // mark as handled
     }
     else
         xRes = new ScRefListToken;
     ScRefList* pRes = xRes->GetRefList();
-    formula::FormulaToken* pt[2] = { x1, x2 };
+    const formula::FormulaToken* pt[2] = { x1, x2 };
     StackVar sv[2] = { sv1, sv2 };
     for (size_t i=0; i<2; ++i)
     {
@@ -2590,16 +2595,16 @@ void ScInterpreter::ScUnionFunc()
         }
     }
     ValidateRef( *pRes);    // set #REF! if needed
-    PushTempToken( xRes.get());
+    PushTokenRef( xRes);
 }
 
 void ScInterpreter::ScCurrent()
 {
-    FormulaTokenRef xTok( PopToken());
+    FormulaConstTokenRef xTok( PopToken());
     if (xTok)
     {
-        PushTempToken( xTok.get());
-        PushTempToken( xTok.get());
+        PushTokenRef( xTok);
+        PushTokenRef( xTok);
     }
     else
         PushError( errUnknownStackVariable);
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 9b200d5..5ff5cfa 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -622,7 +622,7 @@ bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
 
 // Also releases a TempToken if appropriate.
 
-void ScInterpreter::PushWithoutError( FormulaToken& r )
+void ScInterpreter::PushWithoutError( const FormulaToken& r )
 {
     if ( sp >= MAXSTACK )
         SetError( errStackOverflow );
@@ -689,7 +689,7 @@ void ScInterpreter::PushTempToken( FormulaToken* p )
     }
 }
 
-void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
+void ScInterpreter::PushTempTokenWithoutError( const FormulaToken* p )
 {
     p->IncRef();
     if ( sp >= MAXSTACK )
@@ -715,6 +715,26 @@ void ScInterpreter::PushTempToken( const FormulaToken& r )
         PushTempTokenWithoutError( r.Clone());
 }
 
+void ScInterpreter::PushTokenRef( const formula::FormulaConstTokenRef& x )
+{
+    if ( sp >= MAXSTACK )
+    {
+        SetError( errStackOverflow );
+    }
+    else
+    {
+        if (nGlobalError)
+        {
+            if (x->GetType() == svError && x->GetError() == nGlobalError)
+                PushTempTokenWithoutError( x.get());
+            else
+                PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
+        }
+        else
+            PushTempTokenWithoutError( x.get());
+    }
+}
+
 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
         const ScAddress & rAddress, short * pRetTypeExpr, sal_uLong * pRetIndexExpr, bool bFinalResult )
 {
@@ -794,12 +814,12 @@ void ScInterpreter::PopError()
         SetError(errUnknownStackVariable);
 }
 
-FormulaTokenRef ScInterpreter::PopToken()
+FormulaConstTokenRef ScInterpreter::PopToken()
 {
     if (sp)
     {
         sp--;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         if (p->GetType() == svError)
             nGlobalError = p->GetError();
         return p;
@@ -816,7 +836,7 @@ double ScInterpreter::PopDouble()
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -848,7 +868,7 @@ svl::SharedString ScInterpreter::PopString()
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -933,7 +953,7 @@ void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -957,7 +977,7 @@ void ScInterpreter::PopSingleRef( ScAddress& rAdr )
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -1044,7 +1064,7 @@ void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -1083,7 +1103,7 @@ void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRe
 {
     if (sp)
     {
-        formula::FormulaToken* pToken = pStack[ sp-1 ];
+        const formula::FormulaToken* pToken = pStack[ sp-1 ];
         switch (pToken->GetType())
         {
             case svError:
@@ -1128,7 +1148,7 @@ void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -1154,7 +1174,7 @@ void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName
     }
 
     --sp;
-    FormulaToken* p = pStack[sp];
+    const FormulaToken* p = pStack[sp];
     StackVar eType = p->GetType();
 
     if (eType == svError)
@@ -1233,7 +1253,7 @@ void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName
     }
 
     --sp;
-    FormulaToken* p = pStack[sp];
+    const FormulaToken* p = pStack[sp];
     StackVar eType = p->GetType();
 
     if (eType == svError)
@@ -1405,7 +1425,7 @@ bool ScInterpreter::ConvertMatrixParameters()
     SCSIZE nJumpCols = 0, nJumpRows = 0;
     for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
     {
-        FormulaToken* p = pStack[ sp - i ];
+        const FormulaToken* p = pStack[ sp - i ];
         if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
         {
             OSL_FAIL( "ConvertMatrixParameters: not a push");
@@ -1428,7 +1448,7 @@ bool ScInterpreter::ConvertMatrixParameters()
                     if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
                             == ScParameterClassification::Value )
                     {   // only if single value expected
-                        ScMatrixRef pMat = p->GetMatrix();
+                        ScConstMatrixRef pMat = p->GetMatrix();
                         if ( !pMat )
                             SetError( errUnknownVariable);
                         else
@@ -1532,10 +1552,9 @@ bool ScInterpreter::ConvertMatrixParameters()
         short nStart = nPC - 1;     // restart on current code (-1)
         short nNext = nPC;          // next instruction after subroutine
         short nStop = nPC + 1;      // stop subroutine before reaching that
-        FormulaTokenRef xNew;
+        FormulaConstTokenRef xNew;
         ScTokenMatrixMap::const_iterator aMapIter;
-        if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
-                    pTokenMatrixMap->end()))
+        if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) != pTokenMatrixMap->end()))
             xNew = (*aMapIter).second;
         else
         {
@@ -1545,15 +1564,14 @@ bool ScInterpreter::ConvertMatrixParameters()
             ScTokenVec* pParams = new ScTokenVec( nParams);
             for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
             {
-                FormulaToken* p = pStack[ --sp ];
+                const FormulaToken* p = pStack[ --sp ];
                 p->IncRef();
                 // store in reverse order such that a push may simply iterate
                 (*pParams)[ nParams - i ] = p;
             }
             pJumpMat->SetJumpParameters( pParams);
             xNew = new ScJumpMatrixToken( pJumpMat );
-            GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
-                        xNew));
+            GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur, xNew));
         }
         PushTempTokenWithoutError( xNew.get());
         // set continuation point of path for main code line
@@ -1568,7 +1586,7 @@ ScMatrixRef ScInterpreter::PopMatrix()
     if( sp )
     {
         --sp;
-        FormulaToken* p = pStack[ sp ];
+        const FormulaToken* p = pStack[ sp ];
         switch (p->GetType())
         {
             case svError:
@@ -1576,7 +1594,10 @@ ScMatrixRef ScInterpreter::PopMatrix()
                 break;
             case svMatrix:
                 {
-                    ScMatrix* pMat = p->GetMatrix();
+                    // ScMatrix itself maintains an im/mutable flag that should
+                    // be obeyed where necessary.. so we can return ScMatrixRef
+                    // here instead of ScConstMatrixRef.
+                    ScMatrix* pMat = const_cast<FormulaToken*>(p)->GetMatrix();
                     if ( pMat )
                         pMat->SetErrorInterpreter( this);
                     else
@@ -1602,8 +1623,8 @@ sc::RangeMatrix ScInterpreter::PopRangeMatrix()
             case svMatrix:
             {
                 --sp;
-                FormulaToken* p = pStack[sp];
-                aRet.mpMat = p->GetMatrix();
+                const FormulaToken* p = pStack[sp];
+                aRet.mpMat = const_cast<FormulaToken*>(p)->GetMatrix();
                 if (aRet.mpMat)
                 {
                     aRet.mpMat->SetErrorInterpreter(this);
@@ -1906,7 +1927,7 @@ StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
 void ScInterpreter::ReverseStack( sal_uInt8 nParamCount )
 {
     //reverse order of parameter stack
-    FormulaToken* p;
+    const FormulaToken* p;
     assert( sp >= nParamCount && " less stack elements than parameters");
     short nStackParams = std::min<short>( sp, nParamCount);
     for ( short i = 0; i < short( nStackParams / 2 ); i++ )
@@ -3879,7 +3900,7 @@ StackVar ScInterpreter::Interpret()
             if ( nStackBase > sp )
                 nStackBase = sp;        // underflow?!?
             sp = nStackBase;
-            PushTempToken( (*aTokenMatrixMapIter).second.get());
+            PushTokenRef( (*aTokenMatrixMapIter).second);
         }
         else
         {
@@ -4572,7 +4593,7 @@ StackVar ScInterpreter::Interpret()
         xResult = new FormulaErrorToken( errUnknownStackVariable);
 
     // release tokens in expression stack
-    FormulaToken** p = pStack;
+    const FormulaToken** p = pStack;
     while( maxsp-- )
         (*p++)->DecRef();
 
@@ -4580,7 +4601,7 @@ StackVar ScInterpreter::Interpret()
     if (eType == svMatrix)
         // Results are immutable in case they would be reused as input for new
         // interpreters.
-        xResult.get()->GetMatrix()->SetImmutable( true);
+        xResult.get()->GetMatrix()->SetImmutable();
     return eType;
 }
 
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 2c357db..5321791 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -326,7 +326,7 @@ ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty)
     pMat->SetErrorInterpreter( this);
     // A temporary matrix is mutable and ScMatrix::CloneIfConst() returns the
     // very matrix.
-    pMat->SetImmutable( false);
+    pMat->SetMutable();
     SCSIZE nCols, nRows;
     pMat->GetDimensions( nCols, nRows);
     if ( nCols != nC || nRows != nR )
@@ -358,10 +358,15 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken
     }
 
     ScTokenMatrixMap::const_iterator aIter;
-    if (pTokenMatrixMap && ((aIter = pTokenMatrixMap->find( pToken))
-                != pTokenMatrixMap->end()))
+    if (pTokenMatrixMap && ((aIter = pTokenMatrixMap->find( pToken)) != pTokenMatrixMap->end()))
     {
-        return (*aIter).second.get()->GetMatrix();
+        /* XXX casting const away here is ugly; ScMatrixToken (to which the
+         * result of this function usually is assigned) should not be forced to
+         * carry a ScConstMatrixRef though.
+         * TODO: a matrix already stored in pTokenMatrixMap should be
+         * read-only and have a copy-on-write mechanism. Previously all tokens
+         * were modifiable so we're already better than before ... */
+        return const_cast<FormulaToken*>((*aIter).second.get())->GetMatrix();
     }
 
     ScMatrixRef pMat = GetNewMat( nMatCols, nMatRows, true);
@@ -371,8 +376,7 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken
     pDok->FillMatrix(*pMat, nTab1, nCol1, nRow1, nCol2, nRow2);
 
     if (pTokenMatrixMap)
-        pTokenMatrixMap->insert( ScTokenMatrixMap::value_type(
-                    pToken, new ScMatrixToken( pMat)));
+        pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pToken, new ScMatrixToken( pMat)));
 
     return pMat;
 }
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index 78d6f47..c466068 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -915,7 +915,7 @@ void ScInterpreter::ScRawSubtract()
         return;
 
     // Fish the 1st parameter from the stack and push it on top.
-    FormulaToken* p = pStack[ sp - nParamCount ];
+    const FormulaToken* p = pStack[ sp - nParamCount ];
     PushWithoutError( *p );
     // Obtain the minuend.
     double fRes = GetDouble();
diff --git a/sc/source/core/tool/interpr8.cxx b/sc/source/core/tool/interpr8.cxx
index 972b125..d219c6e 100644
--- a/sc/source/core/tool/interpr8.cxx
+++ b/sc/source/core/tool/interpr8.cxx
@@ -1895,7 +1895,7 @@ void ScInterpreter::ScIfs_MS()
     }
 
     //push result :
-    FormulaTokenRef xToken( PopToken() );
+    FormulaConstTokenRef xToken( PopToken() );
     if ( xToken )
     {
         // Remove unused arguments of IFS from the stack before pushing the result.
@@ -1904,7 +1904,7 @@ void ScInterpreter::ScIfs_MS()
             Pop();
             nParamCount--;
         }
-        PushTempToken( xToken.get() );
+        PushTokenRef( xToken );
     }
     else
         PushError( errUnknownStackVariable );
@@ -2006,7 +2006,7 @@ void ScInterpreter::ScSwitch_MS()
     }
 
     // push result
-    FormulaTokenRef xToken( PopToken() );
+    FormulaConstTokenRef xToken( PopToken() );
     if ( xToken )
     {
         // Remove unused arguments of SWITCH from the stack before pushing the result.
@@ -2015,7 +2015,7 @@ void ScInterpreter::ScSwitch_MS()
             Pop();
             nParamCount--;
         }
-        PushTempToken( xToken.get() );
+        PushTokenRef( xToken );
     }
     else
         PushError( errUnknownStackVariable );
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 5e19a6c..3b035c2 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -2696,9 +2696,14 @@ ScMatrix* ScMatrix::CloneIfConst()
     return mbCloneIfConst ? Clone() : this;
 }
 
-void ScMatrix::SetImmutable( bool bVal )
+void ScMatrix::SetMutable()
 {
-    mbCloneIfConst = bVal;
+    mbCloneIfConst = false;
+}
+
+void ScMatrix::SetImmutable() const
+{
+    mbCloneIfConst = true;
 }
 
 void ScFullMatrix::Resize( SCSIZE nC, SCSIZE nR)


More information about the Libreoffice-commits mailing list