OR and AND for legacy infix notation are classified as binary
operators but in fact are functions with parameter count. In case
no argument is supplied, GetByte() returns 0 and for that case the
implicit binary operator 2 parameters were wrongly assumed.
Similar for functions expecting 1 parameter, without argument 1
was assumed. For "real" unary and binary operators the compiler
already checks parameters. Omit OR and AND and 1-parameter
functions from this implicit assumption and return the actual 0
count.
Change-Id: Ie05398c112a98021ac2875cf7b6de994aee9d882
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147173
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit
e7ce9bddadb2db222eaa5f594ef1de2e36d57e5c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147129
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
(cherry picked from commit
d6599a2af131994487d2d9223a4fd32a8c3ddc49)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147132
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Gbp-Pq: Name sc-stack-parameter-count.diff
return 0; // parameters and specials
// ocIf... jump commands not for FAP, have cByte then
//2do: bool parameter whether FAP or not?
- else if ( GetByte() )
+ else if (GetByte())
return GetByte(); // all functions, also ocExternal and ocMacro
- else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP)
- return 2; // binary
- else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
- || eOp == ocPercentSign)
- return 1; // unary
+ else if (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_BIN_OP && eOp != ocAnd && eOp != ocOr)
+ return 2; // binary operators, compiler checked; OR and AND legacy but are functions
+ else if ((SC_OPCODE_START_UN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP) || eOp == ocPercentSign)
+ return 1; // unary operators, compiler checked
else if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
return 0; // no parameter
- else if (SC_OPCODE_START_1_PAR <= eOp && eOp < SC_OPCODE_STOP_1_PAR)
- return 1; // one parameter
else if (FormulaCompiler::IsOpCodeJumpCommand( eOp ))
return 1; // only the condition counts as parameter
else
inline bool MustHaveParamCount( short nAct, short nMust );
inline bool MustHaveParamCount( short nAct, short nMust, short nMax );
inline bool MustHaveParamCountMin( short nAct, short nMin );
+ inline bool MustHaveParamCountMinWithStackCheck( short nAct, short nMin );
void PushParameterExpected();
void PushIllegalParameter();
void PushIllegalArgument();
return false;
}
+inline bool ScInterpreter::MustHaveParamCountMinWithStackCheck( short nAct, short nMin )
+{
+ assert(sp >= nAct);
+ if (sp < nAct)
+ {
+ PushParameterExpected();
+ return false;
+ }
+ return MustHaveParamCountMin( nAct, nMin);
+}
+
inline bool ScInterpreter::CheckStringPositionArgument( double & fVal )
{
if (!std::isfinite( fVal))
GetNumberSequenceArray( 1, aArray, false );
if ( aArray.empty() || nGlobalError != FormulaError::NONE )
{
- SetError( FormulaError::NoValue );
+ PushNoValue();
return;
}
if ( bInclusive )
GetNumberSequenceArray( 1, aArray, false );
if ( aArray.empty() || nGlobalError != FormulaError::NONE )
{
- SetError( FormulaError::NoValue );
+ PushNoValue();
return;
}
if ( bInclusive )
else if (sp >= pCur->GetParamCount())
nStackBase = sp - pCur->GetParamCount();
else
- nStackBase = sp; // underflow?!?
+ {
+ SAL_WARN("sc.core", "Stack anomaly at " << aPos.Format(
+ ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc)
+ << " eOp: " << static_cast<int>(eOp)
+ << " params: " << static_cast<int>(pCur->GetParamCount())
+ << " nStackBase: " << nStackBase << " sp: " << sp);
+ nStackBase = sp;
+ assert(!"underflow");
+ }
}
switch( eOp )