1 /* 2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H 17 #define ES2PANDA_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H 18 19 #include "checker/ETSchecker.h" 20 #include "checker/ets/baseAnalyzer.h" 21 22 #include "utils/arena_containers.h" 23 24 namespace ark::es2panda::ir { 25 class AstNode; 26 } // namespace ark::es2panda::ir 27 28 namespace ark::es2panda::checker { 29 30 class Set { 31 public: 32 Set() = default; 33 ~Set() = default; 34 35 DEFAULT_COPY_SEMANTIC(Set); 36 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(Set); 37 38 void Reset(); 39 bool IsReset(); 40 void Incl(const int id); 41 void InclRange(const int start, const int limit); 42 void ExcludeFrom(const int start); 43 void Excl(const int id); 44 bool IsMember(const int id) const; 45 Set &AndSet(const Set &xs); 46 Set &OrSet(const Set &xs); 47 Set &DiffSet(const Set &xs); 48 int Next(const int id); 49 50 protected: 51 void InternalAndSet(const Set &xs); 52 53 private: 54 bool reset_ {}; 55 std::set<int> nodes_ {}; 56 }; 57 58 class AssignPendingExit : public PendingExit { 59 public: AssignPendingExit(const ir::AstNode * node,Set & inits,Set & uninits,bool isInitialConstructor,bool hasTryFinallyBlock)60 explicit AssignPendingExit(const ir::AstNode *node, Set &inits, Set &uninits, bool isInitialConstructor, 61 bool hasTryFinallyBlock) 62 : PendingExit(node), inits_(&inits), uninits_(&uninits) 63 { 64 if (isInitialConstructor || hasTryFinallyBlock) { 65 exitInits_ = inits; 66 } 67 if (hasTryFinallyBlock) { 68 exitUninits_ = uninits; 69 } 70 } 71 ~AssignPendingExit() override = default; 72 73 DEFAULT_COPY_SEMANTIC(AssignPendingExit); 74 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(AssignPendingExit); 75 76 // NOLINTBEGIN(misc-non-private-member-variables-in-classes,readability-identifier-naming) 77 Set *inits_; 78 Set *uninits_; 79 Set exitInits_; 80 Set exitUninits_; 81 // NOLINTEND(misc-non-private-member-variables-in-classes,readability-identifier-naming) 82 }; 83 84 using NodeId = int; 85 using NodeIdMap = ArenaMap<const ir::AstNode *, NodeId>; 86 87 class AssignAnalyzer : public BaseAnalyzer<AssignPendingExit> { 88 public: 89 explicit AssignAnalyzer(ETSChecker *checker); 90 void Analyze(const ir::AstNode *node); 91 92 void MarkDead() override; 93 94 private: 95 // node visitors 96 void AnalyzeNodes(const ir::AstNode *node); 97 void AnalyzeNode(const ir::AstNode *node); 98 bool AnalyzeStmtNode1(const ir::AstNode *node); 99 bool AnalyzeStmtNode2(const ir::AstNode *node); 100 bool AnalyzeExprNode1(const ir::AstNode *node); 101 bool AnalyzeExprNode2(const ir::AstNode *node); 102 void AnalyzeStat(const ir::AstNode *node); 103 void AnalyzeStats(const ArenaVector<ir::Statement *> &stats); 104 void AnalyzeBlock(const ir::BlockStatement *blockStmt); 105 void AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl); 106 void AnalyzeClassDecl(const ir::ClassDeclaration *classDecl); 107 void AnalyzeClassDef(const ir::ClassDefinition *classDef); 108 void ProcessClassDefStaticFields(const ir::ClassDefinition *classDef); 109 void CheckAnonymousClassCtor(const ir::ClassDefinition *classDef); 110 void AnalyzeMethodDef(const ir::MethodDefinition *methodDef); 111 void AnalyzeVarDef(const ir::VariableDeclaration *varDef); 112 void AnalyzeDoLoop(const ir::DoWhileStatement *doWhileStmt); 113 void AnalyzeWhileLoop(const ir::WhileStatement *whileStmt); 114 void AnalyzeForLoop(const ir::ForUpdateStatement *forStmt); 115 void AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt); 116 void AnalyzeIf(const ir::IfStatement *ifStmt); 117 void AnalyzeLabelled(const ir::LabelledStatement *labelledStmt); 118 void AnalyzeSwitch(const ir::SwitchStatement *switchStmt); 119 void AnalyzeTry(const ir::TryStatement *tryStmt); 120 void AnalyzeBreak(const ir::BreakStatement *breakStmt); 121 void AnalyzeContinue(const ir::ContinueStatement *contStmt); 122 void AnalyzeReturn(const ir::ReturnStatement *retStmt); 123 void AnalyzeThrow(const ir::ThrowStatement *throwStmt); 124 void AnalyzeExpr(const ir::AstNode *node); 125 void AnalyzeExprs(const ArenaVector<ir::Expression *> &exprs); 126 void AnalyzeCond(const ir::AstNode *node); 127 void AnalyzeAssignExpr(const ir::AssignmentExpression *assignExpr); 128 void AnalyzeBinaryExpr(const ir::BinaryExpression *binExpr); 129 void AnalyzeCallExpr(const ir::CallExpression *callExpr); 130 void AnalyzeCondExpr(const ir::ConditionalExpression *condExpr); 131 void AnalyzeId(const ir::Identifier *id); 132 void AnalyzeMemberExpr(const ir::MemberExpression *membExpr); 133 void AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass); 134 void AnalyzeUnaryExpr(const ir::UnaryExpression *unaryExpr); 135 void AnalyzeUpdateExpr(const ir::UpdateExpression *updateExpr); 136 void AnalyzeArrowFunctionExpr(const ir::ArrowFunctionExpression *arrowFuncExpr); 137 138 // utils 139 void Warning(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams &list, 140 const lexer::SourcePosition &pos); 141 bool Trackable(const ir::AstNode *node) const; 142 bool IsConstUninitializedField(const ir::AstNode *node) const; 143 bool IsConstUninitializedStaticField(const ir::AstNode *node) const; 144 void NewVar(const ir::AstNode *node); 145 void LetInit(const ir::AstNode *node); 146 void CheckInit(const ir::AstNode *node); 147 void Split(const bool setToNull); 148 void Merge(); 149 void CheckPendingExits(); 150 NodeId GetNodeId(const ir::AstNode *node) const; 151 util::StringView GetVariableType(const ir::AstNode *node) const; 152 util::StringView GetVariableName(const ir::AstNode *node) const; 153 const lexer::SourcePosition &GetVariablePosition(const ir::AstNode *node) const; 154 const ir::AstNode *GetDeclaringNode(const ir::AstNode *node); 155 varbinder::Variable *GetBoundVariable(const ir::AstNode *node); 156 bool VariableHasDefaultValue(const ir::AstNode *node); 157 158 ETSChecker *checker_; 159 Set inits_ {}; 160 Set uninits_ {}; 161 Set uninitsTry_ {}; 162 Set initsWhenTrue_ {}; 163 Set initsWhenFalse_ {}; 164 Set uninitsWhenTrue_ {}; 165 Set uninitsWhenFalse_ {}; 166 ArenaVector<const ir::AstNode *> varDecls_; 167 const ir::ClassDefinition *globalClass_ {}; 168 const ir::ClassDefinition *classDef_ {}; 169 int classFirstAdr_ {}; 170 int firstNonGlobalAdr_ {}; 171 int firstAdr_ {}; 172 int nextAdr_ {}; 173 int returnAdr_ {}; 174 bool isInitialConstructor_ {}; 175 bool hasTryFinallyBlock_ {}; 176 NodeIdMap nodeIdMap_; 177 int numErrors_ {}; 178 ArenaSet<const ir::AstNode *> foundErrors_; 179 }; 180 181 } // namespace ark::es2panda::checker 182 183 #endif 184