include/formula/token.hxx             |    1 +
 sc/inc/formularesult.hxx              |    3 +++
 sc/source/core/data/formulacell.cxx   |    2 ++
 sc/source/core/tool/formularesult.cxx |   25 +++++++++++++++++++++++++
 4 files changed, 31 insertions(+)

New commits:
commit 9d29649e07a3b2c5c2b3dda1dc15c0ca1ed51ae3
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Sun Apr 14 21:09:59 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Apr 15 14:08:06 2024 +0200

    Related: tdf#160056 FormulaResult may ref an initial interpreter 
FormulaToken
    
    If a token from the original tokens, supplied to a parallel group 
calculation
    while RefCounting was disabled for those tokens, ends up as a FormulaResult
    token, then fix up the ref count when parallel calculation ends
    
    Change-Id: I2587c25d216ab170725017b67b97d203a578160b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166080
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index 68461a48db1d..89043877a4fd 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -186,6 +186,7 @@ public:
     }
 
     void SetRefCntPolicy(RefCntPolicy ePolicy) { eRefCntPolicy = ePolicy; }
+    RefCntPolicy GetRefCntPolicy() const { return eRefCntPolicy; }
 
     oslInterlockedCount GetRef() const       { return mnRefCnt; }
     OpCode              GetOpCode() const    { return eOp; }
diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx
index 581d9a4bba3d..44aab47acd44 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -62,6 +62,7 @@ class ScFormulaResult
         const formula::FormulaToken*  mpToken;    // if not, result token 
obtained from interpreter
     };
     bool                mbToken :1; // whether content of union is a token
+    bool                mbNoneRefCnt :1; // if token was added when using 
RefCntPolicy::None
     bool                mbEmpty :1; // empty cell result
     bool                mbEmptyDisplayedAsString :1;    // only if mbEmpty
     // If set it implies that the result is a simple double (in mfValue) and 
no error
@@ -208,6 +209,8 @@ public:
     /** Get the ScMatrixFormulaCellToken* if token is of that type, else NULL.
         Shouldn't be used externally except by 
ScFormulaCell::SetMatColsRows(). */
     ScMatrixFormulaCellToken* GetMatrixFormulaCellTokenNonConst();
+
+    void HandleStuffAfterParallelCalculation();
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx 
b/sc/source/core/data/formulacell.cxx
index e57514b0345a..529ea73a7e6e 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2336,6 +2336,8 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& 
rContext, ScInterpretTa
 
 void ScFormulaCell::HandleStuffAfterParallelCalculation(ScInterpreter* 
pInterpreter)
 {
+    aResult.HandleStuffAfterParallelCalculation();
+
     if( !pCode->GetCodeLen() )
         return;
 
diff --git a/sc/source/core/tool/formularesult.cxx 
b/sc/source/core/tool/formularesult.cxx
index b421354550a3..08ef363ff68f 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -26,6 +26,7 @@ FormulaResultValue::FormulaResultValue( FormulaError nErr ) : 
mfValue(0.0), meTy
 ScFormulaResult::ScFormulaResult() :
     mpToken(nullptr),
     mbToken(true),
+    mbNoneRefCnt(false),
     mbEmpty(false),
     mbEmptyDisplayedAsString(false),
     mbValueCached(false),
@@ -58,10 +59,12 @@ ScFormulaResult::ScFormulaResult( const ScFormulaResult & r 
) :
     }
     else
         mfValue = r.mfValue;
+    mbNoneRefCnt = mbToken && mpToken && mpToken->GetRefCntPolicy() == 
formula::RefCntPolicy::None;
 }
 
 ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) :
     mbToken(false),
+    mbNoneRefCnt(false),
     mbEmpty(false),
     mbEmptyDisplayedAsString(false),
     mbValueCached(false),
@@ -129,6 +132,7 @@ void ScFormulaResult::ResolveToken( const 
formula::FormulaToken * p )
                 mbToken = true;
         }
     }
+    mbNoneRefCnt = mbToken && mpToken && mpToken->GetRefCntPolicy() == 
formula::RefCntPolicy::None;
 }
 
 ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
@@ -151,6 +155,7 @@ void ScFormulaResult::Assign( const ScFormulaResult & r )
         if (mbToken && mpToken)
             mpToken->DecRef();
         mbToken = false;
+        mbNoneRefCnt = false;
         mbEmpty = true;
         mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
         meMultiline = r.meMultiline;
@@ -236,6 +241,7 @@ void ScFormulaResult::SetDouble( double f )
             mpToken->DecRef();
         mfValue = f;
         mbToken = false;
+        mbNoneRefCnt = false;
         meMultiline = MULTILINE_FALSE;
         mbValueCached = true;
     }
@@ -563,12 +569,14 @@ void ScFormulaResult::SetHybridDouble( double f )
             mpToken->DecRef();
             mpToken = new ScHybridCellToken( f, aString, aFormula, false);
             mpToken->IncRef();
+            mbNoneRefCnt = false;
         }
     }
     else
     {
         mfValue = f;
         mbToken = false;
+        mbNoneRefCnt = false;
         meMultiline = MULTILINE_FALSE;
         mbValueCached = true;
     }
@@ -585,6 +593,7 @@ void ScFormulaResult::SetHybridString( const 
svl::SharedString& rStr )
     mpToken = new ScHybridCellToken( f, rStr, aFormula, false);
     mpToken->IncRef();
     mbToken = true;
+    mbNoneRefCnt = false;
 }
 
 void ScFormulaResult::SetHybridEmptyDisplayedAsString()
@@ -602,6 +611,7 @@ void ScFormulaResult::SetHybridEmptyDisplayedAsString()
     mpToken = new ScHybridCellToken( f, aStr, aFormula, true);
     mpToken->IncRef();
     mbToken = true;
+    mbNoneRefCnt = false;
 }
 
 void ScFormulaResult::SetHybridFormula( const OUString & rFormula )
@@ -615,6 +625,7 @@ void ScFormulaResult::SetHybridFormula( const OUString & 
rFormula )
     mpToken = new ScHybridCellToken( f, aStr, rFormula, false);
     mpToken->IncRef();
     mbToken = true;
+    mbNoneRefCnt = false;
 }
 
 void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const 
ScConstMatrixRef& pMat, const formula::FormulaToken* pUL )
@@ -625,6 +636,7 @@ void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, 
const ScConstMatrixRe
     mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL);
     mpToken->IncRef();
     mbToken = true;
+    mbNoneRefCnt = false;
 }
 
 const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() 
const
@@ -638,4 +650,17 @@ ScMatrixFormulaCellToken* 
ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
     return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
 }
 
+// If a token from the original tokens, supplied to a parallel group 
calculation
+// while RefCounting was disabled for those tokens, ends up as a FormulaResult
+// token, then fix up the ref count now
+void ScFormulaResult::HandleStuffAfterParallelCalculation()
+{
+    if (mbNoneRefCnt)
+    {
+        assert(mbToken && mpToken && mpToken->GetRefCntPolicy() != 
formula::RefCntPolicy::None);
+        mpToken->IncRef();
+        mbNoneRefCnt = false;
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to