sc/source/core/data/formulacell.cxx | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+)
New commits: commit 81c19355d7ad830c2356d7d82e244929be3823a8 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sat Aug 19 16:42:25 2023 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Sat Aug 19 20:55:08 2023 +0200 crashtesting: parallel calc assert with Lookup seen in forum-mso-en4-55192.xlsx with a singlecell as the result vector which gets autoextended outside the range that the pre-parallel calc took into consideration on set up. For simplicity if there is a result vector assume that if it doesn't match the size of the search vector that we can't parallelize this. Change-Id: Ic67e1b5b35964760ac5b1608cd516a69e08d0540 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155862 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 4b974831992b..85d43700461e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -4432,6 +4432,52 @@ struct ScDependantsCalculator return nRowLen; } + // Because Lookup will extend the Result Vector under certain cirumstances listed at: + // https://wiki.documentfoundation.org/Documentation/Calc_Functions/LOOKUP + // then if the Lookup has a Result Vector only accept the Lookup for parallelization + // of the Result Vector has the same dimensions as the Search Vector. + bool LookupResultVectorMismatch(sal_Int32 nTokenIdx) + { + if (nTokenIdx >= 3) + { + FormulaToken** pRPNArray = mrCode.GetCode(); + if (pRPNArray[nTokenIdx - 1]->GetOpCode() == ocPush && // <- result vector + pRPNArray[nTokenIdx - 2]->GetOpCode() == ocPush && // <- search vector + pRPNArray[nTokenIdx - 2]->GetType() == svDoubleRef && + pRPNArray[nTokenIdx - 3]->GetOpCode() == ocPush) // <- search criterion + { + auto res = pRPNArray[nTokenIdx - 1]; + // If Result vector is just a single cell reference + // LOOKUP extends it as a column vector. + if (res->GetType() == svSingleRef) + return true; + + // If Result vector is a cell range and the match position + // falls outside its length, it gets automatically extended + // to the length of Search vector, but in the direction of + // Result vector. + if (res->GetType() == svDoubleRef) + { + ScComplexRefData aRef1 = *res->GetDoubleRef(); + ScComplexRefData aRef2 = *pRPNArray[nTokenIdx - 2]->GetDoubleRef(); + ScRange resultRange = aRef1.toAbs(mrDoc, mrPos); + ScRange sourceRange = aRef2.toAbs(mrDoc, mrPos); + + SCROW nResultRows = resultRange.aEnd.Row() - resultRange.aStart.Row(); + SCROW nSourceRows = sourceRange.aEnd.Row() - sourceRange.aStart.Row(); + if (nResultRows != nSourceRows) + return true; + + SCCOL nResultCols = resultRange.aEnd.Col() - resultRange.aStart.Col(); + SCCOL nSourceCols = sourceRange.aEnd.Col() - sourceRange.aStart.Col(); + if (nResultCols != nSourceCols) + return true; + } + } + } + return false; + } + bool DoIt(ScRangeList* pSuccessfulDependencies, ScAddress* pDirtiedAddress) { // Partially from ScGroupTokenConverter::convert in sc/source/core/data/grouptokenconverter.cxx @@ -4460,6 +4506,12 @@ struct ScDependantsCalculator return false; } + if (p->GetOpCode() == ocLookup && LookupResultVectorMismatch(nTokenIdx)) + { + SAL_INFO("sc.core.formulacell", "Lookup Result Vector size doesn't match Search Vector"); + return false; + } + switch (p->GetType()) { case svSingleRef: