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