13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "aliveAnalyzer.h"
173af6ab5fSopenharmony_ci#include <cstddef>
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "checker/types/ets/etsAsyncFuncReturnType.h"
203af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
213af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
223af6ab5fSopenharmony_ci#include "ir/base/methodDefinition.h"
233af6ab5fSopenharmony_ci#include "ir/base/scriptFunction.h"
243af6ab5fSopenharmony_ci#include "ir/statements/classDeclaration.h"
253af6ab5fSopenharmony_ci#include "ir/statements/variableDeclaration.h"
263af6ab5fSopenharmony_ci#include "ir/statements/doWhileStatement.h"
273af6ab5fSopenharmony_ci#include "ir/statements/expressionStatement.h"
283af6ab5fSopenharmony_ci#include "ir/statements/whileStatement.h"
293af6ab5fSopenharmony_ci#include "ir/statements/forUpdateStatement.h"
303af6ab5fSopenharmony_ci#include "ir/statements/labelledStatement.h"
313af6ab5fSopenharmony_ci#include "ir/statements/forOfStatement.h"
323af6ab5fSopenharmony_ci#include "ir/statements/blockStatement.h"
333af6ab5fSopenharmony_ci#include "ir/statements/ifStatement.h"
343af6ab5fSopenharmony_ci#include "ir/statements/switchStatement.h"
353af6ab5fSopenharmony_ci#include "ir/statements/variableDeclarator.h"
363af6ab5fSopenharmony_ci#include "ir/statements/throwStatement.h"
373af6ab5fSopenharmony_ci#include "ir/statements/switchCaseStatement.h"
383af6ab5fSopenharmony_ci#include "ir/statements/breakStatement.h"
393af6ab5fSopenharmony_ci#include "ir/statements/continueStatement.h"
403af6ab5fSopenharmony_ci#include "ir/statements/returnStatement.h"
413af6ab5fSopenharmony_ci#include "ir/statements/tryStatement.h"
423af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
433af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
443af6ab5fSopenharmony_ci#include "ir/ets/etsNewClassInstanceExpression.h"
453af6ab5fSopenharmony_ci#include "ir/ets/etsStructDeclaration.h"
463af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceDeclaration.h"
473af6ab5fSopenharmony_ci#include "checker/types/globalTypesHolder.h"
483af6ab5fSopenharmony_ci#include "varbinder/variable.h"
493af6ab5fSopenharmony_ci#include "varbinder/declaration.h"
503af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
513af6ab5fSopenharmony_ci#include "ir/base/catchClause.h"
523af6ab5fSopenharmony_ci
533af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
543af6ab5fSopenharmony_ci
553af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeNodes(const ir::AstNode *node)
563af6ab5fSopenharmony_ci{
573af6ab5fSopenharmony_ci    node->Iterate([this](auto *childNode) { AnalyzeNode(childNode); });
583af6ab5fSopenharmony_ci}
593af6ab5fSopenharmony_ci
603af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeNode(const ir::AstNode *node)
613af6ab5fSopenharmony_ci{
623af6ab5fSopenharmony_ci    if (node == nullptr) {
633af6ab5fSopenharmony_ci        return;
643af6ab5fSopenharmony_ci    }
653af6ab5fSopenharmony_ci
663af6ab5fSopenharmony_ci    switch (node->Type()) {
673af6ab5fSopenharmony_ci        case ir::AstNodeType::EXPRESSION_STATEMENT: {
683af6ab5fSopenharmony_ci            AnalyzeNode(node->AsExpressionStatement()->GetExpression());
693af6ab5fSopenharmony_ci            break;
703af6ab5fSopenharmony_ci        }
713af6ab5fSopenharmony_ci        case ir::AstNodeType::STRUCT_DECLARATION: {
723af6ab5fSopenharmony_ci            AnalyzeStructDecl(node->AsETSStructDeclaration());
733af6ab5fSopenharmony_ci            break;
743af6ab5fSopenharmony_ci        }
753af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_DECLARATION: {
763af6ab5fSopenharmony_ci            AnalyzeClassDecl(node->AsClassDeclaration());
773af6ab5fSopenharmony_ci            break;
783af6ab5fSopenharmony_ci        }
793af6ab5fSopenharmony_ci        case ir::AstNodeType::METHOD_DEFINITION: {
803af6ab5fSopenharmony_ci            AnalyzeMethodDef(node->AsMethodDefinition());
813af6ab5fSopenharmony_ci            break;
823af6ab5fSopenharmony_ci        }
833af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATION: {
843af6ab5fSopenharmony_ci            AnalyzeVarDef(node->AsVariableDeclaration());
853af6ab5fSopenharmony_ci            break;
863af6ab5fSopenharmony_ci        }
873af6ab5fSopenharmony_ci        case ir::AstNodeType::BLOCK_STATEMENT: {
883af6ab5fSopenharmony_ci            AnalyzeStats(node->AsBlockStatement()->Statements());
893af6ab5fSopenharmony_ci            break;
903af6ab5fSopenharmony_ci        }
913af6ab5fSopenharmony_ci        case ir::AstNodeType::DO_WHILE_STATEMENT: {
923af6ab5fSopenharmony_ci            AnalyzeDoLoop(node->AsDoWhileStatement());
933af6ab5fSopenharmony_ci            break;
943af6ab5fSopenharmony_ci        }
953af6ab5fSopenharmony_ci        default: {
963af6ab5fSopenharmony_ci            break;
973af6ab5fSopenharmony_ci        }
983af6ab5fSopenharmony_ci    }
993af6ab5fSopenharmony_ci
1003af6ab5fSopenharmony_ci    // Helpers to reduce function size and pass code checker
1013af6ab5fSopenharmony_ci    AnalyzeNodeHelper1(node);
1023af6ab5fSopenharmony_ci    AnalyzeNodeHelper2(node);
1033af6ab5fSopenharmony_ci}
1043af6ab5fSopenharmony_ci
1053af6ab5fSopenharmony_ci// Helper function to reduce AnalyzeNode size and pass code checker
1063af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeNodeHelper1(const ir::AstNode *node)
1073af6ab5fSopenharmony_ci{
1083af6ab5fSopenharmony_ci    switch (node->Type()) {
1093af6ab5fSopenharmony_ci        case ir::AstNodeType::WHILE_STATEMENT: {
1103af6ab5fSopenharmony_ci            AnalyzeWhileLoop(node->AsWhileStatement());
1113af6ab5fSopenharmony_ci            break;
1123af6ab5fSopenharmony_ci        }
1133af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
1143af6ab5fSopenharmony_ci            AnalyzeForLoop(node->AsForUpdateStatement());
1153af6ab5fSopenharmony_ci            break;
1163af6ab5fSopenharmony_ci        }
1173af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_OF_STATEMENT: {
1183af6ab5fSopenharmony_ci            AnalyzeForOfLoop(node->AsForOfStatement());
1193af6ab5fSopenharmony_ci            break;
1203af6ab5fSopenharmony_ci        }
1213af6ab5fSopenharmony_ci        case ir::AstNodeType::IF_STATEMENT: {
1223af6ab5fSopenharmony_ci            AnalyzeIf(node->AsIfStatement());
1233af6ab5fSopenharmony_ci            break;
1243af6ab5fSopenharmony_ci        }
1253af6ab5fSopenharmony_ci        case ir::AstNodeType::LABELLED_STATEMENT: {
1263af6ab5fSopenharmony_ci            AnalyzeLabelled(node->AsLabelledStatement());
1273af6ab5fSopenharmony_ci            break;
1283af6ab5fSopenharmony_ci        }
1293af6ab5fSopenharmony_ci        case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: {
1303af6ab5fSopenharmony_ci            AnalyzeNewClass(node->AsETSNewClassInstanceExpression());
1313af6ab5fSopenharmony_ci            break;
1323af6ab5fSopenharmony_ci        }
1333af6ab5fSopenharmony_ci        case ir::AstNodeType::CALL_EXPRESSION: {
1343af6ab5fSopenharmony_ci            AnalyzeCall(node->AsCallExpression());
1353af6ab5fSopenharmony_ci            break;
1363af6ab5fSopenharmony_ci        }
1373af6ab5fSopenharmony_ci        case ir::AstNodeType::THROW_STATEMENT: {
1383af6ab5fSopenharmony_ci            AnalyzeThrow(node->AsThrowStatement());
1393af6ab5fSopenharmony_ci            break;
1403af6ab5fSopenharmony_ci        }
1413af6ab5fSopenharmony_ci        case ir::AstNodeType::SWITCH_STATEMENT: {
1423af6ab5fSopenharmony_ci            AnalyzeSwitch(node->AsSwitchStatement());
1433af6ab5fSopenharmony_ci            break;
1443af6ab5fSopenharmony_ci        }
1453af6ab5fSopenharmony_ci        default: {
1463af6ab5fSopenharmony_ci            break;
1473af6ab5fSopenharmony_ci        }
1483af6ab5fSopenharmony_ci    }
1493af6ab5fSopenharmony_ci}
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_ci// Helper function to reduce AnalyzeNode size and pass code checker
1523af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeNodeHelper2(const ir::AstNode *node)
1533af6ab5fSopenharmony_ci{
1543af6ab5fSopenharmony_ci    switch (node->Type()) {
1553af6ab5fSopenharmony_ci        case ir::AstNodeType::TRY_STATEMENT: {
1563af6ab5fSopenharmony_ci            AnalyzeTry(node->AsTryStatement());
1573af6ab5fSopenharmony_ci            break;
1583af6ab5fSopenharmony_ci        }
1593af6ab5fSopenharmony_ci        case ir::AstNodeType::BREAK_STATEMENT: {
1603af6ab5fSopenharmony_ci            AnalyzeBreak(node->AsBreakStatement());
1613af6ab5fSopenharmony_ci            break;
1623af6ab5fSopenharmony_ci        }
1633af6ab5fSopenharmony_ci        case ir::AstNodeType::CONTINUE_STATEMENT: {
1643af6ab5fSopenharmony_ci            AnalyzeContinue(node->AsContinueStatement());
1653af6ab5fSopenharmony_ci            break;
1663af6ab5fSopenharmony_ci        }
1673af6ab5fSopenharmony_ci        case ir::AstNodeType::RETURN_STATEMENT: {
1683af6ab5fSopenharmony_ci            AnalyzeReturn(node->AsReturnStatement());
1693af6ab5fSopenharmony_ci            break;
1703af6ab5fSopenharmony_ci        }
1713af6ab5fSopenharmony_ci        default: {
1723af6ab5fSopenharmony_ci            break;
1733af6ab5fSopenharmony_ci        }
1743af6ab5fSopenharmony_ci    }
1753af6ab5fSopenharmony_ci}
1763af6ab5fSopenharmony_ci
1773af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeDef(const ir::AstNode *node)
1783af6ab5fSopenharmony_ci{
1793af6ab5fSopenharmony_ci    AnalyzeStat(node);
1803af6ab5fSopenharmony_ci    if (node != nullptr && node->IsClassStaticBlock() && status_ == LivenessStatus::DEAD) {
1813af6ab5fSopenharmony_ci        checker_->LogTypeError("Initializer must be able to complete normally.", node->Start());
1823af6ab5fSopenharmony_ci    }
1833af6ab5fSopenharmony_ci}
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeStat(const ir::AstNode *node)
1863af6ab5fSopenharmony_ci{
1873af6ab5fSopenharmony_ci    if (node == nullptr) {
1883af6ab5fSopenharmony_ci        return;
1893af6ab5fSopenharmony_ci    }
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci    if (status_ == LivenessStatus::DEAD) {
1923af6ab5fSopenharmony_ci        checker_->LogTypeError("Unreachable statement.", node->Start());
1933af6ab5fSopenharmony_ci        return;
1943af6ab5fSopenharmony_ci    }
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci    if (node->IsClassStaticBlock()) {
1973af6ab5fSopenharmony_ci        AnalyzeNodes(node);
1983af6ab5fSopenharmony_ci        return;
1993af6ab5fSopenharmony_ci    }
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_ci    AnalyzeNode(node);
2023af6ab5fSopenharmony_ci}
2033af6ab5fSopenharmony_ci
2043af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeStats(const ArenaVector<ir::Statement *> &stats)
2053af6ab5fSopenharmony_ci{
2063af6ab5fSopenharmony_ci    for (const auto *it : stats) {
2073af6ab5fSopenharmony_ci        AnalyzeStat(it);
2083af6ab5fSopenharmony_ci    }
2093af6ab5fSopenharmony_ci}
2103af6ab5fSopenharmony_ci
2113af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl)
2123af6ab5fSopenharmony_ci{
2133af6ab5fSopenharmony_ci    for (const auto *it : structDecl->Definition()->Body()) {
2143af6ab5fSopenharmony_ci        AnalyzeNode(it);
2153af6ab5fSopenharmony_ci    }
2163af6ab5fSopenharmony_ci}
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeClassDecl(const ir::ClassDeclaration *classDecl)
2193af6ab5fSopenharmony_ci{
2203af6ab5fSopenharmony_ci    LivenessStatus prevStatus = status_;
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_ci    for (const auto *it : classDecl->Definition()->Body()) {
2233af6ab5fSopenharmony_ci        AnalyzeNode(it);
2243af6ab5fSopenharmony_ci    }
2253af6ab5fSopenharmony_ci
2263af6ab5fSopenharmony_ci    status_ = prevStatus;
2273af6ab5fSopenharmony_ci}
2283af6ab5fSopenharmony_ci
2293af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeMethodDef(const ir::MethodDefinition *methodDef)
2303af6ab5fSopenharmony_ci{
2313af6ab5fSopenharmony_ci    auto *func = methodDef->Function();
2323af6ab5fSopenharmony_ci
2333af6ab5fSopenharmony_ci    if (func->Body() == nullptr || func->IsProxy()) {
2343af6ab5fSopenharmony_ci        return;
2353af6ab5fSopenharmony_ci    }
2363af6ab5fSopenharmony_ci
2373af6ab5fSopenharmony_ci    status_ = LivenessStatus::ALIVE;
2383af6ab5fSopenharmony_ci    AnalyzeStat(func->Body());
2393af6ab5fSopenharmony_ci    ASSERT(methodDef->TsType() && methodDef->TsType()->IsETSFunctionType());
2403af6ab5fSopenharmony_ci    const auto *returnType = methodDef->TsType()->AsETSFunctionType()->FindSignature(func)->ReturnType();
2413af6ab5fSopenharmony_ci    const auto isVoid = returnType->IsETSVoidType() || returnType == checker_->GlobalVoidType();
2423af6ab5fSopenharmony_ci
2433af6ab5fSopenharmony_ci    auto isPromiseVoid = false;
2443af6ab5fSopenharmony_ci
2453af6ab5fSopenharmony_ci    if (returnType->IsETSAsyncFuncReturnType()) {
2463af6ab5fSopenharmony_ci        const auto *asAsync = returnType->AsETSAsyncFuncReturnType();
2473af6ab5fSopenharmony_ci        isPromiseVoid = asAsync->GetPromiseTypeArg() == checker_->GlobalETSUndefinedType();
2483af6ab5fSopenharmony_ci    }
2493af6ab5fSopenharmony_ci
2503af6ab5fSopenharmony_ci    if (status_ == LivenessStatus::ALIVE && !isVoid && !isPromiseVoid && !checker_->IsAsyncImplMethod(methodDef)) {
2513af6ab5fSopenharmony_ci        if (!methodDef->Function()->HasReturnStatement()) {
2523af6ab5fSopenharmony_ci            checker_->LogTypeError("Function with a non void return type must return a value.", func->Id()->Start());
2533af6ab5fSopenharmony_ci            ClearPendingExits();
2543af6ab5fSopenharmony_ci            return;
2553af6ab5fSopenharmony_ci        }
2563af6ab5fSopenharmony_ci
2573af6ab5fSopenharmony_ci        checker_->LogTypeError("Not all code paths return a value.", func->Id()->Start());
2583af6ab5fSopenharmony_ci    }
2593af6ab5fSopenharmony_ci
2603af6ab5fSopenharmony_ci    ClearPendingExits();
2613af6ab5fSopenharmony_ci}
2623af6ab5fSopenharmony_ci
2633af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeVarDef(const ir::VariableDeclaration *varDef)
2643af6ab5fSopenharmony_ci{
2653af6ab5fSopenharmony_ci    for (auto *it : varDef->Declarators()) {
2663af6ab5fSopenharmony_ci        if (it->Init() == nullptr) {
2673af6ab5fSopenharmony_ci            continue;
2683af6ab5fSopenharmony_ci        }
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci        AnalyzeNode(it->Init());
2713af6ab5fSopenharmony_ci    }
2723af6ab5fSopenharmony_ci}
2733af6ab5fSopenharmony_ci
2743af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeDoLoop(const ir::DoWhileStatement *doWhile)
2753af6ab5fSopenharmony_ci{
2763af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
2773af6ab5fSopenharmony_ci    AnalyzeStat(doWhile->Body());
2783af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveContinues(doWhile));
2793af6ab5fSopenharmony_ci    AnalyzeNode(doWhile->Test());
2803af6ab5fSopenharmony_ci    ASSERT(doWhile->Test()->TsType() && doWhile->Test()->TsType()->IsConditionalExprType());
2813af6ab5fSopenharmony_ci    const auto exprRes = doWhile->Test()->TsType()->ResolveConditionExpr();
2823af6ab5fSopenharmony_ci    status_ = And(status_, static_cast<LivenessStatus>(!std::get<0>(exprRes) || !std::get<1>(exprRes)));
2833af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveBreaks(doWhile));
2843af6ab5fSopenharmony_ci}
2853af6ab5fSopenharmony_ci
2863af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeWhileLoop(const ir::WhileStatement *whileStmt)
2873af6ab5fSopenharmony_ci{
2883af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
2893af6ab5fSopenharmony_ci    AnalyzeNode(whileStmt->Test());
2903af6ab5fSopenharmony_ci    ASSERT(whileStmt->Test()->TsType() && whileStmt->Test()->TsType()->IsConditionalExprType());
2913af6ab5fSopenharmony_ci    const auto exprRes = whileStmt->Test()->TsType()->ResolveConditionExpr();
2923af6ab5fSopenharmony_ci    status_ = And(status_, static_cast<LivenessStatus>(!std::get<0>(exprRes) || std::get<1>(exprRes)));
2933af6ab5fSopenharmony_ci    AnalyzeStat(whileStmt->Body());
2943af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveContinues(whileStmt));
2953af6ab5fSopenharmony_ci    status_ = Or(ResolveBreaks(whileStmt), From(!std::get<0>(exprRes) || !std::get<1>(exprRes)));
2963af6ab5fSopenharmony_ci}
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeForLoop(const ir::ForUpdateStatement *forStmt)
2993af6ab5fSopenharmony_ci{
3003af6ab5fSopenharmony_ci    AnalyzeNode(forStmt->Init());
3013af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
3023af6ab5fSopenharmony_ci    const Type *condType {};
3033af6ab5fSopenharmony_ci    bool resolveType = false;
3043af6ab5fSopenharmony_ci    bool res = false;
3053af6ab5fSopenharmony_ci
3063af6ab5fSopenharmony_ci    if (forStmt->Test() != nullptr) {
3073af6ab5fSopenharmony_ci        AnalyzeNode(forStmt->Test());
3083af6ab5fSopenharmony_ci        ASSERT(forStmt->Test()->TsType() && forStmt->Test()->TsType()->IsConditionalExprType());
3093af6ab5fSopenharmony_ci        condType = forStmt->Test()->TsType();
3103af6ab5fSopenharmony_ci        std::tie(resolveType, res) = forStmt->Test()->TsType()->ResolveConditionExpr();
3113af6ab5fSopenharmony_ci        status_ = From(!resolveType || res);
3123af6ab5fSopenharmony_ci    } else {
3133af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
3143af6ab5fSopenharmony_ci    }
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci    AnalyzeStat(forStmt->Body());
3173af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveContinues(forStmt));
3183af6ab5fSopenharmony_ci    AnalyzeNode(forStmt->Update());
3193af6ab5fSopenharmony_ci    status_ = Or(ResolveBreaks(forStmt), From(condType != nullptr && (!resolveType || !res)));
3203af6ab5fSopenharmony_ci}
3213af6ab5fSopenharmony_ci
3223af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt)
3233af6ab5fSopenharmony_ci{
3243af6ab5fSopenharmony_ci    //  Note: iterator definition can be a reference to variable defined in outer scope!
3253af6ab5fSopenharmony_ci    if (forOfStmt->Left()->IsVariableDeclaration()) {
3263af6ab5fSopenharmony_ci        AnalyzeVarDef(forOfStmt->Left()->AsVariableDeclaration());
3273af6ab5fSopenharmony_ci    } else {
3283af6ab5fSopenharmony_ci        AnalyzeNode(forOfStmt->Left());
3293af6ab5fSopenharmony_ci    }
3303af6ab5fSopenharmony_ci    AnalyzeNode(forOfStmt->Right());
3313af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
3323af6ab5fSopenharmony_ci
3333af6ab5fSopenharmony_ci    AnalyzeStat(forOfStmt->Body());
3343af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveContinues(forOfStmt));
3353af6ab5fSopenharmony_ci    ResolveBreaks(forOfStmt);
3363af6ab5fSopenharmony_ci    status_ = LivenessStatus::ALIVE;
3373af6ab5fSopenharmony_ci}
3383af6ab5fSopenharmony_ci
3393af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeIf(const ir::IfStatement *ifStmt)
3403af6ab5fSopenharmony_ci{
3413af6ab5fSopenharmony_ci    AnalyzeNode(ifStmt->Test());
3423af6ab5fSopenharmony_ci    AnalyzeStat(ifStmt->Consequent());
3433af6ab5fSopenharmony_ci    if (ifStmt->Alternate() != nullptr) {
3443af6ab5fSopenharmony_ci        LivenessStatus prevStatus = status_;
3453af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
3463af6ab5fSopenharmony_ci        AnalyzeStat(ifStmt->Alternate());
3473af6ab5fSopenharmony_ci        status_ = Or(status_, prevStatus);
3483af6ab5fSopenharmony_ci    } else {
3493af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
3503af6ab5fSopenharmony_ci    }
3513af6ab5fSopenharmony_ci}
3523af6ab5fSopenharmony_ci
3533af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeLabelled(const ir::LabelledStatement *labelledStmt)
3543af6ab5fSopenharmony_ci{
3553af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
3563af6ab5fSopenharmony_ci    AnalyzeStat(labelledStmt->Body());
3573af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveBreaks(labelledStmt));
3583af6ab5fSopenharmony_ci}
3593af6ab5fSopenharmony_ci
3603af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass)
3613af6ab5fSopenharmony_ci{
3623af6ab5fSopenharmony_ci    for (const auto *it : newClass->GetArguments()) {
3633af6ab5fSopenharmony_ci        AnalyzeNode(it);
3643af6ab5fSopenharmony_ci    }
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_ci    if (newClass->ClassDefinition() != nullptr) {
3673af6ab5fSopenharmony_ci        AnalyzeNode(newClass->ClassDefinition());
3683af6ab5fSopenharmony_ci    }
3693af6ab5fSopenharmony_ci}
3703af6ab5fSopenharmony_ci
3713af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeCall(const ir::CallExpression *callExpr)
3723af6ab5fSopenharmony_ci{
3733af6ab5fSopenharmony_ci    AnalyzeNode(callExpr->Callee());
3743af6ab5fSopenharmony_ci    for (const auto *it : callExpr->Arguments()) {
3753af6ab5fSopenharmony_ci        AnalyzeNode(it);
3763af6ab5fSopenharmony_ci    }
3773af6ab5fSopenharmony_ci    if (callExpr->Signature()->ReturnType() == checker_->GetGlobalTypesHolder()->GlobalBuiltinNeverType()) {
3783af6ab5fSopenharmony_ci        MarkDead();
3793af6ab5fSopenharmony_ci    }
3803af6ab5fSopenharmony_ci}
3813af6ab5fSopenharmony_ci
3823af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeThrow(const ir::ThrowStatement *throwStmt)
3833af6ab5fSopenharmony_ci{
3843af6ab5fSopenharmony_ci    AnalyzeNode(throwStmt->Argument());
3853af6ab5fSopenharmony_ci    MarkDead();
3863af6ab5fSopenharmony_ci}
3873af6ab5fSopenharmony_ci
3883af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeSwitch(const ir::SwitchStatement *switchStmt)
3893af6ab5fSopenharmony_ci{
3903af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
3913af6ab5fSopenharmony_ci
3923af6ab5fSopenharmony_ci    AnalyzeNode(switchStmt->Discriminant());
3933af6ab5fSopenharmony_ci
3943af6ab5fSopenharmony_ci    bool hasDefault = false;
3953af6ab5fSopenharmony_ci    for (std::size_t i = 0, size = switchStmt->Cases().size(); i < size; i++) {
3963af6ab5fSopenharmony_ci        const auto *caseClause = switchStmt->Cases()[i];
3973af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_ci        if (caseClause->Test() == nullptr) {
4003af6ab5fSopenharmony_ci            hasDefault = true;
4013af6ab5fSopenharmony_ci        } else {
4023af6ab5fSopenharmony_ci            AnalyzeNode(caseClause->Test());
4033af6ab5fSopenharmony_ci        }
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci        AnalyzeStats(caseClause->Consequent());
4063af6ab5fSopenharmony_ci
4073af6ab5fSopenharmony_ci        if (status_ == LivenessStatus::ALIVE && !caseClause->Consequent().empty() && i < size - 1) {
4083af6ab5fSopenharmony_ci            // NOTE(user) Add lint categories and option to enable/disable compiler warnings
4093af6ab5fSopenharmony_ci            checker_->Warning("Possible fall-through into case", caseClause->Start());
4103af6ab5fSopenharmony_ci        }
4113af6ab5fSopenharmony_ci    }
4123af6ab5fSopenharmony_ci
4133af6ab5fSopenharmony_ci    if (!hasDefault) {
4143af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
4153af6ab5fSopenharmony_ci    }
4163af6ab5fSopenharmony_ci
4173af6ab5fSopenharmony_ci    status_ = Or(status_, ResolveBreaks(switchStmt));
4183af6ab5fSopenharmony_ci}
4193af6ab5fSopenharmony_ci
4203af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeBreak(const ir::BreakStatement *breakStmt)
4213af6ab5fSopenharmony_ci{
4223af6ab5fSopenharmony_ci    RecordExit(PendingExit(breakStmt));
4233af6ab5fSopenharmony_ci}
4243af6ab5fSopenharmony_ci
4253af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeContinue(const ir::ContinueStatement *contStmt)
4263af6ab5fSopenharmony_ci{
4273af6ab5fSopenharmony_ci    RecordExit(PendingExit(contStmt));
4283af6ab5fSopenharmony_ci}
4293af6ab5fSopenharmony_ci
4303af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeReturn(const ir::ReturnStatement *retStmt)
4313af6ab5fSopenharmony_ci{
4323af6ab5fSopenharmony_ci    AnalyzeNode(retStmt->Argument());
4333af6ab5fSopenharmony_ci    RecordExit(PendingExit(retStmt));
4343af6ab5fSopenharmony_ci}
4353af6ab5fSopenharmony_ci
4363af6ab5fSopenharmony_civoid AliveAnalyzer::AnalyzeTry(const ir::TryStatement *tryStmt)
4373af6ab5fSopenharmony_ci{
4383af6ab5fSopenharmony_ci    status_ = LivenessStatus::ALIVE;
4393af6ab5fSopenharmony_ci    bool isAlive = false;
4403af6ab5fSopenharmony_ci    AnalyzeStats(tryStmt->Block()->Statements());
4413af6ab5fSopenharmony_ci
4423af6ab5fSopenharmony_ci    if (status_ != LivenessStatus::DEAD) {
4433af6ab5fSopenharmony_ci        isAlive = true;
4443af6ab5fSopenharmony_ci    }
4453af6ab5fSopenharmony_ci
4463af6ab5fSopenharmony_ci    for (const auto &it : tryStmt->CatchClauses()) {
4473af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
4483af6ab5fSopenharmony_ci        AnalyzeStats(it->Body()->Statements());
4493af6ab5fSopenharmony_ci        if (status_ == LivenessStatus::ALIVE) {
4503af6ab5fSopenharmony_ci            isAlive = true;
4513af6ab5fSopenharmony_ci        }
4523af6ab5fSopenharmony_ci    }
4533af6ab5fSopenharmony_ci
4543af6ab5fSopenharmony_ci    if (tryStmt->FinallyBlock() != nullptr) {
4553af6ab5fSopenharmony_ci        status_ = LivenessStatus::ALIVE;
4563af6ab5fSopenharmony_ci        AnalyzeStats(tryStmt->FinallyBlock()->Statements());
4573af6ab5fSopenharmony_ci        const_cast<ir::TryStatement *>(tryStmt)->SetFinallyCanCompleteNormally(status_ == LivenessStatus::ALIVE);
4583af6ab5fSopenharmony_ci        if (status_ == LivenessStatus::DEAD) {
4593af6ab5fSopenharmony_ci            isAlive = false;
4603af6ab5fSopenharmony_ci            // NOTE(user) Add lint categories and option to enable/disable compiler warnings
4613af6ab5fSopenharmony_ci            checker_->Warning("Finally clause cannot complete normally", tryStmt->FinallyBlock()->Start());
4623af6ab5fSopenharmony_ci        }
4633af6ab5fSopenharmony_ci    }
4643af6ab5fSopenharmony_ci
4653af6ab5fSopenharmony_ci    status_ = isAlive ? LivenessStatus::ALIVE : LivenessStatus::DEAD;
4663af6ab5fSopenharmony_ci}
4673af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
468