From e2d9d494aff44da96b218fe92aae899c2296b56c Mon Sep 17 00:00:00 2001 From: renguangxuan Date: Sat, 30 Aug 2025 10:41:57 +0800 Subject: [PATCH] Fix break target crash Issue: #ICVJC1 Signed-off-by: renguangxuan --- ets2panda/checker/ETSAnalyzer.cpp | 41 +++++++++++++------ .../test/ast/compiler/ets/break_target.ets | 24 +++++++++++ .../continue_while_target_outside_lambda.ets | 2 +- ets2panda/util/diagnostic/semantic.yaml | 4 +- 4 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/break_target.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 3ddb14664f..b39b10ba85 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3212,6 +3212,32 @@ checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const return ReturnTypeForStatement(st); } +static void CheckJumpStatement(ir::AstNode *st, ETSChecker *checker) +{ + const ir::AstNode *target = nullptr; + ir::Identifier *ident = nullptr; + if (st->IsContinueStatement()) { + target = st->AsContinueStatement()->Target(); + ident = st->AsContinueStatement()->Ident(); + } else { + target = st->AsBreakStatement()->Target(); + ident = st->AsBreakStatement()->Ident(); + } + + // CTE if target is outside the function + auto getEnclosingMethod = [](const ir::AstNode *node) { + const ir::AstNode *enclosingMethod = node->Parent(); + while (enclosingMethod != nullptr && !enclosingMethod->IsMethodDefinition() && + !enclosingMethod->IsArrowFunctionExpression()) { + enclosingMethod = enclosingMethod->Parent(); + } + return enclosingMethod; + }; + if (ident != nullptr && getEnclosingMethod(st) != getEnclosingMethod(target)) { + checker->LogError(diagnostic::CONTINUE_OR_BREAK_TARGET_OUTSIDE_FUNCTION, {}, st->Start()); + } +} + checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const { ETSChecker *checker = GetETSChecker(); @@ -3225,6 +3251,8 @@ checker::Type *ETSAnalyzer::Check(ir::BreakStatement *st) const return checker->GlobalTypeError(); } + CheckJumpStatement(st, checker); + checker->Context().OnBreakStatement(st); return ReturnTypeForStatement(st); } @@ -3343,18 +3371,7 @@ checker::Type *ETSAnalyzer::Check(ir::ContinueStatement *st) const return checker->GlobalTypeError(); } - // CTE if target is outside the function - auto getEnclosingMethod = [](const ir::AstNode *node) { - const ir::AstNode *enclosingMethod = node->Parent(); - while (enclosingMethod != nullptr && !enclosingMethod->IsMethodDefinition() && - !enclosingMethod->IsArrowFunctionExpression()) { - enclosingMethod = enclosingMethod->Parent(); - } - return enclosingMethod; - }; - if (getEnclosingMethod(st) != getEnclosingMethod(st->Target())) { - checker->LogError(diagnostic::CONTINUE_TARGET_OUTSIDE_FUNCTION, {}, st->Start()); - } + CheckJumpStatement(st, checker); checker->AddStatus(CheckerStatus::MEET_CONTINUE); return ReturnTypeForStatement(st); diff --git a/ets2panda/test/ast/compiler/ets/break_target.ets b/ets2panda/test/ast/compiler/ets/break_target.ets new file mode 100644 index 0000000000..a3af3dd42c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/break_target.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 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. + */ + +target: while(true) { + () => { + while(true) { + break target; + } + } +} + +/* @@? 19:13 Error TypeError: Continue or break target can't be outside the function */ diff --git a/ets2panda/test/ast/parser/ets/continue_while_target_outside_lambda.ets b/ets2panda/test/ast/parser/ets/continue_while_target_outside_lambda.ets index b80b62d701..77a0f430c3 100644 --- a/ets2panda/test/ast/parser/ets/continue_while_target_outside_lambda.ets +++ b/ets2panda/test/ast/parser/ets/continue_while_target_outside_lambda.ets @@ -29,4 +29,4 @@ function main(): void { } } -/* @@? 26:17 Error TypeError: Continue target can't be outside the function */ +/* @@? 26:17 Error TypeError: Continue or break target can't be outside the function */ diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 85eeb403a7..e5c787cd31 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -296,9 +296,9 @@ semantic: id: 363 message: "Missing initializer in const declaration" -- name: CONTINUE_TARGET_OUTSIDE_FUNCTION +- name: CONTINUE_OR_BREAK_TARGET_OUTSIDE_FUNCTION id: 49316 - message: "Continue target can't be outside the function" + message: "Continue or break target can't be outside the function" - name: CTOR_CLASS_NOT_FIRST id: 201 -- Gitee