From f433efbdfa9b95ef7f05bbca9eb54d6698c9b036 Mon Sep 17 00:00:00 2001 From: Molokanov Yaroslav Date: Mon, 26 Feb 2024 16:00:11 +0300 Subject: [PATCH] Fixed issue with constant narrowing integer conversion Signed-off-by: Molokanov Yaroslav --- ets2panda/checker/ETSAnalyzer.cpp | 2 + ets2panda/checker/ets/typeRelationContext.h | 3 +- ets2panda/ir/expressions/arrayExpression.cpp | 9 ++-- ets2panda/ir/ts/tsAsExpression.h | 5 ++ .../runtime/ets/const_narrowing_int_conv.ets | 48 +++++++++++++++++++ 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 ets2panda/test/runtime/ets/const_narrowing_int_conv.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 7917598b0e..b66acc2fbf 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2624,6 +2624,8 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const checker->ComputeApparentType(targetType); expr->SetTsType(targetType); + expr->SetConst(sourceType->HasTypeFlag(TypeFlag::CONSTANT) || + (expr->Expr()->IsTSAsExpression() && expr->Expr()->AsTSAsExpression()->IsConst())); return expr->TsType(); } diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index 4e6bb913ef..7229565cbe 100644 --- a/ets2panda/checker/ets/typeRelationContext.h +++ b/ets2panda/checker/ets/typeRelationContext.h @@ -49,7 +49,8 @@ public: // NOTE (oeotvos) The narrowing flag will be applied here. It means, that the result of "let tmp: int = 1.5" // will be 1, which could cause problems. - if (source->HasTypeFlag(TypeFlag::CONSTANT)) { + if (source->HasTypeFlag(TypeFlag::CONSTANT) || + (node->IsTSAsExpression() && node->AsTSAsExpression()->IsConst())) { flags_ |= TypeRelationFlag::NARROWING; } diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index fb53daba53..31531f228e 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -380,9 +380,6 @@ checker::Type *ArrayExpression::Check(checker::ETSChecker *checker) void ArrayExpression::GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker, Expression *param, checker::TypeRelationFlag flags) { - if (preferredType_ != nullptr) { - return; - } auto paramType = param->Check(checker); if (paramType->IsETSArrayType()) { paramType = paramType->AsETSArrayType()->ElementType(); @@ -394,7 +391,11 @@ void ArrayExpression::GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker isAssignable &= assignCtx.IsAssignable(); } if (isAssignable) { - preferredType_ = param->Check(checker); + preferredType_ = paramType; + if (TsType() != nullptr) { + SetTsType(nullptr); + preferredType_ = nullptr; + } } } diff --git a/ets2panda/ir/ts/tsAsExpression.h b/ets2panda/ir/ts/tsAsExpression.h index 69688f971e..84cebad74c 100644 --- a/ets2panda/ir/ts/tsAsExpression.h +++ b/ets2panda/ir/ts/tsAsExpression.h @@ -56,6 +56,11 @@ public: return isConst_; } + void SetConst(bool isConst) noexcept + { + isConst_ = isConst; + } + [[nodiscard]] TSAsExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void SetUncheckedCast(bool isUncheckedCast) noexcept diff --git a/ets2panda/test/runtime/ets/const_narrowing_int_conv.ets b/ets2panda/test/runtime/ets/const_narrowing_int_conv.ets new file mode 100644 index 0000000000..4337c468f0 --- /dev/null +++ b/ets2panda/test/runtime/ets/const_narrowing_int_conv.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * 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. + */ + +function foo(a: byte) : int { + return 10; +} + +function foo(a: short) : int { + return 12; +} + +function foo(a: byte[]) : int { + return 14; +} + +function foo(a: short[]) : int { + return 16; +} + +function main(): void { + let b: byte = 127; + let c: char = 0x42E; + let d: byte = 0x007f as short; + let e: byte = (100 as int) as int; + + assert(b == 127); + assert(c == 0x42E); + assert(d == 0x007f); + assert(e == 100); + + assert(foo(2 as byte) == 10); + assert(foo(2 as short) == 12); + + assert(foo([2 as byte, 1]) == 14); + assert(foo([2 as short, 1]) == 16); +} -- Gitee