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 "assignAnalyzer.h"
173af6ab5fSopenharmony_ci#include <cstddef>
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "ir/base/classDefinition.h"
203af6ab5fSopenharmony_ci#include "ir/base/classProperty.h"
213af6ab5fSopenharmony_ci#include "ir/base/classStaticBlock.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/statements/assertStatement.h"
433af6ab5fSopenharmony_ci#include "ir/expressions/callExpression.h"
443af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
453af6ab5fSopenharmony_ci#include "ir/expressions/arrowFunctionExpression.h"
463af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
473af6ab5fSopenharmony_ci#include "ir/expressions/binaryExpression.h"
483af6ab5fSopenharmony_ci#include "ir/expressions/conditionalExpression.h"
493af6ab5fSopenharmony_ci#include "ir/expressions/memberExpression.h"
503af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h"
513af6ab5fSopenharmony_ci#include "ir/expressions/unaryExpression.h"
523af6ab5fSopenharmony_ci#include "ir/expressions/updateExpression.h"
533af6ab5fSopenharmony_ci#include "ir/expressions/typeofExpression.h"
543af6ab5fSopenharmony_ci#include "ir/ets/etsNewClassInstanceExpression.h"
553af6ab5fSopenharmony_ci#include "ir/ets/etsStructDeclaration.h"
563af6ab5fSopenharmony_ci#include "ir/ts/tsInterfaceDeclaration.h"
573af6ab5fSopenharmony_ci#include "varbinder/ETSBinder.h"
583af6ab5fSopenharmony_ci#include "varbinder/variable.h"
593af6ab5fSopenharmony_ci#include "varbinder/scope.h"
603af6ab5fSopenharmony_ci#include "varbinder/declaration.h"
613af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
623af6ab5fSopenharmony_ci#include "ir/base/catchClause.h"
633af6ab5fSopenharmony_ci#include "parser/program/program.h"
643af6ab5fSopenharmony_ci#include "checker/types/ts/objectType.h"
653af6ab5fSopenharmony_ci
663af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
673af6ab5fSopenharmony_ci
683af6ab5fSopenharmony_cistatic constexpr NodeId INVALID_ID = -1;
693af6ab5fSopenharmony_cistatic constexpr bool CHECK_ALL_PROPERTIES = true;
703af6ab5fSopenharmony_ci// NOTE(pantos) generic field initialization issue, skip them for now
713af6ab5fSopenharmony_cistatic constexpr bool CHECK_GENERIC_NON_READONLY_PROPERTIES = false;
723af6ab5fSopenharmony_cistatic constexpr bool WARN_NO_INIT_ONCE_PER_VARIABLE = false;
733af6ab5fSopenharmony_cistatic constexpr int LOOP_PHASES = 2;
743af6ab5fSopenharmony_ci
753af6ab5fSopenharmony_citemplate <typename... Ts>
763af6ab5fSopenharmony_cistruct ScopeGuard {
773af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
783af6ab5fSopenharmony_ci    std::tuple<Ts...> values;
793af6ab5fSopenharmony_ci    std::tuple<Ts &...> refs;
803af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes)
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_ci    explicit ScopeGuard(Ts &...ts) : values(ts...), refs(ts...) {}
833af6ab5fSopenharmony_ci    ~ScopeGuard()
843af6ab5fSopenharmony_ci    {
853af6ab5fSopenharmony_ci        refs = values;
863af6ab5fSopenharmony_ci    }
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    DEFAULT_COPY_SEMANTIC(ScopeGuard);
893af6ab5fSopenharmony_ci    DEFAULT_MOVE_SEMANTIC(ScopeGuard);
903af6ab5fSopenharmony_ci};
913af6ab5fSopenharmony_ci
923af6ab5fSopenharmony_cistatic std::string Capitalize(const util::StringView &str)
933af6ab5fSopenharmony_ci{
943af6ab5fSopenharmony_ci    if (str.Empty()) {
953af6ab5fSopenharmony_ci        return "";
963af6ab5fSopenharmony_ci    }
973af6ab5fSopenharmony_ci    std::string ret(str.Utf8());
983af6ab5fSopenharmony_ci    ret[0] = std::toupper(ret[0]);
993af6ab5fSopenharmony_ci    return ret;
1003af6ab5fSopenharmony_ci}
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_civoid Set::Reset()
1033af6ab5fSopenharmony_ci{
1043af6ab5fSopenharmony_ci    reset_ = true;
1053af6ab5fSopenharmony_ci}
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_cibool Set::IsReset()
1083af6ab5fSopenharmony_ci{
1093af6ab5fSopenharmony_ci    return reset_;
1103af6ab5fSopenharmony_ci}
1113af6ab5fSopenharmony_ci
1123af6ab5fSopenharmony_civoid Set::Incl(const int id)
1133af6ab5fSopenharmony_ci{
1143af6ab5fSopenharmony_ci    nodes_.insert(id);
1153af6ab5fSopenharmony_ci}
1163af6ab5fSopenharmony_ci
1173af6ab5fSopenharmony_civoid Set::InclRange(const int start, const int limit)
1183af6ab5fSopenharmony_ci{
1193af6ab5fSopenharmony_ci    for (int x = start; x < limit; x++) {
1203af6ab5fSopenharmony_ci        nodes_.insert(x);
1213af6ab5fSopenharmony_ci    }
1223af6ab5fSopenharmony_ci}
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_civoid Set::Excl(const int id)
1253af6ab5fSopenharmony_ci{
1263af6ab5fSopenharmony_ci    nodes_.erase(id);
1273af6ab5fSopenharmony_ci}
1283af6ab5fSopenharmony_ci
1293af6ab5fSopenharmony_civoid Set::ExcludeFrom(const int start)
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    auto it = nodes_.lower_bound(start);
1323af6ab5fSopenharmony_ci    nodes_.erase(nodes_.begin(), it);
1333af6ab5fSopenharmony_ci}
1343af6ab5fSopenharmony_ci
1353af6ab5fSopenharmony_cibool Set::IsMember(const int id) const
1363af6ab5fSopenharmony_ci{
1373af6ab5fSopenharmony_ci    return nodes_.find(id) != nodes_.end();
1383af6ab5fSopenharmony_ci}
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ciSet &Set::AndSet(const Set &xs)
1413af6ab5fSopenharmony_ci{
1423af6ab5fSopenharmony_ci    std::set<int> res;
1433af6ab5fSopenharmony_ci    std::set_intersection(nodes_.begin(), nodes_.end(), xs.nodes_.begin(), xs.nodes_.end(),
1443af6ab5fSopenharmony_ci                          std::inserter(res, res.begin()));
1453af6ab5fSopenharmony_ci    nodes_ = res;
1463af6ab5fSopenharmony_ci    return *this;
1473af6ab5fSopenharmony_ci}
1483af6ab5fSopenharmony_ci
1493af6ab5fSopenharmony_ciSet &Set::OrSet(const Set &xs)
1503af6ab5fSopenharmony_ci{
1513af6ab5fSopenharmony_ci    std::set<int> res;
1523af6ab5fSopenharmony_ci    std::set_union(nodes_.begin(), nodes_.end(), xs.nodes_.begin(), xs.nodes_.end(), std::inserter(res, res.begin()));
1533af6ab5fSopenharmony_ci    nodes_ = res;
1543af6ab5fSopenharmony_ci    return *this;
1553af6ab5fSopenharmony_ci}
1563af6ab5fSopenharmony_ci
1573af6ab5fSopenharmony_ciSet &Set::DiffSet(const Set &xs)
1583af6ab5fSopenharmony_ci{
1593af6ab5fSopenharmony_ci    std::set<int> res;
1603af6ab5fSopenharmony_ci    std::set_difference(nodes_.begin(), nodes_.end(), xs.nodes_.begin(), xs.nodes_.end(),
1613af6ab5fSopenharmony_ci                        std::inserter(res, res.begin()));
1623af6ab5fSopenharmony_ci    nodes_ = res;
1633af6ab5fSopenharmony_ci    return *this;
1643af6ab5fSopenharmony_ci}
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ciint Set::Next(const int id)
1673af6ab5fSopenharmony_ci{
1683af6ab5fSopenharmony_ci    auto it = nodes_.upper_bound(id);
1693af6ab5fSopenharmony_ci    if (it != nodes_.end()) {
1703af6ab5fSopenharmony_ci        return *it;
1713af6ab5fSopenharmony_ci    }
1723af6ab5fSopenharmony_ci    return -1;
1733af6ab5fSopenharmony_ci}
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ciAssignAnalyzer::AssignAnalyzer(ETSChecker *checker)
1763af6ab5fSopenharmony_ci    : checker_(checker),
1773af6ab5fSopenharmony_ci      varDecls_(checker->Allocator()->Adapter()),
1783af6ab5fSopenharmony_ci      nodeIdMap_(checker->Allocator()->Adapter()),
1793af6ab5fSopenharmony_ci      foundErrors_(checker->Allocator()->Adapter())
1803af6ab5fSopenharmony_ci{
1813af6ab5fSopenharmony_ci}
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_civoid AssignAnalyzer::Analyze(const ir::AstNode *node)
1843af6ab5fSopenharmony_ci{
1853af6ab5fSopenharmony_ci    const auto program = checker_->VarBinder()->Program();
1863af6ab5fSopenharmony_ci    globalClass_ = program->GlobalClass();
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci    AnalyzeClassDef(globalClass_);
1893af6ab5fSopenharmony_ci    globalClassIsVisited_ = true;
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci    firstNonGlobalAdr_ = nextAdr_;
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_ci    AnalyzeNodes(node);
1943af6ab5fSopenharmony_ci
1953af6ab5fSopenharmony_ci    if (numErrors_ > 0) {
1963af6ab5fSopenharmony_ci        checker_->LogTypeError("There were errors during assign analysis (" + std::to_string(numErrors_) + ")",
1973af6ab5fSopenharmony_ci                               node->Start());
1983af6ab5fSopenharmony_ci    }
1993af6ab5fSopenharmony_ci}
2003af6ab5fSopenharmony_ci
2013af6ab5fSopenharmony_civoid AssignAnalyzer::Warning(const std::string_view message, const lexer::SourcePosition &pos)
2023af6ab5fSopenharmony_ci{
2033af6ab5fSopenharmony_ci    ++numErrors_;
2043af6ab5fSopenharmony_ci    checker_->Warning(message, pos);
2053af6ab5fSopenharmony_ci}
2063af6ab5fSopenharmony_ci
2073af6ab5fSopenharmony_civoid AssignAnalyzer::Warning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos)
2083af6ab5fSopenharmony_ci{
2093af6ab5fSopenharmony_ci    ++numErrors_;
2103af6ab5fSopenharmony_ci    checker_->ReportWarning(list, pos);
2113af6ab5fSopenharmony_ci}
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeNodes(const ir::AstNode *node)
2143af6ab5fSopenharmony_ci{
2153af6ab5fSopenharmony_ci    node->Iterate([this](auto *childNode) { AnalyzeNode(childNode); });
2163af6ab5fSopenharmony_ci}
2173af6ab5fSopenharmony_ci
2183af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeNode(const ir::AstNode *node)
2193af6ab5fSopenharmony_ci{
2203af6ab5fSopenharmony_ci    if (node == nullptr) {
2213af6ab5fSopenharmony_ci        return;
2223af6ab5fSopenharmony_ci    }
2233af6ab5fSopenharmony_ci
2243af6ab5fSopenharmony_ci    // NOTE(pantos) these are dummy methods to conform the CI's method size and complexity requirements
2253af6ab5fSopenharmony_ci    if (AnalyzeStmtNode1(node) || AnalyzeStmtNode2(node) || AnalyzeExprNode1(node) || AnalyzeExprNode2(node)) {
2263af6ab5fSopenharmony_ci        return;
2273af6ab5fSopenharmony_ci    }
2283af6ab5fSopenharmony_ci
2293af6ab5fSopenharmony_ci    switch (node->Type()) {
2303af6ab5fSopenharmony_ci        case ir::AstNodeType::STRUCT_DECLARATION: {
2313af6ab5fSopenharmony_ci            AnalyzeStructDecl(node->AsETSStructDeclaration());
2323af6ab5fSopenharmony_ci            break;
2333af6ab5fSopenharmony_ci        }
2343af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_DECLARATION: {
2353af6ab5fSopenharmony_ci            AnalyzeClassDecl(node->AsClassDeclaration());
2363af6ab5fSopenharmony_ci            break;
2373af6ab5fSopenharmony_ci        }
2383af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_DEFINITION: {
2393af6ab5fSopenharmony_ci            AnalyzeClassDef(node->AsClassDefinition());
2403af6ab5fSopenharmony_ci            break;
2413af6ab5fSopenharmony_ci        }
2423af6ab5fSopenharmony_ci        case ir::AstNodeType::METHOD_DEFINITION: {
2433af6ab5fSopenharmony_ci            AnalyzeMethodDef(node->AsMethodDefinition());
2443af6ab5fSopenharmony_ci            break;
2453af6ab5fSopenharmony_ci        }
2463af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATION: {
2473af6ab5fSopenharmony_ci            AnalyzeVarDef(node->AsVariableDeclaration());
2483af6ab5fSopenharmony_ci            break;
2493af6ab5fSopenharmony_ci        }
2503af6ab5fSopenharmony_ci        default: {
2513af6ab5fSopenharmony_ci            AnalyzeNodes(node);
2523af6ab5fSopenharmony_ci            if (node->IsExpression()) {
2533af6ab5fSopenharmony_ci                if (inits_.IsReset()) {
2543af6ab5fSopenharmony_ci                    Merge();
2553af6ab5fSopenharmony_ci                }
2563af6ab5fSopenharmony_ci            }
2573af6ab5fSopenharmony_ci            break;
2583af6ab5fSopenharmony_ci        }
2593af6ab5fSopenharmony_ci    }
2603af6ab5fSopenharmony_ci}
2613af6ab5fSopenharmony_ci
2623af6ab5fSopenharmony_cibool AssignAnalyzer::AnalyzeStmtNode1(const ir::AstNode *node)
2633af6ab5fSopenharmony_ci{
2643af6ab5fSopenharmony_ci    switch (node->Type()) {
2653af6ab5fSopenharmony_ci        case ir::AstNodeType::EXPRESSION_STATEMENT: {
2663af6ab5fSopenharmony_ci            AnalyzeNode(node->AsExpressionStatement()->GetExpression());
2673af6ab5fSopenharmony_ci            break;
2683af6ab5fSopenharmony_ci        }
2693af6ab5fSopenharmony_ci        case ir::AstNodeType::BLOCK_STATEMENT: {
2703af6ab5fSopenharmony_ci            AnalyzeBlock(node->AsBlockStatement());
2713af6ab5fSopenharmony_ci            break;
2723af6ab5fSopenharmony_ci        }
2733af6ab5fSopenharmony_ci        case ir::AstNodeType::DO_WHILE_STATEMENT: {
2743af6ab5fSopenharmony_ci            AnalyzeDoLoop(node->AsDoWhileStatement());
2753af6ab5fSopenharmony_ci            break;
2763af6ab5fSopenharmony_ci        }
2773af6ab5fSopenharmony_ci        case ir::AstNodeType::WHILE_STATEMENT: {
2783af6ab5fSopenharmony_ci            AnalyzeWhileLoop(node->AsWhileStatement());
2793af6ab5fSopenharmony_ci            break;
2803af6ab5fSopenharmony_ci        }
2813af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
2823af6ab5fSopenharmony_ci            AnalyzeForLoop(node->AsForUpdateStatement());
2833af6ab5fSopenharmony_ci            break;
2843af6ab5fSopenharmony_ci        }
2853af6ab5fSopenharmony_ci        case ir::AstNodeType::FOR_OF_STATEMENT: {
2863af6ab5fSopenharmony_ci            AnalyzeForOfLoop(node->AsForOfStatement());
2873af6ab5fSopenharmony_ci            break;
2883af6ab5fSopenharmony_ci        }
2893af6ab5fSopenharmony_ci        case ir::AstNodeType::IF_STATEMENT: {
2903af6ab5fSopenharmony_ci            AnalyzeIf(node->AsIfStatement());
2913af6ab5fSopenharmony_ci            break;
2923af6ab5fSopenharmony_ci        }
2933af6ab5fSopenharmony_ci        default:
2943af6ab5fSopenharmony_ci            return false;
2953af6ab5fSopenharmony_ci    }
2963af6ab5fSopenharmony_ci
2973af6ab5fSopenharmony_ci    return true;
2983af6ab5fSopenharmony_ci}
2993af6ab5fSopenharmony_ci
3003af6ab5fSopenharmony_cibool AssignAnalyzer::AnalyzeStmtNode2(const ir::AstNode *node)
3013af6ab5fSopenharmony_ci{
3023af6ab5fSopenharmony_ci    switch (node->Type()) {
3033af6ab5fSopenharmony_ci        case ir::AstNodeType::LABELLED_STATEMENT: {
3043af6ab5fSopenharmony_ci            AnalyzeLabelled(node->AsLabelledStatement());
3053af6ab5fSopenharmony_ci            break;
3063af6ab5fSopenharmony_ci        }
3073af6ab5fSopenharmony_ci        case ir::AstNodeType::SWITCH_STATEMENT: {
3083af6ab5fSopenharmony_ci            AnalyzeSwitch(node->AsSwitchStatement());
3093af6ab5fSopenharmony_ci            break;
3103af6ab5fSopenharmony_ci        }
3113af6ab5fSopenharmony_ci        case ir::AstNodeType::TRY_STATEMENT: {
3123af6ab5fSopenharmony_ci            AnalyzeTry(node->AsTryStatement());
3133af6ab5fSopenharmony_ci            break;
3143af6ab5fSopenharmony_ci        }
3153af6ab5fSopenharmony_ci        case ir::AstNodeType::BREAK_STATEMENT: {
3163af6ab5fSopenharmony_ci            AnalyzeBreak(node->AsBreakStatement());
3173af6ab5fSopenharmony_ci            break;
3183af6ab5fSopenharmony_ci        }
3193af6ab5fSopenharmony_ci        case ir::AstNodeType::CONTINUE_STATEMENT: {
3203af6ab5fSopenharmony_ci            AnalyzeContinue(node->AsContinueStatement());
3213af6ab5fSopenharmony_ci            break;
3223af6ab5fSopenharmony_ci        }
3233af6ab5fSopenharmony_ci        case ir::AstNodeType::RETURN_STATEMENT: {
3243af6ab5fSopenharmony_ci            AnalyzeReturn(node->AsReturnStatement());
3253af6ab5fSopenharmony_ci            break;
3263af6ab5fSopenharmony_ci        }
3273af6ab5fSopenharmony_ci        case ir::AstNodeType::THROW_STATEMENT: {
3283af6ab5fSopenharmony_ci            AnalyzeThrow(node->AsThrowStatement());
3293af6ab5fSopenharmony_ci            break;
3303af6ab5fSopenharmony_ci        }
3313af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSERT_STATEMENT: {
3323af6ab5fSopenharmony_ci            AnalyzeAssert(node->AsAssertStatement());
3333af6ab5fSopenharmony_ci            break;
3343af6ab5fSopenharmony_ci        }
3353af6ab5fSopenharmony_ci        default:
3363af6ab5fSopenharmony_ci            return false;
3373af6ab5fSopenharmony_ci    }
3383af6ab5fSopenharmony_ci
3393af6ab5fSopenharmony_ci    return true;
3403af6ab5fSopenharmony_ci}
3413af6ab5fSopenharmony_ci
3423af6ab5fSopenharmony_cibool AssignAnalyzer::AnalyzeExprNode1(const ir::AstNode *node)
3433af6ab5fSopenharmony_ci{
3443af6ab5fSopenharmony_ci    switch (node->Type()) {
3453af6ab5fSopenharmony_ci        case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: {
3463af6ab5fSopenharmony_ci            AnalyzeNewClass(node->AsETSNewClassInstanceExpression());
3473af6ab5fSopenharmony_ci            break;
3483af6ab5fSopenharmony_ci        }
3493af6ab5fSopenharmony_ci        case ir::AstNodeType::CALL_EXPRESSION: {
3503af6ab5fSopenharmony_ci            AnalyzeCallExpr(node->AsCallExpression());
3513af6ab5fSopenharmony_ci            break;
3523af6ab5fSopenharmony_ci        }
3533af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
3543af6ab5fSopenharmony_ci            AnalyzeId(node->AsIdentifier());
3553af6ab5fSopenharmony_ci            break;
3563af6ab5fSopenharmony_ci        }
3573af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
3583af6ab5fSopenharmony_ci            AnalyzeAssignExpr(node->AsAssignmentExpression());
3593af6ab5fSopenharmony_ci            break;
3603af6ab5fSopenharmony_ci        }
3613af6ab5fSopenharmony_ci        case ir::AstNodeType::CONDITIONAL_EXPRESSION: {
3623af6ab5fSopenharmony_ci            AnalyzeCondExpr(node->AsConditionalExpression());
3633af6ab5fSopenharmony_ci            break;
3643af6ab5fSopenharmony_ci        }
3653af6ab5fSopenharmony_ci        case ir::AstNodeType::MEMBER_EXPRESSION: {
3663af6ab5fSopenharmony_ci            AnalyzeMemberExpr(node->AsMemberExpression());
3673af6ab5fSopenharmony_ci            break;
3683af6ab5fSopenharmony_ci        }
3693af6ab5fSopenharmony_ci        default:
3703af6ab5fSopenharmony_ci            return false;
3713af6ab5fSopenharmony_ci    }
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci    return true;
3743af6ab5fSopenharmony_ci}
3753af6ab5fSopenharmony_ci
3763af6ab5fSopenharmony_cibool AssignAnalyzer::AnalyzeExprNode2(const ir::AstNode *node)
3773af6ab5fSopenharmony_ci{
3783af6ab5fSopenharmony_ci    switch (node->Type()) {
3793af6ab5fSopenharmony_ci        case ir::AstNodeType::BINARY_EXPRESSION: {
3803af6ab5fSopenharmony_ci            AnalyzeBinaryExpr(node->AsBinaryExpression());
3813af6ab5fSopenharmony_ci            break;
3823af6ab5fSopenharmony_ci        }
3833af6ab5fSopenharmony_ci        case ir::AstNodeType::UNARY_EXPRESSION: {
3843af6ab5fSopenharmony_ci            AnalyzeUnaryExpr(node->AsUnaryExpression());
3853af6ab5fSopenharmony_ci            break;
3863af6ab5fSopenharmony_ci        }
3873af6ab5fSopenharmony_ci        case ir::AstNodeType::UPDATE_EXPRESSION: {
3883af6ab5fSopenharmony_ci            AnalyzeUpdateExpr(node->AsUpdateExpression());
3893af6ab5fSopenharmony_ci            break;
3903af6ab5fSopenharmony_ci        }
3913af6ab5fSopenharmony_ci        case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: {
3923af6ab5fSopenharmony_ci            AnalyzeArrowFunctionExpr(node->AsArrowFunctionExpression());
3933af6ab5fSopenharmony_ci            break;
3943af6ab5fSopenharmony_ci        }
3953af6ab5fSopenharmony_ci        default:
3963af6ab5fSopenharmony_ci            return false;
3973af6ab5fSopenharmony_ci    }
3983af6ab5fSopenharmony_ci
3993af6ab5fSopenharmony_ci    return true;
4003af6ab5fSopenharmony_ci}
4013af6ab5fSopenharmony_ci
4023af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeStat(const ir::AstNode *node)
4033af6ab5fSopenharmony_ci{
4043af6ab5fSopenharmony_ci    if (node == nullptr) {
4053af6ab5fSopenharmony_ci        return;
4063af6ab5fSopenharmony_ci    }
4073af6ab5fSopenharmony_ci
4083af6ab5fSopenharmony_ci    AnalyzeNode(node);
4093af6ab5fSopenharmony_ci}
4103af6ab5fSopenharmony_ci
4113af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeStats(const ArenaVector<ir::Statement *> &stats)
4123af6ab5fSopenharmony_ci{
4133af6ab5fSopenharmony_ci    for (const auto it : stats) {
4143af6ab5fSopenharmony_ci        AnalyzeStat(it);
4153af6ab5fSopenharmony_ci    }
4163af6ab5fSopenharmony_ci}
4173af6ab5fSopenharmony_ci
4183af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeBlock(const ir::BlockStatement *blockStmt)
4193af6ab5fSopenharmony_ci{
4203af6ab5fSopenharmony_ci    ScopeGuard save(nextAdr_);
4213af6ab5fSopenharmony_ci
4223af6ab5fSopenharmony_ci    AnalyzeStats(blockStmt->Statements());
4233af6ab5fSopenharmony_ci}
4243af6ab5fSopenharmony_ci
4253af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl)
4263af6ab5fSopenharmony_ci{
4273af6ab5fSopenharmony_ci    AnalyzeNode(structDecl->Definition());
4283af6ab5fSopenharmony_ci}
4293af6ab5fSopenharmony_ci
4303af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeClassDecl(const ir::ClassDeclaration *classDecl)
4313af6ab5fSopenharmony_ci{
4323af6ab5fSopenharmony_ci    AnalyzeNode(classDecl->Definition());
4333af6ab5fSopenharmony_ci}
4343af6ab5fSopenharmony_ci
4353af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeClassDef(const ir::ClassDefinition *classDef)
4363af6ab5fSopenharmony_ci{
4373af6ab5fSopenharmony_ci    if (classDef == globalClass_ && globalClassIsVisited_) {
4383af6ab5fSopenharmony_ci        return;
4393af6ab5fSopenharmony_ci    }
4403af6ab5fSopenharmony_ci
4413af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
4423af6ab5fSopenharmony_ci
4433af6ab5fSopenharmony_ci    ScopeGuard save(firstAdr_, nextAdr_, classDef_, classFirstAdr_);
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_ci    classDef_ = classDef;
4463af6ab5fSopenharmony_ci    firstAdr_ = nextAdr_;
4473af6ab5fSopenharmony_ci    classFirstAdr_ = nextAdr_;
4483af6ab5fSopenharmony_ci
4493af6ab5fSopenharmony_ci    ProcessClassDefStaticFields(classDef_);
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci    // define all the instance fields
4523af6ab5fSopenharmony_ci    for (const auto it : classDef->Body()) {
4533af6ab5fSopenharmony_ci        if (it->IsClassProperty() && !it->IsStatic()) {
4543af6ab5fSopenharmony_ci            const auto prop = it->AsClassProperty();
4553af6ab5fSopenharmony_ci            NewVar(prop);
4563af6ab5fSopenharmony_ci            if (prop->Value() != nullptr) {
4573af6ab5fSopenharmony_ci                LetInit(prop);
4583af6ab5fSopenharmony_ci            }
4593af6ab5fSopenharmony_ci        }
4603af6ab5fSopenharmony_ci    }
4613af6ab5fSopenharmony_ci
4623af6ab5fSopenharmony_ci    CheckAnonymousClassCtor(classDef_);
4633af6ab5fSopenharmony_ci
4643af6ab5fSopenharmony_ci    // process all the methods
4653af6ab5fSopenharmony_ci    std::vector<const ir::AstNode *> methods;
4663af6ab5fSopenharmony_ci    for (const auto it : classDef->Body()) {
4673af6ab5fSopenharmony_ci        if (it->IsMethodDefinition()) {
4683af6ab5fSopenharmony_ci            const auto methodDef = it->AsMethodDefinition();
4693af6ab5fSopenharmony_ci            if (methodDef->Key()->AsIdentifier()->Name().Is(compiler::Signatures::INIT_METHOD)) {
4703af6ab5fSopenharmony_ci                // skip the special init method as we have already checked it
4713af6ab5fSopenharmony_ci                continue;
4723af6ab5fSopenharmony_ci            }
4733af6ab5fSopenharmony_ci
4743af6ab5fSopenharmony_ci            methods.push_back(methodDef);
4753af6ab5fSopenharmony_ci
4763af6ab5fSopenharmony_ci            for (const auto it2 : methodDef->Overloads()) {
4773af6ab5fSopenharmony_ci                methods.push_back(it2);
4783af6ab5fSopenharmony_ci            }
4793af6ab5fSopenharmony_ci        }
4803af6ab5fSopenharmony_ci    }
4813af6ab5fSopenharmony_ci
4823af6ab5fSopenharmony_ci    for (const auto it : methods) {
4833af6ab5fSopenharmony_ci        AnalyzeNode(it);
4843af6ab5fSopenharmony_ci    }
4853af6ab5fSopenharmony_ci
4863af6ab5fSopenharmony_ci    SetPendingExits(OldPendingExits());
4873af6ab5fSopenharmony_ci}
4883af6ab5fSopenharmony_ci
4893af6ab5fSopenharmony_ci// NOTE (pantos) awkward methods to conform method length/complexity requirements of CI...
4903af6ab5fSopenharmony_civoid AssignAnalyzer::ProcessClassDefStaticFields(const ir::ClassDefinition *classDef)
4913af6ab5fSopenharmony_ci{
4923af6ab5fSopenharmony_ci    // define all the static fields
4933af6ab5fSopenharmony_ci    for (const auto it : classDef->Body()) {
4943af6ab5fSopenharmony_ci        if (it->IsClassProperty() && it->IsStatic()) {
4953af6ab5fSopenharmony_ci            const auto prop = it->AsClassProperty();
4963af6ab5fSopenharmony_ci            NewVar(prop);
4973af6ab5fSopenharmony_ci            if (prop->Value() != nullptr) {
4983af6ab5fSopenharmony_ci                LetInit(prop);
4993af6ab5fSopenharmony_ci            }
5003af6ab5fSopenharmony_ci        }
5013af6ab5fSopenharmony_ci    }
5023af6ab5fSopenharmony_ci
5033af6ab5fSopenharmony_ci    // process all the static initializers
5043af6ab5fSopenharmony_ci    for (const auto it : classDef->Body()) {
5053af6ab5fSopenharmony_ci        if (it->IsClassStaticBlock() ||
5063af6ab5fSopenharmony_ci            (it->IsStatic() && it->IsMethodDefinition() &&
5073af6ab5fSopenharmony_ci             it->AsMethodDefinition()->Key()->AsIdentifier()->Name().Is(compiler::Signatures::INIT_METHOD))) {
5083af6ab5fSopenharmony_ci            AnalyzeNodes(it);
5093af6ab5fSopenharmony_ci            CheckPendingExits(false);
5103af6ab5fSopenharmony_ci        }
5113af6ab5fSopenharmony_ci    }
5123af6ab5fSopenharmony_ci
5133af6ab5fSopenharmony_ci    // verify all static const fields got initailized
5143af6ab5fSopenharmony_ci    if (classDef != globalClass_) {
5153af6ab5fSopenharmony_ci        for (int i = firstAdr_; i < nextAdr_; i++) {
5163af6ab5fSopenharmony_ci            const ir::AstNode *var = varDecls_[i];
5173af6ab5fSopenharmony_ci            if (var->IsStatic() && (var->IsConst() || CHECK_ALL_PROPERTIES)) {
5183af6ab5fSopenharmony_ci                CheckInit(var);
5193af6ab5fSopenharmony_ci            }
5203af6ab5fSopenharmony_ci        }
5213af6ab5fSopenharmony_ci    }
5223af6ab5fSopenharmony_ci}
5233af6ab5fSopenharmony_ci
5243af6ab5fSopenharmony_civoid AssignAnalyzer::CheckAnonymousClassCtor(const ir::ClassDefinition *classDef)
5253af6ab5fSopenharmony_ci{
5263af6ab5fSopenharmony_ci    if (classDef == globalClass_) {
5273af6ab5fSopenharmony_ci        return;
5283af6ab5fSopenharmony_ci    }
5293af6ab5fSopenharmony_ci
5303af6ab5fSopenharmony_ci    // NOTE(pantos) anonymous classes of new expressions has no default ctor right now
5313af6ab5fSopenharmony_ci    // but this feature might be completely removed from the spec...
5323af6ab5fSopenharmony_ci    bool hasCtor = false;
5333af6ab5fSopenharmony_ci    for (const auto it : classDef->Body()) {
5343af6ab5fSopenharmony_ci        if (it->IsMethodDefinition() && it->AsMethodDefinition()->IsConstructor()) {
5353af6ab5fSopenharmony_ci            hasCtor = true;
5363af6ab5fSopenharmony_ci            break;
5373af6ab5fSopenharmony_ci        }
5383af6ab5fSopenharmony_ci    }
5393af6ab5fSopenharmony_ci    if (!hasCtor) {
5403af6ab5fSopenharmony_ci        for (int i = firstAdr_; i < nextAdr_; i++) {
5413af6ab5fSopenharmony_ci            const ir::AstNode *var = varDecls_[i];
5423af6ab5fSopenharmony_ci            if (!var->IsStatic() && (var->IsConst() || CHECK_ALL_PROPERTIES)) {
5433af6ab5fSopenharmony_ci                CheckInit(var);
5443af6ab5fSopenharmony_ci            }
5453af6ab5fSopenharmony_ci        }
5463af6ab5fSopenharmony_ci    }
5473af6ab5fSopenharmony_ci}
5483af6ab5fSopenharmony_ci
5493af6ab5fSopenharmony_ci// NOTE(pantos) modified version of ETSChecker::CheckCyclicConstructorCall
5503af6ab5fSopenharmony_cistatic bool IsInitialConstructor(const ir::AstNode *node)
5513af6ab5fSopenharmony_ci{
5523af6ab5fSopenharmony_ci    if (!node->IsMethodDefinition() || !node->AsMethodDefinition()->IsConstructor()) {
5533af6ab5fSopenharmony_ci        return false;
5543af6ab5fSopenharmony_ci    }
5553af6ab5fSopenharmony_ci
5563af6ab5fSopenharmony_ci    const auto methodDef = node->AsMethodDefinition();
5573af6ab5fSopenharmony_ci    if (methodDef->Function()->Body() == nullptr || methodDef->Function()->IsExternal()) {
5583af6ab5fSopenharmony_ci        return false;
5593af6ab5fSopenharmony_ci    }
5603af6ab5fSopenharmony_ci
5613af6ab5fSopenharmony_ci    const auto funcBody = node->AsMethodDefinition()->Function()->Body()->AsBlockStatement();
5623af6ab5fSopenharmony_ci
5633af6ab5fSopenharmony_ci    return !(!funcBody->Statements().empty() && funcBody->Statements()[0]->IsExpressionStatement() &&
5643af6ab5fSopenharmony_ci             funcBody->Statements()[0]->AsExpressionStatement()->GetExpression()->IsCallExpression() &&
5653af6ab5fSopenharmony_ci             funcBody->Statements()[0]
5663af6ab5fSopenharmony_ci                 ->AsExpressionStatement()
5673af6ab5fSopenharmony_ci                 ->GetExpression()
5683af6ab5fSopenharmony_ci                 ->AsCallExpression()
5693af6ab5fSopenharmony_ci                 ->Callee()
5703af6ab5fSopenharmony_ci                 ->IsThisExpression());
5713af6ab5fSopenharmony_ci}
5723af6ab5fSopenharmony_ci
5733af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeMethodDef(const ir::MethodDefinition *methodDef)
5743af6ab5fSopenharmony_ci{
5753af6ab5fSopenharmony_ci    auto *func = methodDef->Function();
5763af6ab5fSopenharmony_ci
5773af6ab5fSopenharmony_ci    if (func->Body() == nullptr || func->IsProxy()) {
5783af6ab5fSopenharmony_ci        return;
5793af6ab5fSopenharmony_ci    }
5803af6ab5fSopenharmony_ci
5813af6ab5fSopenharmony_ci    Set initsPrev = inits_;
5823af6ab5fSopenharmony_ci    Set uninitsPrev = uninits_;
5833af6ab5fSopenharmony_ci
5843af6ab5fSopenharmony_ci    ScopeGuard save(firstAdr_, nextAdr_, returnAdr_, isInitialConstructor_);
5853af6ab5fSopenharmony_ci
5863af6ab5fSopenharmony_ci    isInitialConstructor_ = IsInitialConstructor(methodDef);
5873af6ab5fSopenharmony_ci    if (!isInitialConstructor_) {
5883af6ab5fSopenharmony_ci        firstAdr_ = nextAdr_;
5893af6ab5fSopenharmony_ci    }
5903af6ab5fSopenharmony_ci
5913af6ab5fSopenharmony_ci    AnalyzeStat(func->Body());
5923af6ab5fSopenharmony_ci
5933af6ab5fSopenharmony_ci    if (isInitialConstructor_) {
5943af6ab5fSopenharmony_ci        for (int i = firstAdr_; i < nextAdr_; i++) {
5953af6ab5fSopenharmony_ci            const ir::AstNode *var = varDecls_[i];
5963af6ab5fSopenharmony_ci            if (!var->IsStatic() && (var->IsConst() || CHECK_ALL_PROPERTIES)) {
5973af6ab5fSopenharmony_ci                CheckInit(var);
5983af6ab5fSopenharmony_ci            }
5993af6ab5fSopenharmony_ci        }
6003af6ab5fSopenharmony_ci    }
6013af6ab5fSopenharmony_ci
6023af6ab5fSopenharmony_ci    CheckPendingExits(true);
6033af6ab5fSopenharmony_ci
6043af6ab5fSopenharmony_ci    inits_ = initsPrev;
6053af6ab5fSopenharmony_ci    uninits_ = uninitsPrev;
6063af6ab5fSopenharmony_ci}
6073af6ab5fSopenharmony_ci
6083af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeVarDef(const ir::VariableDeclaration *varDef)
6093af6ab5fSopenharmony_ci{
6103af6ab5fSopenharmony_ci    for (auto *var : varDef->Declarators()) {
6113af6ab5fSopenharmony_ci        NewVar(var);
6123af6ab5fSopenharmony_ci
6133af6ab5fSopenharmony_ci        if (var->Init() != nullptr) {
6143af6ab5fSopenharmony_ci            AnalyzeNode(var->Init());
6153af6ab5fSopenharmony_ci            LetInit(var);
6163af6ab5fSopenharmony_ci        }
6173af6ab5fSopenharmony_ci    }
6183af6ab5fSopenharmony_ci}
6193af6ab5fSopenharmony_ci
6203af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeDoLoop(const ir::DoWhileStatement *doWhileStmt)
6213af6ab5fSopenharmony_ci{
6223af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
6233af6ab5fSopenharmony_ci
6243af6ab5fSopenharmony_ci    Set initsSkip {};
6253af6ab5fSopenharmony_ci    Set uninitsSkip {};
6263af6ab5fSopenharmony_ci    int prevErrors = numErrors_;
6273af6ab5fSopenharmony_ci
6283af6ab5fSopenharmony_ci    for (int phase = 1; phase <= LOOP_PHASES; phase++) {
6293af6ab5fSopenharmony_ci        Set uninitsEntry = uninits_;
6303af6ab5fSopenharmony_ci        uninitsEntry.ExcludeFrom(nextAdr_);
6313af6ab5fSopenharmony_ci
6323af6ab5fSopenharmony_ci        AnalyzeStat(doWhileStmt->Body());
6333af6ab5fSopenharmony_ci
6343af6ab5fSopenharmony_ci        ResolveContinues(doWhileStmt);
6353af6ab5fSopenharmony_ci
6363af6ab5fSopenharmony_ci        AnalyzeCond(doWhileStmt->Test());
6373af6ab5fSopenharmony_ci
6383af6ab5fSopenharmony_ci        if (phase == 1) {
6393af6ab5fSopenharmony_ci            initsSkip = initsWhenFalse_;
6403af6ab5fSopenharmony_ci            uninitsSkip = uninitsWhenFalse_;
6413af6ab5fSopenharmony_ci        }
6423af6ab5fSopenharmony_ci
6433af6ab5fSopenharmony_ci        if (prevErrors != numErrors_ || phase == LOOP_PHASES ||
6443af6ab5fSopenharmony_ci            uninitsEntry.DiffSet(uninitsWhenTrue_).Next(firstAdr_) == -1) {
6453af6ab5fSopenharmony_ci            break;
6463af6ab5fSopenharmony_ci        }
6473af6ab5fSopenharmony_ci
6483af6ab5fSopenharmony_ci        inits_ = initsWhenTrue_;
6493af6ab5fSopenharmony_ci        uninits_ = uninitsEntry.AndSet(uninitsWhenTrue_);
6503af6ab5fSopenharmony_ci    }
6513af6ab5fSopenharmony_ci
6523af6ab5fSopenharmony_ci    inits_ = initsSkip;
6533af6ab5fSopenharmony_ci    uninits_ = uninitsSkip;
6543af6ab5fSopenharmony_ci
6553af6ab5fSopenharmony_ci    ResolveBreaks(doWhileStmt);
6563af6ab5fSopenharmony_ci}
6573af6ab5fSopenharmony_ci
6583af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeWhileLoop(const ir::WhileStatement *whileStmt)
6593af6ab5fSopenharmony_ci{
6603af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
6613af6ab5fSopenharmony_ci
6623af6ab5fSopenharmony_ci    Set initsSkip {};
6633af6ab5fSopenharmony_ci    Set uninitsSkip {};
6643af6ab5fSopenharmony_ci    int prevErrors = numErrors_;
6653af6ab5fSopenharmony_ci
6663af6ab5fSopenharmony_ci    Set uninitsEntry = uninits_;
6673af6ab5fSopenharmony_ci    uninitsEntry.ExcludeFrom(nextAdr_);
6683af6ab5fSopenharmony_ci
6693af6ab5fSopenharmony_ci    for (int phase = 1; phase <= LOOP_PHASES; phase++) {
6703af6ab5fSopenharmony_ci        AnalyzeCond(whileStmt->Test());
6713af6ab5fSopenharmony_ci
6723af6ab5fSopenharmony_ci        if (phase == 1) {
6733af6ab5fSopenharmony_ci            initsSkip = initsWhenFalse_;
6743af6ab5fSopenharmony_ci            uninitsSkip = uninitsWhenFalse_;
6753af6ab5fSopenharmony_ci        }
6763af6ab5fSopenharmony_ci
6773af6ab5fSopenharmony_ci        inits_ = initsWhenTrue_;
6783af6ab5fSopenharmony_ci        uninits_ = uninitsWhenTrue_;
6793af6ab5fSopenharmony_ci
6803af6ab5fSopenharmony_ci        AnalyzeStat(whileStmt->Body());
6813af6ab5fSopenharmony_ci
6823af6ab5fSopenharmony_ci        ResolveContinues(whileStmt);
6833af6ab5fSopenharmony_ci
6843af6ab5fSopenharmony_ci        if (prevErrors != numErrors_ || phase == LOOP_PHASES || uninitsEntry.DiffSet(uninits_).Next(firstAdr_) == -1) {
6853af6ab5fSopenharmony_ci            break;
6863af6ab5fSopenharmony_ci        }
6873af6ab5fSopenharmony_ci
6883af6ab5fSopenharmony_ci        uninits_ = uninitsEntry.AndSet(uninits_);
6893af6ab5fSopenharmony_ci    }
6903af6ab5fSopenharmony_ci
6913af6ab5fSopenharmony_ci    inits_ = initsSkip;
6923af6ab5fSopenharmony_ci    uninits_ = uninitsSkip;
6933af6ab5fSopenharmony_ci
6943af6ab5fSopenharmony_ci    ResolveBreaks(whileStmt);
6953af6ab5fSopenharmony_ci}
6963af6ab5fSopenharmony_ci
6973af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeForLoop(const ir::ForUpdateStatement *forStmt)
6983af6ab5fSopenharmony_ci{
6993af6ab5fSopenharmony_ci    ScopeGuard save(nextAdr_);
7003af6ab5fSopenharmony_ci
7013af6ab5fSopenharmony_ci    AnalyzeNode(forStmt->Init());
7023af6ab5fSopenharmony_ci
7033af6ab5fSopenharmony_ci    Set initsSkip {};
7043af6ab5fSopenharmony_ci    Set uninitsSkip {};
7053af6ab5fSopenharmony_ci    int prevErrors = numErrors_;
7063af6ab5fSopenharmony_ci
7073af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
7083af6ab5fSopenharmony_ci
7093af6ab5fSopenharmony_ci    for (int phase = 1; phase <= LOOP_PHASES; phase++) {
7103af6ab5fSopenharmony_ci        Set uninitsEntry = uninits_;
7113af6ab5fSopenharmony_ci        uninitsEntry.ExcludeFrom(nextAdr_);
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_ci        if (forStmt->Test() != nullptr) {
7143af6ab5fSopenharmony_ci            AnalyzeCond(forStmt->Test());
7153af6ab5fSopenharmony_ci
7163af6ab5fSopenharmony_ci            if (phase == 1) {
7173af6ab5fSopenharmony_ci                initsSkip = initsWhenFalse_;
7183af6ab5fSopenharmony_ci                uninitsSkip = uninitsWhenFalse_;
7193af6ab5fSopenharmony_ci            }
7203af6ab5fSopenharmony_ci
7213af6ab5fSopenharmony_ci            inits_ = initsWhenTrue_;
7223af6ab5fSopenharmony_ci            uninits_ = uninitsWhenTrue_;
7233af6ab5fSopenharmony_ci        } else if (phase == 1) {
7243af6ab5fSopenharmony_ci            initsSkip = inits_;
7253af6ab5fSopenharmony_ci            initsSkip.InclRange(firstAdr_, nextAdr_);
7263af6ab5fSopenharmony_ci            uninitsSkip = uninits_;
7273af6ab5fSopenharmony_ci            uninitsSkip.InclRange(firstAdr_, nextAdr_);
7283af6ab5fSopenharmony_ci        }
7293af6ab5fSopenharmony_ci
7303af6ab5fSopenharmony_ci        AnalyzeStat(forStmt->Body());
7313af6ab5fSopenharmony_ci
7323af6ab5fSopenharmony_ci        ResolveContinues(forStmt);
7333af6ab5fSopenharmony_ci
7343af6ab5fSopenharmony_ci        AnalyzeNode(forStmt->Update());
7353af6ab5fSopenharmony_ci
7363af6ab5fSopenharmony_ci        if (prevErrors != numErrors_ || phase == LOOP_PHASES || uninitsEntry.DiffSet(uninits_).Next(firstAdr_) == -1) {
7373af6ab5fSopenharmony_ci            break;
7383af6ab5fSopenharmony_ci        }
7393af6ab5fSopenharmony_ci
7403af6ab5fSopenharmony_ci        uninits_ = uninitsEntry.AndSet(uninits_);
7413af6ab5fSopenharmony_ci    }
7423af6ab5fSopenharmony_ci
7433af6ab5fSopenharmony_ci    inits_ = initsSkip;
7443af6ab5fSopenharmony_ci    uninits_ = uninitsSkip;
7453af6ab5fSopenharmony_ci
7463af6ab5fSopenharmony_ci    ResolveBreaks(forStmt);
7473af6ab5fSopenharmony_ci}
7483af6ab5fSopenharmony_ci
7493af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt)
7503af6ab5fSopenharmony_ci{
7513af6ab5fSopenharmony_ci    ScopeGuard save(nextAdr_);
7523af6ab5fSopenharmony_ci
7533af6ab5fSopenharmony_ci    if (forOfStmt->Left()->IsVariableDeclaration()) {
7543af6ab5fSopenharmony_ci        AnalyzeVarDef(forOfStmt->Left()->AsVariableDeclaration());
7553af6ab5fSopenharmony_ci        for (auto *var : forOfStmt->Left()->AsVariableDeclaration()->Declarators()) {
7563af6ab5fSopenharmony_ci            LetInit(var);
7573af6ab5fSopenharmony_ci        }
7583af6ab5fSopenharmony_ci    } else {
7593af6ab5fSopenharmony_ci        LetInit(forOfStmt->Left());
7603af6ab5fSopenharmony_ci    }
7613af6ab5fSopenharmony_ci
7623af6ab5fSopenharmony_ci    AnalyzeNode(forOfStmt->Right());
7633af6ab5fSopenharmony_ci
7643af6ab5fSopenharmony_ci    Set initsStart = inits_;
7653af6ab5fSopenharmony_ci    Set uninitsStart = uninits_;
7663af6ab5fSopenharmony_ci    int prevErrors = numErrors_;
7673af6ab5fSopenharmony_ci
7683af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
7693af6ab5fSopenharmony_ci
7703af6ab5fSopenharmony_ci    for (int phase = 1; phase <= LOOP_PHASES; phase++) {
7713af6ab5fSopenharmony_ci        Set uninitsEntry = uninits_;
7723af6ab5fSopenharmony_ci        uninitsEntry.ExcludeFrom(nextAdr_);
7733af6ab5fSopenharmony_ci
7743af6ab5fSopenharmony_ci        AnalyzeStat(forOfStmt->Body());
7753af6ab5fSopenharmony_ci
7763af6ab5fSopenharmony_ci        ResolveContinues(forOfStmt);
7773af6ab5fSopenharmony_ci
7783af6ab5fSopenharmony_ci        if (prevErrors != numErrors_ || phase == LOOP_PHASES || uninitsEntry.DiffSet(uninits_).Next(firstAdr_) == -1) {
7793af6ab5fSopenharmony_ci            break;
7803af6ab5fSopenharmony_ci        }
7813af6ab5fSopenharmony_ci
7823af6ab5fSopenharmony_ci        uninits_ = uninitsEntry.AndSet(uninits_);
7833af6ab5fSopenharmony_ci    }
7843af6ab5fSopenharmony_ci
7853af6ab5fSopenharmony_ci    inits_ = initsStart;
7863af6ab5fSopenharmony_ci    uninits_ = uninitsStart.AndSet(uninits_);
7873af6ab5fSopenharmony_ci
7883af6ab5fSopenharmony_ci    ResolveBreaks(forOfStmt);
7893af6ab5fSopenharmony_ci}
7903af6ab5fSopenharmony_ci
7913af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeIf(const ir::IfStatement *ifStmt)
7923af6ab5fSopenharmony_ci{
7933af6ab5fSopenharmony_ci    AnalyzeCond(ifStmt->Test());
7943af6ab5fSopenharmony_ci
7953af6ab5fSopenharmony_ci    Set initsBeforeElse = initsWhenFalse_;
7963af6ab5fSopenharmony_ci    Set uninitsBeforeElse = uninitsWhenFalse_;
7973af6ab5fSopenharmony_ci    inits_ = initsWhenTrue_;
7983af6ab5fSopenharmony_ci    uninits_ = uninitsWhenTrue_;
7993af6ab5fSopenharmony_ci
8003af6ab5fSopenharmony_ci    AnalyzeStat(ifStmt->Consequent());
8013af6ab5fSopenharmony_ci
8023af6ab5fSopenharmony_ci    if (ifStmt->Alternate() != nullptr) {
8033af6ab5fSopenharmony_ci        Set initsAfterThen = inits_;
8043af6ab5fSopenharmony_ci        Set uninitsAfterThen = uninits_;
8053af6ab5fSopenharmony_ci        inits_ = initsBeforeElse;
8063af6ab5fSopenharmony_ci        uninits_ = uninitsBeforeElse;
8073af6ab5fSopenharmony_ci
8083af6ab5fSopenharmony_ci        AnalyzeStat(ifStmt->Alternate());
8093af6ab5fSopenharmony_ci
8103af6ab5fSopenharmony_ci        inits_.AndSet(initsAfterThen);
8113af6ab5fSopenharmony_ci        uninits_.AndSet(uninitsAfterThen);
8123af6ab5fSopenharmony_ci    } else {
8133af6ab5fSopenharmony_ci        inits_.AndSet(initsBeforeElse);
8143af6ab5fSopenharmony_ci        uninits_.AndSet(uninitsBeforeElse);
8153af6ab5fSopenharmony_ci    }
8163af6ab5fSopenharmony_ci}
8173af6ab5fSopenharmony_ci
8183af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeLabelled(const ir::LabelledStatement *labelledStmt)
8193af6ab5fSopenharmony_ci{
8203af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
8213af6ab5fSopenharmony_ci
8223af6ab5fSopenharmony_ci    AnalyzeStat(labelledStmt->Body());
8233af6ab5fSopenharmony_ci
8243af6ab5fSopenharmony_ci    ResolveBreaks(labelledStmt);
8253af6ab5fSopenharmony_ci}
8263af6ab5fSopenharmony_ci
8273af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeSwitch(const ir::SwitchStatement *switchStmt)
8283af6ab5fSopenharmony_ci{
8293af6ab5fSopenharmony_ci    SetOldPendingExits(PendingExits());
8303af6ab5fSopenharmony_ci
8313af6ab5fSopenharmony_ci    ScopeGuard save(nextAdr_);
8323af6ab5fSopenharmony_ci
8333af6ab5fSopenharmony_ci    AnalyzeNode(switchStmt->Discriminant());
8343af6ab5fSopenharmony_ci
8353af6ab5fSopenharmony_ci    Set initsSwitch = inits_;
8363af6ab5fSopenharmony_ci    Set uninitsSwitch = uninits_;
8373af6ab5fSopenharmony_ci
8383af6ab5fSopenharmony_ci    bool hasDefault = false;
8393af6ab5fSopenharmony_ci
8403af6ab5fSopenharmony_ci    for (const auto caseClause : switchStmt->Cases()) {
8413af6ab5fSopenharmony_ci        inits_ = initsSwitch;
8423af6ab5fSopenharmony_ci        uninits_ = uninits_.AndSet(uninitsSwitch);
8433af6ab5fSopenharmony_ci
8443af6ab5fSopenharmony_ci        if (caseClause->Test() == nullptr) {
8453af6ab5fSopenharmony_ci            hasDefault = true;
8463af6ab5fSopenharmony_ci        } else {
8473af6ab5fSopenharmony_ci            AnalyzeNode(caseClause->Test());
8483af6ab5fSopenharmony_ci        }
8493af6ab5fSopenharmony_ci
8503af6ab5fSopenharmony_ci        if (hasDefault) {
8513af6ab5fSopenharmony_ci            inits_ = initsSwitch;
8523af6ab5fSopenharmony_ci            uninits_ = uninits_.AndSet(uninitsSwitch);
8533af6ab5fSopenharmony_ci        }
8543af6ab5fSopenharmony_ci
8553af6ab5fSopenharmony_ci        AnalyzeStats(caseClause->Consequent());
8563af6ab5fSopenharmony_ci
8573af6ab5fSopenharmony_ci        for (const auto stmt : caseClause->Consequent()) {
8583af6ab5fSopenharmony_ci            if (!stmt->IsVariableDeclaration()) {
8593af6ab5fSopenharmony_ci                continue;
8603af6ab5fSopenharmony_ci            }
8613af6ab5fSopenharmony_ci            for (auto *var : stmt->AsVariableDeclaration()->Declarators()) {
8623af6ab5fSopenharmony_ci                NodeId adr = GetNodeId(var);
8633af6ab5fSopenharmony_ci                ASSERT(adr >= 0);
8643af6ab5fSopenharmony_ci                initsSwitch.Excl(adr);
8653af6ab5fSopenharmony_ci                uninitsSwitch.Incl(adr);
8663af6ab5fSopenharmony_ci            }
8673af6ab5fSopenharmony_ci        }
8683af6ab5fSopenharmony_ci
8693af6ab5fSopenharmony_ci        if (!hasDefault) {
8703af6ab5fSopenharmony_ci            inits_ = initsSwitch;
8713af6ab5fSopenharmony_ci            uninits_ = uninits_.AndSet(uninitsSwitch);
8723af6ab5fSopenharmony_ci        }
8733af6ab5fSopenharmony_ci    }
8743af6ab5fSopenharmony_ci
8753af6ab5fSopenharmony_ci    if (!hasDefault) {
8763af6ab5fSopenharmony_ci        inits_.AndSet(initsSwitch);
8773af6ab5fSopenharmony_ci    }
8783af6ab5fSopenharmony_ci
8793af6ab5fSopenharmony_ci    ResolveBreaks(switchStmt);
8803af6ab5fSopenharmony_ci}
8813af6ab5fSopenharmony_ci
8823af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeTry(const ir::TryStatement *tryStmt)
8833af6ab5fSopenharmony_ci{
8843af6ab5fSopenharmony_ci    Set uninitsTryPrev = uninitsTry_;
8853af6ab5fSopenharmony_ci
8863af6ab5fSopenharmony_ci    PendingExitsVector prevPendingExits = PendingExits();
8873af6ab5fSopenharmony_ci    SetOldPendingExits(prevPendingExits);
8883af6ab5fSopenharmony_ci
8893af6ab5fSopenharmony_ci    Set initsTry = inits_;
8903af6ab5fSopenharmony_ci    uninitsTry_ = uninits_;
8913af6ab5fSopenharmony_ci
8923af6ab5fSopenharmony_ci    AnalyzeNode(tryStmt->Block());
8933af6ab5fSopenharmony_ci
8943af6ab5fSopenharmony_ci    uninitsTry_.AndSet(uninits_);
8953af6ab5fSopenharmony_ci
8963af6ab5fSopenharmony_ci    Set initsEnd = inits_;
8973af6ab5fSopenharmony_ci    Set uninitsEnd = uninits_;
8983af6ab5fSopenharmony_ci    int nextAdrCatch = nextAdr_;
8993af6ab5fSopenharmony_ci
9003af6ab5fSopenharmony_ci    Set initsCatchPrev = initsTry;  // NOLINT(performance-unnecessary-copy-initialization)
9013af6ab5fSopenharmony_ci    Set uninitsCatchPrev = uninitsTry_;
9023af6ab5fSopenharmony_ci
9033af6ab5fSopenharmony_ci    for (const auto catchClause : tryStmt->CatchClauses()) {
9043af6ab5fSopenharmony_ci        inits_ = initsCatchPrev;
9053af6ab5fSopenharmony_ci        uninits_ = uninitsCatchPrev;
9063af6ab5fSopenharmony_ci
9073af6ab5fSopenharmony_ci        AnalyzeNode(catchClause->Body());
9083af6ab5fSopenharmony_ci
9093af6ab5fSopenharmony_ci        initsEnd.AndSet(inits_);
9103af6ab5fSopenharmony_ci        uninitsEnd.AndSet(uninits_);
9113af6ab5fSopenharmony_ci        nextAdr_ = nextAdrCatch;
9123af6ab5fSopenharmony_ci    }
9133af6ab5fSopenharmony_ci
9143af6ab5fSopenharmony_ci    if (tryStmt->FinallyBlock() != nullptr) {
9153af6ab5fSopenharmony_ci        inits_ = initsTry;
9163af6ab5fSopenharmony_ci        uninits_ = uninitsTry_;
9173af6ab5fSopenharmony_ci
9183af6ab5fSopenharmony_ci        PendingExitsVector exits = PendingExits();
9193af6ab5fSopenharmony_ci        SetPendingExits(prevPendingExits);
9203af6ab5fSopenharmony_ci
9213af6ab5fSopenharmony_ci        AnalyzeNode(tryStmt->FinallyBlock());
9223af6ab5fSopenharmony_ci
9233af6ab5fSopenharmony_ci        if (tryStmt->FinallyCanCompleteNormally()) {
9243af6ab5fSopenharmony_ci            uninits_.AndSet(uninitsEnd);
9253af6ab5fSopenharmony_ci            for (auto exit : exits) {
9263af6ab5fSopenharmony_ci                exit.exitInits_.OrSet(inits_);
9273af6ab5fSopenharmony_ci                exit.exitUninits_.AndSet(uninits_);
9283af6ab5fSopenharmony_ci                PendingExits().push_back(exit);
9293af6ab5fSopenharmony_ci            }
9303af6ab5fSopenharmony_ci            inits_.OrSet(initsEnd);
9313af6ab5fSopenharmony_ci        }
9323af6ab5fSopenharmony_ci    } else {
9333af6ab5fSopenharmony_ci        inits_ = initsEnd;
9343af6ab5fSopenharmony_ci        uninits_ = uninitsEnd;
9353af6ab5fSopenharmony_ci
9363af6ab5fSopenharmony_ci        PendingExitsVector exits = PendingExits();
9373af6ab5fSopenharmony_ci        SetPendingExits(prevPendingExits);
9383af6ab5fSopenharmony_ci
9393af6ab5fSopenharmony_ci        for (const auto &exit : exits) {
9403af6ab5fSopenharmony_ci            PendingExits().push_back(exit);
9413af6ab5fSopenharmony_ci        }
9423af6ab5fSopenharmony_ci    }
9433af6ab5fSopenharmony_ci
9443af6ab5fSopenharmony_ci    uninitsTry_.AndSet(uninitsTryPrev).AndSet(uninits_);
9453af6ab5fSopenharmony_ci}
9463af6ab5fSopenharmony_ci
9473af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeBreak(const ir::BreakStatement *breakStmt)
9483af6ab5fSopenharmony_ci{
9493af6ab5fSopenharmony_ci    RecordExit(AssignPendingExit(breakStmt, inits_, uninits_));
9503af6ab5fSopenharmony_ci}
9513af6ab5fSopenharmony_ci
9523af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeContinue(const ir::ContinueStatement *contStmt)
9533af6ab5fSopenharmony_ci{
9543af6ab5fSopenharmony_ci    RecordExit(AssignPendingExit(contStmt, inits_, uninits_));
9553af6ab5fSopenharmony_ci}
9563af6ab5fSopenharmony_ci
9573af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeReturn(const ir::ReturnStatement *retStmt)
9583af6ab5fSopenharmony_ci{
9593af6ab5fSopenharmony_ci    AnalyzeNode(retStmt->Argument());
9603af6ab5fSopenharmony_ci    RecordExit(AssignPendingExit(retStmt, inits_, uninits_));
9613af6ab5fSopenharmony_ci}
9623af6ab5fSopenharmony_ci
9633af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeThrow(const ir::ThrowStatement *throwStmt)
9643af6ab5fSopenharmony_ci{
9653af6ab5fSopenharmony_ci    AnalyzeNode(throwStmt->Argument());
9663af6ab5fSopenharmony_ci    MarkDead();
9673af6ab5fSopenharmony_ci}
9683af6ab5fSopenharmony_ci
9693af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeAssert(const ir::AssertStatement *assertStmt)
9703af6ab5fSopenharmony_ci{
9713af6ab5fSopenharmony_ci    Set initsExit = inits_;
9723af6ab5fSopenharmony_ci    Set uninitsExit = uninits_;
9733af6ab5fSopenharmony_ci
9743af6ab5fSopenharmony_ci    AnalyzeCond(assertStmt->Test());
9753af6ab5fSopenharmony_ci
9763af6ab5fSopenharmony_ci    uninitsExit.AndSet(uninitsWhenTrue_);
9773af6ab5fSopenharmony_ci
9783af6ab5fSopenharmony_ci    if (assertStmt->Second() != nullptr) {
9793af6ab5fSopenharmony_ci        inits_ = initsWhenFalse_;
9803af6ab5fSopenharmony_ci        uninits_ = uninitsWhenFalse_;
9813af6ab5fSopenharmony_ci        AnalyzeExpr(assertStmt->Second());
9823af6ab5fSopenharmony_ci    }
9833af6ab5fSopenharmony_ci
9843af6ab5fSopenharmony_ci    inits_ = initsExit;
9853af6ab5fSopenharmony_ci    uninits_ = uninitsExit;
9863af6ab5fSopenharmony_ci}
9873af6ab5fSopenharmony_ci
9883af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeExpr(const ir::AstNode *node)
9893af6ab5fSopenharmony_ci{
9903af6ab5fSopenharmony_ci    if (node != nullptr) {
9913af6ab5fSopenharmony_ci        AnalyzeNode(node);
9923af6ab5fSopenharmony_ci        if (inits_.IsReset()) {
9933af6ab5fSopenharmony_ci            Merge();
9943af6ab5fSopenharmony_ci        }
9953af6ab5fSopenharmony_ci    }
9963af6ab5fSopenharmony_ci}
9973af6ab5fSopenharmony_ci
9983af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeExprs(const ArenaVector<ir::Expression *> &exprs)
9993af6ab5fSopenharmony_ci{
10003af6ab5fSopenharmony_ci    for (const auto it : exprs) {
10013af6ab5fSopenharmony_ci        AnalyzeExpr(it);
10023af6ab5fSopenharmony_ci    }
10033af6ab5fSopenharmony_ci}
10043af6ab5fSopenharmony_ci
10053af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeCond(const ir::AstNode *node)
10063af6ab5fSopenharmony_ci{
10073af6ab5fSopenharmony_ci    ASSERT(node->IsExpression());
10083af6ab5fSopenharmony_ci    const ir::Expression *expr = node->AsExpression();
10093af6ab5fSopenharmony_ci
10103af6ab5fSopenharmony_ci    if (auto etype = expr->TsTypeOrError();
10113af6ab5fSopenharmony_ci        etype != nullptr && etype->IsETSBooleanType() && etype->HasTypeFlag(TypeFlag::CONSTANT)) {
10123af6ab5fSopenharmony_ci        const ETSBooleanType *condType = etype->AsETSBooleanType();
10133af6ab5fSopenharmony_ci        if (inits_.IsReset()) {
10143af6ab5fSopenharmony_ci            Merge();
10153af6ab5fSopenharmony_ci        }
10163af6ab5fSopenharmony_ci        if (condType->GetValue()) {
10173af6ab5fSopenharmony_ci            initsWhenFalse_ = inits_;
10183af6ab5fSopenharmony_ci            initsWhenFalse_.InclRange(firstAdr_, nextAdr_);
10193af6ab5fSopenharmony_ci            uninitsWhenFalse_ = uninits_;
10203af6ab5fSopenharmony_ci            uninitsWhenFalse_.InclRange(firstAdr_, nextAdr_);
10213af6ab5fSopenharmony_ci            initsWhenTrue_ = inits_;
10223af6ab5fSopenharmony_ci            uninitsWhenTrue_ = uninits_;
10233af6ab5fSopenharmony_ci        } else {
10243af6ab5fSopenharmony_ci            initsWhenTrue_ = inits_;
10253af6ab5fSopenharmony_ci            initsWhenTrue_.InclRange(firstAdr_, nextAdr_);
10263af6ab5fSopenharmony_ci            uninitsWhenTrue_ = uninits_;
10273af6ab5fSopenharmony_ci            uninitsWhenTrue_.InclRange(firstAdr_, nextAdr_);
10283af6ab5fSopenharmony_ci            initsWhenFalse_ = inits_;
10293af6ab5fSopenharmony_ci            uninitsWhenFalse_ = uninits_;
10303af6ab5fSopenharmony_ci        }
10313af6ab5fSopenharmony_ci    } else {
10323af6ab5fSopenharmony_ci        AnalyzeNode(node);
10333af6ab5fSopenharmony_ci        if (!inits_.IsReset()) {
10343af6ab5fSopenharmony_ci            Split(true);
10353af6ab5fSopenharmony_ci        }
10363af6ab5fSopenharmony_ci    }
10373af6ab5fSopenharmony_ci
10383af6ab5fSopenharmony_ci    inits_.Reset();
10393af6ab5fSopenharmony_ci    uninits_.Reset();
10403af6ab5fSopenharmony_ci}
10413af6ab5fSopenharmony_ci
10423af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeId(const ir::Identifier *id)
10433af6ab5fSopenharmony_ci{
10443af6ab5fSopenharmony_ci    if (id->Parent()->IsProperty() && id->Parent()->AsProperty()->Key() == id &&
10453af6ab5fSopenharmony_ci        id->Parent()->Parent()->IsObjectExpression()) {
10463af6ab5fSopenharmony_ci        return;  // inside ObjectExpression
10473af6ab5fSopenharmony_ci    }
10483af6ab5fSopenharmony_ci
10493af6ab5fSopenharmony_ci    if (id->Parent()->IsTypeofExpression() && id->Parent()->AsTypeofExpression()->Argument() == id) {
10503af6ab5fSopenharmony_ci        return;  // according to the spec 'typeof' works on uninitialized variables too
10513af6ab5fSopenharmony_ci    }
10523af6ab5fSopenharmony_ci
10533af6ab5fSopenharmony_ci    if (id->Parent()->IsBinaryExpression()) {
10543af6ab5fSopenharmony_ci        const ir::BinaryExpression *binExpr = id->Parent()->AsBinaryExpression();
10553af6ab5fSopenharmony_ci        if ((binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL ||
10563af6ab5fSopenharmony_ci             binExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL) &&
10573af6ab5fSopenharmony_ci            (binExpr->Left()->IsNullLiteral() || binExpr->Right()->IsNullLiteral() ||
10583af6ab5fSopenharmony_ci             binExpr->Left()->IsUndefinedLiteral() || binExpr->Right()->IsUndefinedLiteral())) {
10593af6ab5fSopenharmony_ci            return;  // null/undefined comparison with == or != operators (e.g. in assert statement)
10603af6ab5fSopenharmony_ci        }
10613af6ab5fSopenharmony_ci    }
10623af6ab5fSopenharmony_ci
10633af6ab5fSopenharmony_ci    if (id->Parent()->IsMemberExpression()) {
10643af6ab5fSopenharmony_ci        const ir::MemberExpression *membExpr = id->Parent()->AsMemberExpression();
10653af6ab5fSopenharmony_ci        if (id == membExpr->Property() && !membExpr->Object()->IsThisExpression() &&
10663af6ab5fSopenharmony_ci            membExpr->HasMemberKind(ir::MemberExpressionKind::PROPERTY_ACCESS)) {
10673af6ab5fSopenharmony_ci            return;  // something.property
10683af6ab5fSopenharmony_ci        }
10693af6ab5fSopenharmony_ci    }
10703af6ab5fSopenharmony_ci
10713af6ab5fSopenharmony_ci    if (id->Variable() != nullptr) {
10723af6ab5fSopenharmony_ci        CheckInit(id);
10733af6ab5fSopenharmony_ci    }
10743af6ab5fSopenharmony_ci}
10753af6ab5fSopenharmony_ci
10763af6ab5fSopenharmony_cistatic bool IsIdentOrThisDotIdent(const ir::AstNode *node)
10773af6ab5fSopenharmony_ci{
10783af6ab5fSopenharmony_ci    return node->IsIdentifier() ||
10793af6ab5fSopenharmony_ci           (node->IsMemberExpression() && node->AsMemberExpression()->Object()->IsThisExpression());
10803af6ab5fSopenharmony_ci}
10813af6ab5fSopenharmony_ci
10823af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeAssignExpr(const ir::AssignmentExpression *assignExpr)
10833af6ab5fSopenharmony_ci{
10843af6ab5fSopenharmony_ci    if (!IsIdentOrThisDotIdent(assignExpr->Left())) {
10853af6ab5fSopenharmony_ci        AnalyzeExpr(assignExpr->Left());
10863af6ab5fSopenharmony_ci    }
10873af6ab5fSopenharmony_ci
10883af6ab5fSopenharmony_ci    AnalyzeExpr(assignExpr->Right());
10893af6ab5fSopenharmony_ci
10903af6ab5fSopenharmony_ci    if (assignExpr->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) {
10913af6ab5fSopenharmony_ci        LetInit(assignExpr->Left());
10923af6ab5fSopenharmony_ci    } else {
10933af6ab5fSopenharmony_ci        CheckInit(assignExpr->Left());
10943af6ab5fSopenharmony_ci    }
10953af6ab5fSopenharmony_ci}
10963af6ab5fSopenharmony_ci
10973af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeCondExpr(const ir::ConditionalExpression *condExpr)
10983af6ab5fSopenharmony_ci{
10993af6ab5fSopenharmony_ci    AnalyzeCond(condExpr->Test());
11003af6ab5fSopenharmony_ci
11013af6ab5fSopenharmony_ci    Set initsBeforeElse = initsWhenFalse_;
11023af6ab5fSopenharmony_ci    Set uninitsBeforeElse = uninitsWhenFalse_;
11033af6ab5fSopenharmony_ci    inits_ = initsWhenTrue_;
11043af6ab5fSopenharmony_ci    uninits_ = uninitsWhenTrue_;
11053af6ab5fSopenharmony_ci
11063af6ab5fSopenharmony_ci    ASSERT(condExpr->Consequent()->TsType() && condExpr->Alternate()->TsType());
11073af6ab5fSopenharmony_ci
11083af6ab5fSopenharmony_ci    if (condExpr->Consequent()->TsType()->IsETSBooleanType() && condExpr->Alternate()->TsType()->IsETSBooleanType()) {
11093af6ab5fSopenharmony_ci        AnalyzeCond(condExpr->Consequent());
11103af6ab5fSopenharmony_ci
11113af6ab5fSopenharmony_ci        Set initsAfterThenWhenTrue = initsWhenTrue_;
11123af6ab5fSopenharmony_ci        Set initsAfterThenWhenFalse = initsWhenFalse_;
11133af6ab5fSopenharmony_ci        Set uninitsAfterThenWhenTrue = uninitsWhenTrue_;
11143af6ab5fSopenharmony_ci        Set uninitsAfterThenWhenFalse = uninitsWhenFalse_;
11153af6ab5fSopenharmony_ci        inits_ = initsBeforeElse;
11163af6ab5fSopenharmony_ci        uninits_ = uninitsBeforeElse;
11173af6ab5fSopenharmony_ci
11183af6ab5fSopenharmony_ci        AnalyzeCond(condExpr->Alternate());
11193af6ab5fSopenharmony_ci
11203af6ab5fSopenharmony_ci        initsWhenTrue_.AndSet(initsAfterThenWhenTrue);
11213af6ab5fSopenharmony_ci        initsWhenFalse_.AndSet(initsAfterThenWhenFalse);
11223af6ab5fSopenharmony_ci        uninitsWhenTrue_.AndSet(uninitsAfterThenWhenTrue);
11233af6ab5fSopenharmony_ci        uninitsWhenFalse_.AndSet(uninitsAfterThenWhenFalse);
11243af6ab5fSopenharmony_ci    } else {
11253af6ab5fSopenharmony_ci        AnalyzeExpr(condExpr->Consequent());
11263af6ab5fSopenharmony_ci
11273af6ab5fSopenharmony_ci        Set initsAfterThen = inits_;
11283af6ab5fSopenharmony_ci        Set uninitsAfterThen = uninits_;
11293af6ab5fSopenharmony_ci        inits_ = initsBeforeElse;
11303af6ab5fSopenharmony_ci        uninits_ = uninitsBeforeElse;
11313af6ab5fSopenharmony_ci
11323af6ab5fSopenharmony_ci        AnalyzeExpr(condExpr->Alternate());
11333af6ab5fSopenharmony_ci
11343af6ab5fSopenharmony_ci        inits_.AndSet(initsAfterThen);
11353af6ab5fSopenharmony_ci        uninits_.AndSet(uninitsAfterThen);
11363af6ab5fSopenharmony_ci    }
11373af6ab5fSopenharmony_ci}
11383af6ab5fSopenharmony_ci
11393af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeCallExpr(const ir::CallExpression *callExpr)
11403af6ab5fSopenharmony_ci{
11413af6ab5fSopenharmony_ci    AnalyzeExpr(callExpr->Callee());
11423af6ab5fSopenharmony_ci    AnalyzeExprs(callExpr->Arguments());
11433af6ab5fSopenharmony_ci}
11443af6ab5fSopenharmony_ci
11453af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeMemberExpr(const ir::MemberExpression *membExpr)
11463af6ab5fSopenharmony_ci{
11473af6ab5fSopenharmony_ci    if (membExpr->Object()->IsThisExpression() && membExpr->HasMemberKind(ir::MemberExpressionKind::PROPERTY_ACCESS)) {
11483af6ab5fSopenharmony_ci        CheckInit(membExpr);
11493af6ab5fSopenharmony_ci    } else {
11503af6ab5fSopenharmony_ci        AnalyzeNode(membExpr->Object());
11513af6ab5fSopenharmony_ci        AnalyzeNode(membExpr->Property());
11523af6ab5fSopenharmony_ci    }
11533af6ab5fSopenharmony_ci}
11543af6ab5fSopenharmony_ci
11553af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass)
11563af6ab5fSopenharmony_ci{
11573af6ab5fSopenharmony_ci    AnalyzeExpr(newClass->GetTypeRef());
11583af6ab5fSopenharmony_ci    AnalyzeExprs(newClass->GetArguments());
11593af6ab5fSopenharmony_ci    AnalyzeNode(newClass->ClassDefinition());
11603af6ab5fSopenharmony_ci}
11613af6ab5fSopenharmony_ci
11623af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeUnaryExpr(const ir::UnaryExpression *unaryExpr)
11633af6ab5fSopenharmony_ci{
11643af6ab5fSopenharmony_ci    AnalyzeCond(unaryExpr->Argument());
11653af6ab5fSopenharmony_ci
11663af6ab5fSopenharmony_ci    switch (unaryExpr->OperatorType()) {
11673af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
11683af6ab5fSopenharmony_ci            Set t = initsWhenFalse_;
11693af6ab5fSopenharmony_ci            initsWhenFalse_ = initsWhenTrue_;
11703af6ab5fSopenharmony_ci            initsWhenTrue_ = t;
11713af6ab5fSopenharmony_ci            t = uninitsWhenFalse_;
11723af6ab5fSopenharmony_ci            uninitsWhenFalse_ = uninitsWhenTrue_;
11733af6ab5fSopenharmony_ci            uninitsWhenTrue_ = t;
11743af6ab5fSopenharmony_ci            break;
11753af6ab5fSopenharmony_ci        }
11763af6ab5fSopenharmony_ci        default: {
11773af6ab5fSopenharmony_ci            AnalyzeExpr(unaryExpr->Argument());
11783af6ab5fSopenharmony_ci            break;
11793af6ab5fSopenharmony_ci        }
11803af6ab5fSopenharmony_ci    }
11813af6ab5fSopenharmony_ci}
11823af6ab5fSopenharmony_ci
11833af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeBinaryExpr(const ir::BinaryExpression *binExpr)
11843af6ab5fSopenharmony_ci{
11853af6ab5fSopenharmony_ci    switch (binExpr->OperatorType()) {
11863af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: {
11873af6ab5fSopenharmony_ci            AnalyzeCond(binExpr->Left());
11883af6ab5fSopenharmony_ci            Set initsWhenFalseLeft = initsWhenFalse_;
11893af6ab5fSopenharmony_ci            Set uninitsWhenFalseLeft = uninitsWhenFalse_;
11903af6ab5fSopenharmony_ci            inits_ = initsWhenTrue_;
11913af6ab5fSopenharmony_ci            uninits_ = uninitsWhenTrue_;
11923af6ab5fSopenharmony_ci            AnalyzeCond(binExpr->Right());
11933af6ab5fSopenharmony_ci            initsWhenFalse_.AndSet(initsWhenFalseLeft);
11943af6ab5fSopenharmony_ci            uninitsWhenFalse_.AndSet(uninitsWhenFalseLeft);
11953af6ab5fSopenharmony_ci            break;
11963af6ab5fSopenharmony_ci        }
11973af6ab5fSopenharmony_ci        case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: {
11983af6ab5fSopenharmony_ci            AnalyzeCond(binExpr->Left());
11993af6ab5fSopenharmony_ci            Set initsWhenTrueLeft = initsWhenTrue_;
12003af6ab5fSopenharmony_ci            Set uninitsWhenTrueLeft = uninitsWhenTrue_;
12013af6ab5fSopenharmony_ci            inits_ = initsWhenFalse_;
12023af6ab5fSopenharmony_ci            uninits_ = uninitsWhenFalse_;
12033af6ab5fSopenharmony_ci            AnalyzeCond(binExpr->Right());
12043af6ab5fSopenharmony_ci            initsWhenTrue_.AndSet(initsWhenTrueLeft);
12053af6ab5fSopenharmony_ci            uninitsWhenTrue_.AndSet(uninitsWhenTrueLeft);
12063af6ab5fSopenharmony_ci            break;
12073af6ab5fSopenharmony_ci        }
12083af6ab5fSopenharmony_ci        default: {
12093af6ab5fSopenharmony_ci            AnalyzeExpr(binExpr->Left());
12103af6ab5fSopenharmony_ci            AnalyzeExpr(binExpr->Right());
12113af6ab5fSopenharmony_ci            break;
12123af6ab5fSopenharmony_ci        }
12133af6ab5fSopenharmony_ci    }
12143af6ab5fSopenharmony_ci}
12153af6ab5fSopenharmony_ci
12163af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeUpdateExpr(const ir::UpdateExpression *updateExpr)
12173af6ab5fSopenharmony_ci{
12183af6ab5fSopenharmony_ci    AnalyzeExpr(updateExpr->Argument());
12193af6ab5fSopenharmony_ci    LetInit(updateExpr->Argument());
12203af6ab5fSopenharmony_ci}
12213af6ab5fSopenharmony_ci
12223af6ab5fSopenharmony_civoid AssignAnalyzer::AnalyzeArrowFunctionExpr(const ir::ArrowFunctionExpression *arrowFuncExpr)
12233af6ab5fSopenharmony_ci{
12243af6ab5fSopenharmony_ci    // NOTE (pantos) handle lamdas correctly
12253af6ab5fSopenharmony_ci    (void)arrowFuncExpr;
12263af6ab5fSopenharmony_ci}
12273af6ab5fSopenharmony_ci
12283af6ab5fSopenharmony_ciutil::StringView AssignAnalyzer::GetVariableType(const ir::AstNode *node) const
12293af6ab5fSopenharmony_ci{
12303af6ab5fSopenharmony_ci    switch (node->Type()) {
12313af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_PROPERTY:
12323af6ab5fSopenharmony_ci            if (node->AsClassProperty()->Parent() == globalClass_) {
12333af6ab5fSopenharmony_ci                return "variable";
12343af6ab5fSopenharmony_ci            } else {
12353af6ab5fSopenharmony_ci                return "property";
12363af6ab5fSopenharmony_ci            }
12373af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR:
12383af6ab5fSopenharmony_ci            return "variable";
12393af6ab5fSopenharmony_ci        default:
12403af6ab5fSopenharmony_ci            UNREACHABLE();
12413af6ab5fSopenharmony_ci    }
12423af6ab5fSopenharmony_ci}
12433af6ab5fSopenharmony_ci
12443af6ab5fSopenharmony_ciutil::StringView AssignAnalyzer::GetVariableName(const ir::AstNode *node) const
12453af6ab5fSopenharmony_ci{
12463af6ab5fSopenharmony_ci    switch (node->Type()) {
12473af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_PROPERTY:
12483af6ab5fSopenharmony_ci            return node->AsClassProperty()->Id()->Name();
12493af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR:
12503af6ab5fSopenharmony_ci            return node->AsVariableDeclarator()->Id()->AsIdentifier()->Name();
12513af6ab5fSopenharmony_ci        default:
12523af6ab5fSopenharmony_ci            UNREACHABLE();
12533af6ab5fSopenharmony_ci    }
12543af6ab5fSopenharmony_ci}
12553af6ab5fSopenharmony_ci
12563af6ab5fSopenharmony_ciconst lexer::SourcePosition &AssignAnalyzer::GetVariablePosition(const ir::AstNode *node) const
12573af6ab5fSopenharmony_ci{
12583af6ab5fSopenharmony_ci    switch (node->Type()) {
12593af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_PROPERTY:
12603af6ab5fSopenharmony_ci            return node->AsClassProperty()->Key()->Start();
12613af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR:
12623af6ab5fSopenharmony_ci        default:
12633af6ab5fSopenharmony_ci            return node->Start();
12643af6ab5fSopenharmony_ci    }
12653af6ab5fSopenharmony_ci}
12663af6ab5fSopenharmony_ci
12673af6ab5fSopenharmony_ciNodeId AssignAnalyzer::GetNodeId(const ir::AstNode *node) const
12683af6ab5fSopenharmony_ci{
12693af6ab5fSopenharmony_ci    auto res = nodeIdMap_.find(node);
12703af6ab5fSopenharmony_ci    if (res != nodeIdMap_.end()) {
12713af6ab5fSopenharmony_ci        return res->second;
12723af6ab5fSopenharmony_ci    }
12733af6ab5fSopenharmony_ci    return INVALID_ID;
12743af6ab5fSopenharmony_ci}
12753af6ab5fSopenharmony_ci
12763af6ab5fSopenharmony_cibool AssignAnalyzer::Trackable(const ir::AstNode *node) const
12773af6ab5fSopenharmony_ci{
12783af6ab5fSopenharmony_ci    switch (node->Type()) {
12793af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_PROPERTY:
12803af6ab5fSopenharmony_ci        case ir::AstNodeType::VARIABLE_DECLARATOR:
12813af6ab5fSopenharmony_ci            return true;
12823af6ab5fSopenharmony_ci        default:
12833af6ab5fSopenharmony_ci            return false;
12843af6ab5fSopenharmony_ci    }
12853af6ab5fSopenharmony_ci}
12863af6ab5fSopenharmony_ci
12873af6ab5fSopenharmony_cibool AssignAnalyzer::IsConstUninitializedField(const ir::AstNode *node) const
12883af6ab5fSopenharmony_ci{
12893af6ab5fSopenharmony_ci    return node->IsClassProperty() && node->IsConst();
12903af6ab5fSopenharmony_ci}
12913af6ab5fSopenharmony_ci
12923af6ab5fSopenharmony_cibool AssignAnalyzer::IsConstUninitializedStaticField(const ir::AstNode *node) const
12933af6ab5fSopenharmony_ci{
12943af6ab5fSopenharmony_ci    return IsConstUninitializedField(node) && node->IsStatic();
12953af6ab5fSopenharmony_ci}
12963af6ab5fSopenharmony_ci
12973af6ab5fSopenharmony_civoid AssignAnalyzer::NewVar(const ir::AstNode *node)
12983af6ab5fSopenharmony_ci{
12993af6ab5fSopenharmony_ci    if (!Trackable(node)) {
13003af6ab5fSopenharmony_ci        return;
13013af6ab5fSopenharmony_ci    }
13023af6ab5fSopenharmony_ci
13033af6ab5fSopenharmony_ci    if (GetNodeId(node) != INVALID_ID) {
13043af6ab5fSopenharmony_ci        return;
13053af6ab5fSopenharmony_ci    }
13063af6ab5fSopenharmony_ci
13073af6ab5fSopenharmony_ci    nodeIdMap_[node] = nextAdr_;
13083af6ab5fSopenharmony_ci    varDecls_.reserve(nextAdr_ + 1);
13093af6ab5fSopenharmony_ci    varDecls_.insert(varDecls_.begin() + nextAdr_, node);
13103af6ab5fSopenharmony_ci    inits_.Excl(nextAdr_);
13113af6ab5fSopenharmony_ci    uninits_.Incl(nextAdr_);
13123af6ab5fSopenharmony_ci    ++nextAdr_;
13133af6ab5fSopenharmony_ci}
13143af6ab5fSopenharmony_ci
13153af6ab5fSopenharmony_civarbinder::Variable *AssignAnalyzer::GetBoundVariable(const ir::AstNode *node)
13163af6ab5fSopenharmony_ci{
13173af6ab5fSopenharmony_ci    varbinder::Variable *ret = nullptr;
13183af6ab5fSopenharmony_ci
13193af6ab5fSopenharmony_ci    if (node->IsClassProperty()) {
13203af6ab5fSopenharmony_ci        ret = node->AsClassProperty()->Id()->Variable();
13213af6ab5fSopenharmony_ci    } else if (node->IsVariableDeclarator()) {
13223af6ab5fSopenharmony_ci        ret = node->AsVariableDeclarator()->Id()->AsIdentifier()->Variable();
13233af6ab5fSopenharmony_ci    } else {
13243af6ab5fSopenharmony_ci        UNREACHABLE();
13253af6ab5fSopenharmony_ci    }
13263af6ab5fSopenharmony_ci
13273af6ab5fSopenharmony_ci    return ret;
13283af6ab5fSopenharmony_ci}
13293af6ab5fSopenharmony_ci
13303af6ab5fSopenharmony_ciconst ir::AstNode *AssignAnalyzer::GetDeclaringNode(const ir::AstNode *node)
13313af6ab5fSopenharmony_ci{
13323af6ab5fSopenharmony_ci    if (node->IsClassProperty() || node->IsVariableDeclarator()) {
13333af6ab5fSopenharmony_ci        return node;
13343af6ab5fSopenharmony_ci    }
13353af6ab5fSopenharmony_ci
13363af6ab5fSopenharmony_ci    const ir::AstNode *ret = nullptr;
13373af6ab5fSopenharmony_ci
13383af6ab5fSopenharmony_ci    if (node->IsMemberExpression()) {
13393af6ab5fSopenharmony_ci        const ir::MemberExpression *membExpr = node->AsMemberExpression();
13403af6ab5fSopenharmony_ci        if (membExpr->PropVar() != nullptr) {
13413af6ab5fSopenharmony_ci            if (membExpr->PropVar()->Declaration() != nullptr) {
13423af6ab5fSopenharmony_ci                ret = membExpr->PropVar()->Declaration()->Node();
13433af6ab5fSopenharmony_ci            }
13443af6ab5fSopenharmony_ci        }
13453af6ab5fSopenharmony_ci    } else if (node->IsIdentifier()) {
13463af6ab5fSopenharmony_ci        const ir::Identifier *id = node->AsIdentifier();
13473af6ab5fSopenharmony_ci        if (id->Variable() != nullptr) {
13483af6ab5fSopenharmony_ci            if (id->Variable()->Declaration() != nullptr) {
13493af6ab5fSopenharmony_ci                ret = id->Variable()->Declaration()->Node();
13503af6ab5fSopenharmony_ci            }
13513af6ab5fSopenharmony_ci        }
13523af6ab5fSopenharmony_ci    }
13533af6ab5fSopenharmony_ci
13543af6ab5fSopenharmony_ci    if (ret != nullptr) {
13553af6ab5fSopenharmony_ci        if (ret->IsIdentifier() && ret->Parent()->IsVariableDeclarator() &&
13563af6ab5fSopenharmony_ci            ret == ret->Parent()->AsVariableDeclarator()->Id()) {
13573af6ab5fSopenharmony_ci            ret = ret->Parent();
13583af6ab5fSopenharmony_ci        }
13593af6ab5fSopenharmony_ci    }
13603af6ab5fSopenharmony_ci
13613af6ab5fSopenharmony_ci    return ret;
13623af6ab5fSopenharmony_ci}
13633af6ab5fSopenharmony_ci
13643af6ab5fSopenharmony_cibool AssignAnalyzer::VariableHasDefaultValue(const ir::AstNode *node)
13653af6ab5fSopenharmony_ci{
13663af6ab5fSopenharmony_ci    ASSERT(node != nullptr);
13673af6ab5fSopenharmony_ci
13683af6ab5fSopenharmony_ci    const checker::Type *type = nullptr;
13693af6ab5fSopenharmony_ci    bool isNonReadonlyField = false;
13703af6ab5fSopenharmony_ci
13713af6ab5fSopenharmony_ci    if (node->IsClassProperty()) {
13723af6ab5fSopenharmony_ci        type = node->AsClassProperty()->TsType();
13733af6ab5fSopenharmony_ci        isNonReadonlyField = !node->IsReadonly();  // NOTE(pantos) readonly is true, const is not set?
13743af6ab5fSopenharmony_ci    } else if (node->IsVariableDeclarator()) {
13753af6ab5fSopenharmony_ci        varbinder::Variable *variable = GetBoundVariable(node);
13763af6ab5fSopenharmony_ci        if (variable != nullptr) {
13773af6ab5fSopenharmony_ci            type = variable->TsType();
13783af6ab5fSopenharmony_ci        }
13793af6ab5fSopenharmony_ci    } else {
13803af6ab5fSopenharmony_ci        UNREACHABLE();
13813af6ab5fSopenharmony_ci    }
13823af6ab5fSopenharmony_ci
13833af6ab5fSopenharmony_ci    return type != nullptr &&
13843af6ab5fSopenharmony_ci           (type->HasTypeFlag(checker::TypeFlag::ETS_PRIMITIVE) ||
13853af6ab5fSopenharmony_ci            (type->PossiblyETSNullish() && (!type->HasTypeFlag(checker::TypeFlag::GENERIC) ||
13863af6ab5fSopenharmony_ci                                            (isNonReadonlyField && !CHECK_GENERIC_NON_READONLY_PROPERTIES))));
13873af6ab5fSopenharmony_ci}
13883af6ab5fSopenharmony_ci
13893af6ab5fSopenharmony_civoid AssignAnalyzer::LetInit(const ir::AstNode *node)
13903af6ab5fSopenharmony_ci{
13913af6ab5fSopenharmony_ci    const ir::AstNode *declNode = GetDeclaringNode(node);
13923af6ab5fSopenharmony_ci
13933af6ab5fSopenharmony_ci    if (declNode == nullptr || declNode->IsDeclare()) {
13943af6ab5fSopenharmony_ci        return;
13953af6ab5fSopenharmony_ci    }
13963af6ab5fSopenharmony_ci
13973af6ab5fSopenharmony_ci    NodeId adr = GetNodeId(declNode);
13983af6ab5fSopenharmony_ci    if (adr == INVALID_ID) {
13993af6ab5fSopenharmony_ci        return;
14003af6ab5fSopenharmony_ci    }
14013af6ab5fSopenharmony_ci
14023af6ab5fSopenharmony_ci    if (node != declNode && declNode->IsConst()) {
14033af6ab5fSopenharmony_ci        // check reassignment of readonly properties
14043af6ab5fSopenharmony_ci        util::StringView type = GetVariableType(declNode);
14053af6ab5fSopenharmony_ci        util::StringView name = GetVariableName(declNode);
14063af6ab5fSopenharmony_ci        const lexer::SourcePosition &pos = GetVariablePosition(node);
14073af6ab5fSopenharmony_ci
14083af6ab5fSopenharmony_ci        auto uninit = [this](NodeId a) {
14093af6ab5fSopenharmony_ci            uninits_.Excl(a);
14103af6ab5fSopenharmony_ci            if (!inits_.IsMember(a)) {
14113af6ab5fSopenharmony_ci                uninitsTry_.Excl(a);
14123af6ab5fSopenharmony_ci            }
14133af6ab5fSopenharmony_ci        };
14143af6ab5fSopenharmony_ci
14153af6ab5fSopenharmony_ci        if (classDef_ == globalClass_ || (adr < classFirstAdr_ || adr >= firstAdr_)) {
14163af6ab5fSopenharmony_ci            if (declNode->IsClassProperty() && classDef_ != declNode->Parent()) {
14173af6ab5fSopenharmony_ci                Warning({"Cannot assign to '", name, "' because it is a read-only property."}, pos);
14183af6ab5fSopenharmony_ci            } else if (!uninits_.IsMember(adr)) {
14193af6ab5fSopenharmony_ci                Warning({Capitalize(type).c_str(), " '", name, "' might already have been assigned."}, pos);
14203af6ab5fSopenharmony_ci            } else {
14213af6ab5fSopenharmony_ci                uninit(adr);
14223af6ab5fSopenharmony_ci            }
14233af6ab5fSopenharmony_ci        }
14243af6ab5fSopenharmony_ci    }
14253af6ab5fSopenharmony_ci
14263af6ab5fSopenharmony_ci    inits_.Incl(adr);
14273af6ab5fSopenharmony_ci}
14283af6ab5fSopenharmony_ci
14293af6ab5fSopenharmony_civoid AssignAnalyzer::CheckInit(const ir::AstNode *node)
14303af6ab5fSopenharmony_ci{
14313af6ab5fSopenharmony_ci    const ir::AstNode *declNode = GetDeclaringNode(node);
14323af6ab5fSopenharmony_ci
14333af6ab5fSopenharmony_ci    if (declNode == nullptr || declNode->IsDeclare()) {
14343af6ab5fSopenharmony_ci        return;
14353af6ab5fSopenharmony_ci    }
14363af6ab5fSopenharmony_ci
14373af6ab5fSopenharmony_ci    NodeId adr = GetNodeId(declNode);
14383af6ab5fSopenharmony_ci    if (adr == INVALID_ID) {
14393af6ab5fSopenharmony_ci        return;
14403af6ab5fSopenharmony_ci    }
14413af6ab5fSopenharmony_ci
14423af6ab5fSopenharmony_ci    if (VariableHasDefaultValue(declNode)) {
14433af6ab5fSopenharmony_ci        // no explicit init is required (primitive, nullish)
14443af6ab5fSopenharmony_ci        return;
14453af6ab5fSopenharmony_ci    }
14463af6ab5fSopenharmony_ci
14473af6ab5fSopenharmony_ci    if (declNode->IsClassProperty()) {
14483af6ab5fSopenharmony_ci        if (!CHECK_ALL_PROPERTIES && !declNode->IsConst()) {
14493af6ab5fSopenharmony_ci            // non readonly property
14503af6ab5fSopenharmony_ci            return;
14513af6ab5fSopenharmony_ci        }
14523af6ab5fSopenharmony_ci
14533af6ab5fSopenharmony_ci        if (declNode->Parent() == globalClass_) {
14543af6ab5fSopenharmony_ci            // NOTE(pantos) dont check global variable accesses
14553af6ab5fSopenharmony_ci            return;
14563af6ab5fSopenharmony_ci        }
14573af6ab5fSopenharmony_ci
14583af6ab5fSopenharmony_ci        if (declNode->Parent() != classDef_) {
14593af6ab5fSopenharmony_ci            // property of an other class
14603af6ab5fSopenharmony_ci            return;
14613af6ab5fSopenharmony_ci        }
14623af6ab5fSopenharmony_ci    }
14633af6ab5fSopenharmony_ci
14643af6ab5fSopenharmony_ci    if (classDef_ == globalClass_ || (adr < classFirstAdr_ || adr >= firstAdr_)) {
14653af6ab5fSopenharmony_ci        if (!inits_.IsMember(adr)) {
14663af6ab5fSopenharmony_ci            if (WARN_NO_INIT_ONCE_PER_VARIABLE && !foundErrors_.insert(declNode).second) {
14673af6ab5fSopenharmony_ci                return;
14683af6ab5fSopenharmony_ci            }
14693af6ab5fSopenharmony_ci
14703af6ab5fSopenharmony_ci            util::StringView type = GetVariableType(declNode);
14713af6ab5fSopenharmony_ci            util::StringView name = GetVariableName(declNode);
14723af6ab5fSopenharmony_ci            const lexer::SourcePosition &pos = GetVariablePosition(node);
14733af6ab5fSopenharmony_ci
14743af6ab5fSopenharmony_ci            std::stringstream ss;
14753af6ab5fSopenharmony_ci            if (node->IsClassProperty()) {
14763af6ab5fSopenharmony_ci                ss << "Property '" << name << "' might not have been initialized.";
14773af6ab5fSopenharmony_ci            } else {
14783af6ab5fSopenharmony_ci                ss << Capitalize(type) << " '" << name << "' is used before being assigned.";
14793af6ab5fSopenharmony_ci            }
14803af6ab5fSopenharmony_ci
14813af6ab5fSopenharmony_ci            Warning(ss.str(), pos);
14823af6ab5fSopenharmony_ci        }
14833af6ab5fSopenharmony_ci    }
14843af6ab5fSopenharmony_ci}
14853af6ab5fSopenharmony_ci
14863af6ab5fSopenharmony_civoid AssignAnalyzer::Split(const bool setToNull)
14873af6ab5fSopenharmony_ci{
14883af6ab5fSopenharmony_ci    initsWhenFalse_ = inits_;
14893af6ab5fSopenharmony_ci    uninitsWhenFalse_ = uninits_;
14903af6ab5fSopenharmony_ci    initsWhenTrue_ = inits_;
14913af6ab5fSopenharmony_ci    uninitsWhenTrue_ = uninits_;
14923af6ab5fSopenharmony_ci    if (setToNull) {
14933af6ab5fSopenharmony_ci        inits_.Reset();
14943af6ab5fSopenharmony_ci        uninits_.Reset();
14953af6ab5fSopenharmony_ci    }
14963af6ab5fSopenharmony_ci}
14973af6ab5fSopenharmony_ci
14983af6ab5fSopenharmony_civoid AssignAnalyzer::Merge()
14993af6ab5fSopenharmony_ci{
15003af6ab5fSopenharmony_ci    inits_ = initsWhenFalse_.AndSet(initsWhenTrue_);
15013af6ab5fSopenharmony_ci    uninits_ = uninitsWhenFalse_.AndSet(uninitsWhenTrue_);
15023af6ab5fSopenharmony_ci}
15033af6ab5fSopenharmony_ci
15043af6ab5fSopenharmony_civoid AssignAnalyzer::CheckPendingExits(bool inMethod)
15053af6ab5fSopenharmony_ci{
15063af6ab5fSopenharmony_ci    PendingExitsVector exits = PendingExits();
15073af6ab5fSopenharmony_ci
15083af6ab5fSopenharmony_ci    for (auto &it : exits) {
15093af6ab5fSopenharmony_ci        // NOTE(pantos) pending exits should be refactored, break/continue may stay in this
15103af6ab5fSopenharmony_ci        if (inMethod && !it.Node()->IsReturnStatement()) {
15113af6ab5fSopenharmony_ci            continue;
15123af6ab5fSopenharmony_ci        }
15133af6ab5fSopenharmony_ci
15143af6ab5fSopenharmony_ci        if (inMethod && isInitialConstructor_) {
15153af6ab5fSopenharmony_ci            inits_ = it.exitInits_;
15163af6ab5fSopenharmony_ci
15173af6ab5fSopenharmony_ci            for (int i = firstAdr_; i < nextAdr_; i++) {
15183af6ab5fSopenharmony_ci                CheckInit(varDecls_[i]);
15193af6ab5fSopenharmony_ci            }
15203af6ab5fSopenharmony_ci        }
15213af6ab5fSopenharmony_ci    }
15223af6ab5fSopenharmony_ci
15233af6ab5fSopenharmony_ci    ClearPendingExits();
15243af6ab5fSopenharmony_ci}
15253af6ab5fSopenharmony_ci
15263af6ab5fSopenharmony_civoid AssignAnalyzer::MarkDead()
15273af6ab5fSopenharmony_ci{
15283af6ab5fSopenharmony_ci    if (!isInitialConstructor_) {
15293af6ab5fSopenharmony_ci        inits_.InclRange(returnAdr_, nextAdr_);
15303af6ab5fSopenharmony_ci    } else {
15313af6ab5fSopenharmony_ci        for (int address = returnAdr_; address < nextAdr_; address++) {
15323af6ab5fSopenharmony_ci            if (!IsConstUninitializedStaticField(varDecls_[address])) {
15333af6ab5fSopenharmony_ci                inits_.Incl(address);
15343af6ab5fSopenharmony_ci            }
15353af6ab5fSopenharmony_ci        }
15363af6ab5fSopenharmony_ci    }
15373af6ab5fSopenharmony_ci    uninits_.InclRange(returnAdr_, nextAdr_);
15383af6ab5fSopenharmony_ci}
15393af6ab5fSopenharmony_ci
15403af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
1541