• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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