From 98cd3c1d550901e40601481df0d81b0ad67bc5d4 Mon Sep 17 00:00:00 2001 From: Gavin Halliday Date: Thu, 12 Sep 2024 12:48:38 +0100 Subject: [PATCH] HPCC-32654 Fix crash in eclcc for mismatched functions in PROJECT(module, interface) Signed-off-by: Gavin Halliday --- ecl/hql/hqlexpr.cpp | 4 ++- ecl/hql/hqlgram2.cpp | 24 +++++++++++++++++ ecl/regress/iproject.ecl | 50 ++++++++++++++++++++++++++++++++++++ ecl/regress/iproject_err.ecl | 50 ++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 ecl/regress/iproject.ecl create mode 100644 ecl/regress/iproject_err.ecl diff --git a/ecl/hql/hqlexpr.cpp b/ecl/hql/hqlexpr.cpp index 57529bce0ae..5d5da00fec7 100644 --- a/ecl/hql/hqlexpr.cpp +++ b/ecl/hql/hqlexpr.cpp @@ -11028,7 +11028,9 @@ IHqlExpression *CHqlDelayedCall::clone(HqlExprArray &newkids) IHqlExpression * CHqlDelayedCall::makeDelayedCall(IHqlExpression * _funcdef, HqlExprArray &operands) { - ITypeInfo * returnType = _funcdef->queryType()->queryChildType(); + ITypeInfo * funcType = _funcdef->queryType(); + assertex(funcType->getTypeCode() == type_function); + ITypeInfo * returnType = funcType->queryChildType(); CHqlDelayedCall * ret; switch (returnType->getTypeCode()) { diff --git a/ecl/hql/hqlgram2.cpp b/ecl/hql/hqlgram2.cpp index 6692f19502e..37c0f2ce3f4 100644 --- a/ecl/hql/hqlgram2.cpp +++ b/ecl/hql/hqlgram2.cpp @@ -3638,6 +3638,30 @@ IHqlExpression * HqlGram::implementInterfaceFromModule(const attribute & modpos, { HqlExprArray parameters; bool isParametered = extractSymbolParameters(parameters, &baseSym); + if (baseSym.isFunction() != match->isFunction()) + { + if (isParametered) + { + //Convert the value to a function definition - the parameters will be ignored + IHqlExpression * formals = queryFunctionParameters(&baseSym); + IHqlExpression * defaults = queryFunctionDefaults(&baseSym); + OwnedHqlExpr funcdef = createFunctionDefinition(id, LINK(match->queryBody()), LINK(formals), LINK(defaults), NULL); + match.setown(match->cloneAllAnnotations(funcdef)); + } + else + { + //Convert a function into a value - possible if all parameters (including none) have default values + if (!allParametersHaveDefaults(match)) + { + reportError(ERR_EXPECTED_ATTRIBUTE, ipos, "Symbol %s is defined as a value in the base scope, but a function with non-default parameters in the interface", str(id)); + } + else + { + HqlExprArray actuals; + match.setown(createBoundFunction(nullptr, match, actuals, nullptr, false)); + } + } + } checkDerivedCompatible(id, newScopeExpr, match, isParametered, parameters, modpos); newScope->defineSymbol(LINK(match)); diff --git a/ecl/regress/iproject.ecl b/ecl/regress/iproject.ecl new file mode 100644 index 00000000000..3822182065d --- /dev/null +++ b/ecl/regress/iproject.ecl @@ -0,0 +1,50 @@ +/*############################################################################## + + HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +############################################################################## */ + +myModule := MODULE + + EXPORT value1 := 100; + EXPORT value2 := 200; + EXPORT value3(unsigned x = 10) := 300; + EXPORT value4() := 400; + +END; + +myInterface := INTERFACE + + EXPORT value1 := 0; + EXPORT value2(unsigned unknown) := 0; + EXPORT value3 := 0; + EXPORT value4() := 0; + +END; + + + +display(myInterface x) := FUNCTION + RETURN + ORDERED( + OUTPUT(x.value1); + OUTPUT(x.value2(99999)); + OUTPUT(x.value3); + OUTPUT(x.value4()); + ); +END; + + +mappedModule := PROJECT(myModule, myInterface); +display(mappedModule); \ No newline at end of file diff --git a/ecl/regress/iproject_err.ecl b/ecl/regress/iproject_err.ecl new file mode 100644 index 00000000000..cb4d64b7c74 --- /dev/null +++ b/ecl/regress/iproject_err.ecl @@ -0,0 +1,50 @@ +/*############################################################################## + + HPCC SYSTEMS software Copyright (C) 2024 HPCC Systems®. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +############################################################################## */ + +myModule := MODULE + + EXPORT value1 := 100; + EXPORT value2 := 200; + EXPORT value3(unsigned i) := 300; // invalid - no default value supplied + EXPORT value4() := 400; + +END; + +myInterface := INTERFACE + + EXPORT value1 := 0; + EXPORT value2() := 0; + EXPORT value3 := 0; + EXPORT value4() := 0; + +END; + + + +display(myInterface x) := FUNCTION + RETURN + ORDERED( + OUTPUT(x.value1); + OUTPUT(x.value2()); + OUTPUT(x.value3); + OUTPUT(x.value4()); + ); +END; + + +mappedModule := PROJECT(myModule, myInterface); +display(mappedModule); \ No newline at end of file