diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp index 9d109667b19bca1327400ba39a97d26ff8b87c0a..4ae9e1ced1713825df96021752e24d3edf3a1c15 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp @@ -14,6 +14,7 @@ */ #include "constantExpressionLowering.h" +#include #include #include "checker/ETSchecker.h" @@ -614,11 +615,23 @@ static bool IsAdditiveExpression(const ir::BinaryExpression *expr) return opType == lexer::TokenType::PUNCTUATOR_PLUS || opType == lexer::TokenType::PUNCTUATOR_MINUS; } +static double CalculateFloatZeroDevision(double leftNum) +{ + if (leftNum == 0.0) { + return std::numeric_limits::quiet_NaN(); + } else if (leftNum > 0) { + return std::numeric_limits::infinity(); + } else { + return -std::numeric_limits::infinity(); + } +} + template static TargetType PerformMultiplicativeOperation(TargetType leftNum, TargetType rightNum, const ir::BinaryExpression *expr, public_lib::Context *context) { auto isForbiddenZeroDivision = [&rightNum]() { return std::is_integral_v && rightNum == 0; }; + auto isFloatZeroDevision = [&rightNum]() { return std::is_floating_point_v && rightNum == 0; }; auto opType = expr->OperatorType(); switch (opType) { case lexer::TokenType::PUNCTUATOR_MULTIPLY: { @@ -630,6 +643,12 @@ static TargetType PerformMultiplicativeOperation(TargetType leftNum, TargetType // Max integral value return std::numeric_limits::max(); } + if (isFloatZeroDevision()) { + return CalculateFloatZeroDevision(leftNum); + } + + ES2PANDA_ASSERT(rightNum != 0); + // CC-OFFNXT(G.EXP.22-CPP) false positive return leftNum / rightNum; } case lexer::TokenType::PUNCTUATOR_MOD: { diff --git a/ets2panda/compiler/lowering/ets/unboxLowering.cpp b/ets2panda/compiler/lowering/ets/unboxLowering.cpp index 6baa75bd81f6f4d0c1726f7c910172bacb1344eb..68ee229e51f3f7956e143fde4d6161f4ad7f1a61 100644 --- a/ets2panda/compiler/lowering/ets/unboxLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unboxLowering.cpp @@ -497,8 +497,36 @@ static ir::Expression *InsertBoxing(UnboxContext *uctx, ir::Expression *expr) return constrCall; } +static checker::Type *SelectTypeToConvert( + std::tuple ctx, checker::Type *toConvert, + checker::Type *expectedType, checker::Type *actualType) +{ + auto [uctx, relation, checker] = ctx; + if (toConvert == nullptr && actualType->IsCharType() && + relation->IsSupertypeOf(expectedType, checker->GlobalBuiltinETSStringType())) { + return uctx->checker->GlobalBuiltinETSStringType(); + } + if (toConvert == nullptr && actualType->IsByteType() && + relation->IsSupertypeOf(expectedType, checker->GlobalCharBuiltinType())) { + return uctx->checker->GlobalCharBuiltinType(); + } + + // Appears in "~b" if "b" is of type Float + if (toConvert == nullptr && actualType->IsFloatType() && + relation->IsSupertypeOf(expectedType, checker->GlobalIntBuiltinType())) { + return checker->GlobalIntBuiltinType(); + } + + // Appears in "~b" if "b" is of type Double + if (toConvert == nullptr && actualType->IsDoubleType() && + relation->IsSupertypeOf(expectedType, checker->GlobalLongBuiltinType())) { + return checker->GlobalLongBuiltinType(); + } + return toConvert; +} + /* NOTE(gogabr): conversions should be inserted at the checker stage. This function is temporary. */ -// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05, huge_cyclomatic_complexity) solid logic +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, huge_cyclomatic_complexity) solid logic static ir::Expression *InsertPrimitiveConversionIfNeeded(UnboxContext *uctx, ir::Expression *expr, checker::Type *expectedType) { @@ -546,27 +574,7 @@ static ir::Expression *InsertPrimitiveConversionIfNeeded(UnboxContext *uctx, ir: break; } - if (toConvert == nullptr && actualType->IsCharType() && - relation->IsSupertypeOf(expectedType, checker->GlobalBuiltinETSStringType())) { - toConvert = uctx->checker->GlobalBuiltinETSStringType(); - } - if (toConvert == nullptr && actualType->IsByteType() && - relation->IsSupertypeOf(expectedType, checker->GlobalCharBuiltinType())) { - toConvert = uctx->checker->GlobalCharBuiltinType(); - } - - // Appears in "~b" if "b" is of type Float - if (toConvert == nullptr && actualType->IsFloatType() && - relation->IsSupertypeOf(expectedType, checker->GlobalIntBuiltinType())) { - toConvert = checker->GlobalIntBuiltinType(); - } - - // Appears in "~b" if "b" is of type Double - if (toConvert == nullptr && actualType->IsDoubleType() && - relation->IsSupertypeOf(expectedType, checker->GlobalLongBuiltinType())) { - toConvert = checker->GlobalLongBuiltinType(); - } - + toConvert = SelectTypeToConvert(std::make_tuple(uctx, relation, checker), toConvert, expectedType, actualType); ES2PANDA_ASSERT(toConvert != nullptr); auto *toConvertUnboxed = checker->MaybeUnboxType(toConvert);