From aa7c63ec369972e270df340b3d78fa99c783fde3 Mon Sep 17 00:00:00 2001 From: wangzhengji Date: Thu, 14 Aug 2025 11:33:55 +0800 Subject: [PATCH] Fix unexpected cte of constructor super Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICSWQ4 Signed-off-by: wangzhengji --- ets2panda/checker/ETSchecker.h | 2 + ets2panda/checker/ets/object.cpp | 45 +++++++++++++++---- .../ets/constructor_super_under_ifstmt.ets | 35 +++++++++++++++ 3 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 ets2panda/test/runtime/ets/constructor_super_under_ifstmt.ets diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index a42ab34a91a..1738cb4b73e 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -285,6 +285,8 @@ public: varbinder::Variable *GetExtensionFuncVarInFunctionScope(const ir::MemberExpression *const memberExpr); varbinder::Variable *ResolveInstanceExtension(const ir::MemberExpression *memberExpr); void CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig); + ArenaVector ExtractFromIfStatement( + const ArenaVector &stmts); void CheckThisOrSuperCallInConstructor(ETSObjectType *classType, Signature *ctorSig); void CheckExpressionsInConstructor(const ArenaVector &arguments); ArenaVector CheckMemberOrCallOrObjectExpressionInConstructor(const ir::Expression *arg); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 7303f27a93e..a31ab0a591f 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1450,21 +1450,23 @@ void ETSChecker::CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig } auto &stmts = ctorSig->Function()->Body()->AsBlockStatement()->Statements(); - const auto thisCall = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) { + + auto extendStmts = ExtractFromIfStatement(stmts); + const auto thisCall = std::find_if(extendStmts.begin(), extendStmts.end(), [](const ir::Statement *stmt) { return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() && stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsThisExpression(); }); // There is an alternate constructor invocation, no need for super constructor invocation - if (thisCall != stmts.end()) { + if (thisCall != extendStmts.end()) { return; } - const auto superExpr = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) { + const auto superExpr = std::find_if(extendStmts.begin(), extendStmts.end(), [](const ir::Statement *stmt) { return stmt->IsExpressionStatement() && stmt->AsExpressionStatement()->GetExpression()->IsCallExpression() && stmt->AsExpressionStatement()->GetExpression()->AsCallExpression()->Callee()->IsSuperExpression(); }); // There is no super expression - if (superExpr == stmts.end()) { + if (superExpr == extendStmts.end()) { const auto superTypeCtorSigs = classType->SuperType()->ConstructSignatures(); const auto superTypeCtorSig = std::find_if(superTypeCtorSigs.begin(), superTypeCtorSigs.end(), [](const Signature *sig) { return sig->MinArgCount() == 0; }); @@ -1477,6 +1479,36 @@ void ETSChecker::CheckImplicitSuper(ETSObjectType *classType, Signature *ctorSig } } +// Extract statements under the if and else conditions of one or more layers in 'stmts' +ArenaVector ETSChecker::ExtractFromIfStatement( + const ArenaVector &stmts) +{ + ArenaVector newStmts(ProgramAllocator()->Adapter()); + auto tryExtractFromIfStatement = [&](const auto &self, const ir::Statement *stmt) -> bool { + if (!stmt->IsIfStatement()) { + return false; + } + auto ifStmt = stmt->AsIfStatement(); + if (ifStmt->Consequent() != nullptr && ifStmt->Consequent()->IsBlockStatement()) { + self(self, ifStmt->Consequent()->AsBlockStatement()->Statements()); + } + if (ifStmt->Alternate() && ifStmt->Alternate()->IsBlockStatement()) { + self(self, ifStmt->Alternate()->AsBlockStatement()->Statements()); + } + + return true; + }; + auto extractor = [&](const auto &self, const ArenaVector &statements) -> void { + for (const auto &stmt : statements) { + if (!tryExtractFromIfStatement(self, stmt)) { + newStmts.push_back(stmt); + } + } + }; + extractor(extractor, stmts); + return newStmts; +} + void ETSChecker::CheckThisOrSuperCallInConstructor(ETSObjectType *classType, Signature *ctorSig) { if (classType == GlobalETSObjectType()) { @@ -1847,11 +1879,6 @@ ETSObjectType *ETSChecker::CheckThisOrSuperAccess(ir::Expression *node, ETSObjec LogError(diagnostic::CTOR_CLASS_NOT_FIRST, {msg}, node->Start()); return classType; } - - if (sig->Function()->Body()->AsBlockStatement()->Statements().front() != node->Parent()->Parent()) { - LogError(diagnostic::CTOR_CLASS_NOT_FIRST, {msg}, node->Start()); - return classType; - } } if (HasStatus(checker::CheckerStatus::IN_STATIC_CONTEXT)) { diff --git a/ets2panda/test/runtime/ets/constructor_super_under_ifstmt.ets b/ets2panda/test/runtime/ets/constructor_super_under_ifstmt.ets new file mode 100644 index 00000000000..c6a35271b7e --- /dev/null +++ b/ets2panda/test/runtime/ets/constructor_super_under_ifstmt.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +class ColoredPoint { + color: number; + constructor(color: number) { + this.color = color + } +} + +class BWPoint extends ColoredPoint { + constructor(black: boolean) { + if (black) { + super(0) + } else { + super(1) + } + } +} + +function main() { + arktest.assertEQ(new BWPoint(false).color, 1) +} -- Gitee