diff options
author | Eike Rathke <erack@redhat.com> | 2016-08-25 11:02:50 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-08-25 10:20:26 +0000 |
commit | db8c3afe8c5a5756537d16cf0399e3b46876cc8b (patch) | |
tree | e43e25742e2c461e565adba3d8a69ecccd6c86ab /sc | |
parent | 9fda8f5ad61c11d72718a50a175b23cb43bfa9ab (diff) |
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@redhat.com>
Tested-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 2 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/scmatrix.hxx | 10 | ||||
-rw-r--r-- | sc/inc/table.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/documen8.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/table1.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 21 | ||||
-rw-r--r-- | sc/source/core/inc/jumpmatrix.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/formulagroup.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 42 | ||||
-rw-r--r-- | sc/source/core/tool/interpr2.cxx | 59 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 79 | ||||
-rw-r--r-- | sc/source/core/tool/interpr5.cxx | 16 | ||||
-rw-r--r-- | sc/source/core/tool/interpr6.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/interpr8.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/tool/scmatrix.cxx | 9 |
17 files changed, 153 insertions, 111 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index a73f7c4eed13..bb7a2b91b603 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 b2f97534cc77..749eab291595 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 62cddee992ab..b565335844ff 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 bd6344657dfa..708e53537750 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 cae1ff55e051..9faf724db50c 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 a84c2d09a01e..ca158fdda762 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 feac2964b94e..f770c7e02d61 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 f1b8e0d4e11c..c6987f850b85 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 ed98e53f5ad6..4ef4f87b282a 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 15ce590bfc6c..e165e0c317fe 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 52db34123cb1..85f443fa56c4 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 658119848879..b71d1babee59 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 9b200d5cf494..5ff5cfaf909c 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 2c357dbb99cf..5321791e4eb6 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 78d6f47c2589..c46606891c95 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 972b125267c0..d219c6e4692f 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 5e19a6c6a32a..3b035c2c868b 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) |