1 /* 2 * Copyright (c) 2021-2024 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)60 explicit AssignPendingExit(const ir::AstNode *node, Set &inits, Set &uninits) 61 : PendingExit(node), inits_(&inits), uninits_(&uninits) 62 { 63 exitInits_ = inits; 64 exitUninits_ = uninits; 65 } 66 ~AssignPendingExit() override = default; 67 68 DEFAULT_COPY_SEMANTIC(AssignPendingExit); 69 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(AssignPendingExit); 70 71 void ResolveJump() override 72 { 73 inits_->AndSet(exitInits_); 74 uninits_->AndSet(exitUninits_); 75 } 76 77 // NOLINTBEGIN(misc-non-private-member-variables-in-classes,readability-identifier-naming) 78 Set *inits_; 79 Set *uninits_; 80 Set exitInits_; 81 Set exitUninits_; 82 // NOLINTEND(misc-non-private-member-variables-in-classes,readability-identifier-naming) 83 }; 84 85 using NodeId = int; 86 using NodeIdMap = ArenaMap<const ir::AstNode *, NodeId>; 87 88 class AssignAnalyzer : public BaseAnalyzer<AssignPendingExit> { 89 public: 90 explicit AssignAnalyzer(ETSChecker *checker); 91 void Analyze(const ir::AstNode *node); 92 93 void MarkDead() override; 94 95 private: 96 // node visitors 97 void AnalyzeNodes(const ir::AstNode *node); 98 void AnalyzeNode(const ir::AstNode *node); 99 bool AnalyzeStmtNode1(const ir::AstNode *node); 100 bool AnalyzeStmtNode2(const ir::AstNode *node); 101 bool AnalyzeExprNode1(const ir::AstNode *node); 102 bool AnalyzeExprNode2(const ir::AstNode *node); 103 void AnalyzeStat(const ir::AstNode *node); 104 void AnalyzeStats(const ArenaVector<ir::Statement *> &stats); 105 void AnalyzeBlock(const ir::BlockStatement *blockStmt); 106 void AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl); 107 void AnalyzeClassDecl(const ir::ClassDeclaration *classDecl); 108 void AnalyzeClassDef(const ir::ClassDefinition *classDef); 109 void ProcessClassDefStaticFields(const ir::ClassDefinition *classDef); 110 void CheckAnonymousClassCtor(const ir::ClassDefinition *classDef); 111 void AnalyzeMethodDef(const ir::MethodDefinition *methodDef); 112 void AnalyzeVarDef(const ir::VariableDeclaration *varDef); 113 void AnalyzeDoLoop(const ir::DoWhileStatement *doWhileStmt); 114 void AnalyzeWhileLoop(const ir::WhileStatement *whileStmt); 115 void AnalyzeForLoop(const ir::ForUpdateStatement *forStmt); 116 void AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt); 117 void AnalyzeIf(const ir::IfStatement *ifStmt); 118 void AnalyzeLabelled(const ir::LabelledStatement *labelledStmt); 119 void AnalyzeSwitch(const ir::SwitchStatement *switchStmt); 120 void AnalyzeTry(const ir::TryStatement *tryStmt); 121 void AnalyzeBreak(const ir::BreakStatement *breakStmt); 122 void AnalyzeContinue(const ir::ContinueStatement *contStmt); 123 void AnalyzeReturn(const ir::ReturnStatement *retStmt); 124 void AnalyzeThrow(const ir::ThrowStatement *throwStmt); 125 void AnalyzeAssert(const ir::AssertStatement *assertStmt); 126 void AnalyzeExpr(const ir::AstNode *node); 127 void AnalyzeExprs(const ArenaVector<ir::Expression *> &exprs); 128 void AnalyzeCond(const ir::AstNode *node); 129 void AnalyzeAssignExpr(const ir::AssignmentExpression *assignExpr); 130 void AnalyzeBinaryExpr(const ir::BinaryExpression *binExpr); 131 void AnalyzeCallExpr(const ir::CallExpression *callExpr); 132 void AnalyzeCondExpr(const ir::ConditionalExpression *condExpr); 133 void AnalyzeId(const ir::Identifier *id); 134 void AnalyzeMemberExpr(const ir::MemberExpression *membExpr); 135 void AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass); 136 void AnalyzeUnaryExpr(const ir::UnaryExpression *unaryExpr); 137 void AnalyzeUpdateExpr(const ir::UpdateExpression *updateExpr); 138 void AnalyzeArrowFunctionExpr(const ir::ArrowFunctionExpression *arrowFuncExpr); 139 140 // utils 141 void Warning(std::string_view message, const lexer::SourcePosition &pos); 142 void Warning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos); 143 bool Trackable(const ir::AstNode *node) const; 144 bool IsConstUninitializedField(const ir::AstNode *node) const; 145 bool IsConstUninitializedStaticField(const ir::AstNode *node) const; 146 void NewVar(const ir::AstNode *node); 147 void LetInit(const ir::AstNode *node); 148 void CheckInit(const ir::AstNode *node); 149 void Split(bool setToNull); 150 void Merge(); 151 void CheckPendingExits(bool inMethod); 152 NodeId GetNodeId(const ir::AstNode *node) const; 153 util::StringView GetVariableType(const ir::AstNode *node) const; 154 util::StringView GetVariableName(const ir::AstNode *node) const; 155 const lexer::SourcePosition &GetVariablePosition(const ir::AstNode *node) const; 156 const ir::AstNode *GetDeclaringNode(const ir::AstNode *node); 157 varbinder::Variable *GetBoundVariable(const ir::AstNode *node); 158 bool VariableHasDefaultValue(const ir::AstNode *node); 159 160 ETSChecker *checker_; 161 Set inits_ {}; 162 Set uninits_ {}; 163 Set uninitsTry_ {}; 164 Set initsWhenTrue_ {}; 165 Set initsWhenFalse_ {}; 166 Set uninitsWhenTrue_ {}; 167 Set uninitsWhenFalse_ {}; 168 ArenaVector<const ir::AstNode *> varDecls_; 169 const ir::ClassDefinition *globalClass_ {}; 170 const ir::ClassDefinition *classDef_ {}; 171 bool globalClassIsVisited_ {}; 172 int classFirstAdr_ {}; 173 int firstNonGlobalAdr_ {}; 174 int firstAdr_ {}; 175 int nextAdr_ {}; 176 int returnAdr_ {}; 177 bool isInitialConstructor_ {}; 178 NodeIdMap nodeIdMap_; 179 int numErrors_ {}; 180 ArenaSet<const ir::AstNode *> foundErrors_; 181 }; 182 183 } // namespace ark::es2panda::checker 184 185 #endif 186