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#ifndef ES2PANDA_CHECKER_CHECKER_H 173af6ab5fSopenharmony_ci#define ES2PANDA_CHECKER_CHECKER_H 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ci#include "es2panda.h" 203af6ab5fSopenharmony_ci 213af6ab5fSopenharmony_ci#include "checker/checkerContext.h" 223af6ab5fSopenharmony_ci#include "checker/SemanticAnalyzer.h" 233af6ab5fSopenharmony_ci#include "util/errorLogger.h" 243af6ab5fSopenharmony_ci 253af6ab5fSopenharmony_cinamespace ark::es2panda::parser { 263af6ab5fSopenharmony_ciclass Program; 273af6ab5fSopenharmony_ci} // namespace ark::es2panda::parser 283af6ab5fSopenharmony_ci 293af6ab5fSopenharmony_cinamespace ark::es2panda::ir { 303af6ab5fSopenharmony_ciclass AstNode; 313af6ab5fSopenharmony_ciclass Expression; 323af6ab5fSopenharmony_ciclass BlockStatement; 333af6ab5fSopenharmony_cienum class AstNodeType; 343af6ab5fSopenharmony_ci} // namespace ark::es2panda::ir 353af6ab5fSopenharmony_ci 363af6ab5fSopenharmony_cinamespace ark::es2panda::varbinder { 373af6ab5fSopenharmony_ciclass VarBinder; 383af6ab5fSopenharmony_ciclass Decl; 393af6ab5fSopenharmony_ciclass EnumVariable; 403af6ab5fSopenharmony_ciclass FunctionDecl; 413af6ab5fSopenharmony_ciclass LocalVariable; 423af6ab5fSopenharmony_ciclass Scope; 433af6ab5fSopenharmony_ciclass Variable; 443af6ab5fSopenharmony_ci} // namespace ark::es2panda::varbinder 453af6ab5fSopenharmony_ci 463af6ab5fSopenharmony_cinamespace ark::es2panda::checker { 473af6ab5fSopenharmony_ciclass ETSChecker; 483af6ab5fSopenharmony_ciclass InterfaceType; 493af6ab5fSopenharmony_ciclass GlobalTypesHolder; 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ciusing StringLiteralPool = std::unordered_map<util::StringView, Type *>; 523af6ab5fSopenharmony_ciusing NumberLiteralPool = std::unordered_map<double, Type *>; 533af6ab5fSopenharmony_ciusing FunctionParamsResolveResult = std::variant<std::vector<varbinder::LocalVariable *> &, bool>; 543af6ab5fSopenharmony_ciusing InterfacePropertyMap = 553af6ab5fSopenharmony_ci std::unordered_map<util::StringView, std::pair<varbinder::LocalVariable *, InterfaceType *>>; 563af6ab5fSopenharmony_ciusing TypeOrNode = std::variant<Type *, ir::AstNode *>; 573af6ab5fSopenharmony_ciusing IndexInfoTypePair = std::pair<Type *, Type *>; 583af6ab5fSopenharmony_ciusing PropertyMap = std::unordered_map<util::StringView, varbinder::LocalVariable *>; 593af6ab5fSopenharmony_ciusing ArgRange = std::pair<uint32_t, uint32_t>; 603af6ab5fSopenharmony_ci 613af6ab5fSopenharmony_ciclass Checker { 623af6ab5fSopenharmony_cipublic: 633af6ab5fSopenharmony_ci explicit Checker(); 643af6ab5fSopenharmony_ci virtual ~Checker() = default; 653af6ab5fSopenharmony_ci 663af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(Checker); 673af6ab5fSopenharmony_ci NO_MOVE_SEMANTIC(Checker); 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci [[nodiscard]] ArenaAllocator *Allocator() noexcept 703af6ab5fSopenharmony_ci { 713af6ab5fSopenharmony_ci return &allocator_; 723af6ab5fSopenharmony_ci } 733af6ab5fSopenharmony_ci 743af6ab5fSopenharmony_ci [[nodiscard]] varbinder::Scope *Scope() const noexcept 753af6ab5fSopenharmony_ci { 763af6ab5fSopenharmony_ci return scope_; 773af6ab5fSopenharmony_ci } 783af6ab5fSopenharmony_ci 793af6ab5fSopenharmony_ci [[nodiscard]] CheckerContext &Context() noexcept 803af6ab5fSopenharmony_ci { 813af6ab5fSopenharmony_ci return context_; 823af6ab5fSopenharmony_ci } 833af6ab5fSopenharmony_ci 843af6ab5fSopenharmony_ci [[nodiscard]] bool HasStatus(CheckerStatus status) noexcept 853af6ab5fSopenharmony_ci { 863af6ab5fSopenharmony_ci return (context_.Status() & status) != 0; 873af6ab5fSopenharmony_ci } 883af6ab5fSopenharmony_ci 893af6ab5fSopenharmony_ci void RemoveStatus(CheckerStatus status) noexcept 903af6ab5fSopenharmony_ci { 913af6ab5fSopenharmony_ci context_.Status() &= ~status; 923af6ab5fSopenharmony_ci } 933af6ab5fSopenharmony_ci 943af6ab5fSopenharmony_ci void AddStatus(CheckerStatus status) noexcept 953af6ab5fSopenharmony_ci { 963af6ab5fSopenharmony_ci context_.Status() |= status; 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci 993af6ab5fSopenharmony_ci [[nodiscard]] TypeRelation *Relation() const noexcept 1003af6ab5fSopenharmony_ci { 1013af6ab5fSopenharmony_ci return relation_; 1023af6ab5fSopenharmony_ci } 1033af6ab5fSopenharmony_ci 1043af6ab5fSopenharmony_ci [[nodiscard]] GlobalTypesHolder *GetGlobalTypesHolder() const noexcept 1053af6ab5fSopenharmony_ci { 1063af6ab5fSopenharmony_ci return globalTypes_; 1073af6ab5fSopenharmony_ci } 1083af6ab5fSopenharmony_ci 1093af6ab5fSopenharmony_ci [[nodiscard]] RelationHolder &IdenticalResults() noexcept 1103af6ab5fSopenharmony_ci { 1113af6ab5fSopenharmony_ci return identicalResults_; 1123af6ab5fSopenharmony_ci } 1133af6ab5fSopenharmony_ci 1143af6ab5fSopenharmony_ci [[nodiscard]] RelationHolder &AssignableResults() noexcept 1153af6ab5fSopenharmony_ci { 1163af6ab5fSopenharmony_ci return assignableResults_; 1173af6ab5fSopenharmony_ci } 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_ci [[nodiscard]] RelationHolder &ComparableResults() noexcept 1203af6ab5fSopenharmony_ci { 1213af6ab5fSopenharmony_ci return comparableResults_; 1223af6ab5fSopenharmony_ci } 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ci [[nodiscard]] RelationHolder &UncheckedCastableResult() noexcept 1253af6ab5fSopenharmony_ci { 1263af6ab5fSopenharmony_ci return uncheckedCastableResults_; 1273af6ab5fSopenharmony_ci } 1283af6ab5fSopenharmony_ci 1293af6ab5fSopenharmony_ci [[nodiscard]] RelationHolder &SupertypeResults() noexcept 1303af6ab5fSopenharmony_ci { 1313af6ab5fSopenharmony_ci return supertypeResults_; 1323af6ab5fSopenharmony_ci } 1333af6ab5fSopenharmony_ci 1343af6ab5fSopenharmony_ci [[nodiscard]] std::unordered_set<const void *> &TypeStack() noexcept 1353af6ab5fSopenharmony_ci { 1363af6ab5fSopenharmony_ci return typeStack_; 1373af6ab5fSopenharmony_ci } 1383af6ab5fSopenharmony_ci 1393af6ab5fSopenharmony_ci [[nodiscard]] std::unordered_set<Type *> &NamedTypeStack() noexcept 1403af6ab5fSopenharmony_ci { 1413af6ab5fSopenharmony_ci return namedTypeStack_; 1423af6ab5fSopenharmony_ci } 1433af6ab5fSopenharmony_ci 1443af6ab5fSopenharmony_ci [[nodiscard]] virtual bool IsETSChecker() const noexcept 1453af6ab5fSopenharmony_ci { 1463af6ab5fSopenharmony_ci return false; 1473af6ab5fSopenharmony_ci } 1483af6ab5fSopenharmony_ci 1493af6ab5fSopenharmony_ci [[nodiscard]] ETSChecker *AsETSChecker() 1503af6ab5fSopenharmony_ci { 1513af6ab5fSopenharmony_ci ASSERT(IsETSChecker()); 1523af6ab5fSopenharmony_ci return reinterpret_cast<ETSChecker *>(this); 1533af6ab5fSopenharmony_ci } 1543af6ab5fSopenharmony_ci 1553af6ab5fSopenharmony_ci [[nodiscard]] const ETSChecker *AsETSChecker() const 1563af6ab5fSopenharmony_ci { 1573af6ab5fSopenharmony_ci ASSERT(IsETSChecker()); 1583af6ab5fSopenharmony_ci return reinterpret_cast<const ETSChecker *>(this); 1593af6ab5fSopenharmony_ci } 1603af6ab5fSopenharmony_ci 1613af6ab5fSopenharmony_ci virtual bool StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const CompilerOptions &options) = 0; 1623af6ab5fSopenharmony_ci virtual Type *CheckTypeCached(ir::Expression *expr) = 0; 1633af6ab5fSopenharmony_ci virtual Type *GetTypeOfVariable(varbinder::Variable *var) = 0; 1643af6ab5fSopenharmony_ci virtual void ResolveStructuredTypeMembers(Type *type) = 0; 1653af6ab5fSopenharmony_ci 1663af6ab5fSopenharmony_ci std::string FormatMsg(std::initializer_list<TypeErrorMessageElement> list); 1673af6ab5fSopenharmony_ci [[noreturn]] void ThrowTypeError(std::string_view message, const lexer::SourcePosition &pos); 1683af6ab5fSopenharmony_ci [[noreturn]] void ThrowTypeError(std::initializer_list<TypeErrorMessageElement> list, 1693af6ab5fSopenharmony_ci const lexer::SourcePosition &pos); 1703af6ab5fSopenharmony_ci void LogTypeError(std::string_view message, const lexer::SourcePosition &pos); 1713af6ab5fSopenharmony_ci void LogTypeError(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos); 1723af6ab5fSopenharmony_ci void Warning(std::string_view message, const lexer::SourcePosition &pos) const; 1733af6ab5fSopenharmony_ci void ReportWarning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos); 1743af6ab5fSopenharmony_ci 1753af6ab5fSopenharmony_ci bool IsTypeIdenticalTo(Type *source, Type *target); 1763af6ab5fSopenharmony_ci bool IsTypeIdenticalTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 1773af6ab5fSopenharmony_ci bool IsTypeIdenticalTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 1783af6ab5fSopenharmony_ci const lexer::SourcePosition &errPos); 1793af6ab5fSopenharmony_ci bool IsTypeAssignableTo(Type *source, Type *target); 1803af6ab5fSopenharmony_ci bool IsTypeAssignableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 1813af6ab5fSopenharmony_ci bool IsTypeAssignableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 1823af6ab5fSopenharmony_ci const lexer::SourcePosition &errPos); 1833af6ab5fSopenharmony_ci bool IsTypeComparableTo(Type *source, Type *target); 1843af6ab5fSopenharmony_ci bool IsTypeComparableTo(Type *source, Type *target, const std::string &errMsg, const lexer::SourcePosition &errPos); 1853af6ab5fSopenharmony_ci bool IsTypeComparableTo(Type *source, Type *target, std::initializer_list<TypeErrorMessageElement> list, 1863af6ab5fSopenharmony_ci const lexer::SourcePosition &errPos); 1873af6ab5fSopenharmony_ci bool AreTypesComparable(Type *source, Type *target); 1883af6ab5fSopenharmony_ci bool IsTypeEqualityComparableTo(Type *source, Type *target); 1893af6ab5fSopenharmony_ci bool IsAllTypesAssignableTo(Type *source, Type *target); 1903af6ab5fSopenharmony_ci void SetAnalyzer(SemanticAnalyzer *analyzer); 1913af6ab5fSopenharmony_ci checker::SemanticAnalyzer *GetAnalyzer() const; 1923af6ab5fSopenharmony_ci 1933af6ab5fSopenharmony_ci friend class ScopeContext; 1943af6ab5fSopenharmony_ci friend class TypeStackElement; 1953af6ab5fSopenharmony_ci friend class NamedTypeStackElement; 1963af6ab5fSopenharmony_ci friend class SavedCheckerContext; 1973af6ab5fSopenharmony_ci friend class NamedTypeStackElement; 1983af6ab5fSopenharmony_ci 1993af6ab5fSopenharmony_ci varbinder::VarBinder *VarBinder() const; 2003af6ab5fSopenharmony_ci 2013af6ab5fSopenharmony_ci util::ErrorLogger *ErrorLogger() 2023af6ab5fSopenharmony_ci { 2033af6ab5fSopenharmony_ci return &errorLogger_; 2043af6ab5fSopenharmony_ci } 2053af6ab5fSopenharmony_ci 2063af6ab5fSopenharmony_ci // NOTE: required only for evaluate. 2073af6ab5fSopenharmony_ci void Initialize(varbinder::VarBinder *varbinder); 2083af6ab5fSopenharmony_ci 2093af6ab5fSopenharmony_ciprotected: 2103af6ab5fSopenharmony_ci parser::Program *Program() const; 2113af6ab5fSopenharmony_ci void SetProgram(parser::Program *program); 2123af6ab5fSopenharmony_ci 2133af6ab5fSopenharmony_ciprivate: 2143af6ab5fSopenharmony_ci ArenaAllocator allocator_; 2153af6ab5fSopenharmony_ci CheckerContext context_; 2163af6ab5fSopenharmony_ci GlobalTypesHolder *globalTypes_; 2173af6ab5fSopenharmony_ci TypeRelation *relation_; 2183af6ab5fSopenharmony_ci SemanticAnalyzer *analyzer_ {}; 2193af6ab5fSopenharmony_ci varbinder::VarBinder *varbinder_ {}; 2203af6ab5fSopenharmony_ci parser::Program *program_ {}; 2213af6ab5fSopenharmony_ci varbinder::Scope *scope_ {}; 2223af6ab5fSopenharmony_ci util::ErrorLogger errorLogger_; 2233af6ab5fSopenharmony_ci 2243af6ab5fSopenharmony_ci RelationHolder identicalResults_ {{}, RelationType::IDENTICAL}; 2253af6ab5fSopenharmony_ci RelationHolder assignableResults_ {{}, RelationType::ASSIGNABLE}; 2263af6ab5fSopenharmony_ci RelationHolder comparableResults_ {{}, RelationType::COMPARABLE}; 2273af6ab5fSopenharmony_ci RelationHolder uncheckedCastableResults_ {{}, RelationType::UNCHECKED_CASTABLE}; 2283af6ab5fSopenharmony_ci RelationHolder supertypeResults_ {{}, RelationType::SUPERTYPE}; 2293af6ab5fSopenharmony_ci 2303af6ab5fSopenharmony_ci std::unordered_set<const void *> typeStack_; 2313af6ab5fSopenharmony_ci std::unordered_set<Type *> namedTypeStack_; 2323af6ab5fSopenharmony_ci}; 2333af6ab5fSopenharmony_ci 2343af6ab5fSopenharmony_ciclass NamedTypeStackElement { 2353af6ab5fSopenharmony_cipublic: 2363af6ab5fSopenharmony_ci explicit NamedTypeStackElement(Checker *checker, Type *element) : checker_(checker), element_(element) 2373af6ab5fSopenharmony_ci { 2383af6ab5fSopenharmony_ci checker_->namedTypeStack_.insert(element); 2393af6ab5fSopenharmony_ci } 2403af6ab5fSopenharmony_ci 2413af6ab5fSopenharmony_ci ~NamedTypeStackElement() 2423af6ab5fSopenharmony_ci { 2433af6ab5fSopenharmony_ci checker_->namedTypeStack_.erase(element_); 2443af6ab5fSopenharmony_ci } 2453af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(NamedTypeStackElement); 2463af6ab5fSopenharmony_ci NO_MOVE_SEMANTIC(NamedTypeStackElement); 2473af6ab5fSopenharmony_ci 2483af6ab5fSopenharmony_ciprivate: 2493af6ab5fSopenharmony_ci Checker *checker_; 2503af6ab5fSopenharmony_ci Type *element_; 2513af6ab5fSopenharmony_ci}; 2523af6ab5fSopenharmony_ci 2533af6ab5fSopenharmony_ciclass TypeStackElement { 2543af6ab5fSopenharmony_cipublic: 2553af6ab5fSopenharmony_ci explicit TypeStackElement(Checker *checker, void *element, std::initializer_list<TypeErrorMessageElement> list, 2563af6ab5fSopenharmony_ci const lexer::SourcePosition &pos) 2573af6ab5fSopenharmony_ci : checker_(checker), element_(element), hasErrorChecker_(false) 2583af6ab5fSopenharmony_ci { 2593af6ab5fSopenharmony_ci if (!checker->typeStack_.insert(element).second) { 2603af6ab5fSopenharmony_ci checker_->LogTypeError(list, pos); 2613af6ab5fSopenharmony_ci element_ = nullptr; 2623af6ab5fSopenharmony_ci } 2633af6ab5fSopenharmony_ci } 2643af6ab5fSopenharmony_ci 2653af6ab5fSopenharmony_ci explicit TypeStackElement(Checker *checker, void *element, std::string_view err, const lexer::SourcePosition &pos) 2663af6ab5fSopenharmony_ci : checker_(checker), element_(element), hasErrorChecker_(false) 2673af6ab5fSopenharmony_ci { 2683af6ab5fSopenharmony_ci if (!checker->typeStack_.insert(element).second) { 2693af6ab5fSopenharmony_ci checker_->LogTypeError(err, pos); 2703af6ab5fSopenharmony_ci element_ = nullptr; 2713af6ab5fSopenharmony_ci } 2723af6ab5fSopenharmony_ci } 2733af6ab5fSopenharmony_ci 2743af6ab5fSopenharmony_ci bool HasTypeError() 2753af6ab5fSopenharmony_ci { 2763af6ab5fSopenharmony_ci hasErrorChecker_ = true; 2773af6ab5fSopenharmony_ci return element_ == nullptr; 2783af6ab5fSopenharmony_ci } 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci ~TypeStackElement() 2813af6ab5fSopenharmony_ci { 2823af6ab5fSopenharmony_ci ASSERT(hasErrorChecker_); 2833af6ab5fSopenharmony_ci if (element_ != nullptr) { 2843af6ab5fSopenharmony_ci checker_->typeStack_.erase(element_); 2853af6ab5fSopenharmony_ci } 2863af6ab5fSopenharmony_ci } 2873af6ab5fSopenharmony_ci 2883af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(TypeStackElement); 2893af6ab5fSopenharmony_ci NO_MOVE_SEMANTIC(TypeStackElement); 2903af6ab5fSopenharmony_ci 2913af6ab5fSopenharmony_ciprivate: 2923af6ab5fSopenharmony_ci Checker *checker_; 2933af6ab5fSopenharmony_ci void *element_; 2943af6ab5fSopenharmony_ci bool hasErrorChecker_; 2953af6ab5fSopenharmony_ci}; 2963af6ab5fSopenharmony_ci 2973af6ab5fSopenharmony_ciclass ScopeContext { 2983af6ab5fSopenharmony_cipublic: 2993af6ab5fSopenharmony_ci explicit ScopeContext(Checker *checker, varbinder::Scope *newScope) 3003af6ab5fSopenharmony_ci : checker_(checker), prevScope_(checker_->scope_) 3013af6ab5fSopenharmony_ci { 3023af6ab5fSopenharmony_ci checker_->scope_ = newScope; 3033af6ab5fSopenharmony_ci } 3043af6ab5fSopenharmony_ci 3053af6ab5fSopenharmony_ci ~ScopeContext() 3063af6ab5fSopenharmony_ci { 3073af6ab5fSopenharmony_ci checker_->scope_ = prevScope_; 3083af6ab5fSopenharmony_ci } 3093af6ab5fSopenharmony_ci 3103af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(ScopeContext); 3113af6ab5fSopenharmony_ci NO_MOVE_SEMANTIC(ScopeContext); 3123af6ab5fSopenharmony_ci 3133af6ab5fSopenharmony_ciprivate: 3143af6ab5fSopenharmony_ci Checker *checker_; 3153af6ab5fSopenharmony_ci varbinder::Scope *prevScope_; 3163af6ab5fSopenharmony_ci}; 3173af6ab5fSopenharmony_ci 3183af6ab5fSopenharmony_ciclass SavedCheckerContext { 3193af6ab5fSopenharmony_cipublic: 3203af6ab5fSopenharmony_ci explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus) 3213af6ab5fSopenharmony_ci : SavedCheckerContext(checker, newStatus, nullptr) 3223af6ab5fSopenharmony_ci { 3233af6ab5fSopenharmony_ci } 3243af6ab5fSopenharmony_ci 3253af6ab5fSopenharmony_ci explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus, const ETSObjectType *containingClass) 3263af6ab5fSopenharmony_ci : SavedCheckerContext(checker, newStatus, containingClass, nullptr) 3273af6ab5fSopenharmony_ci { 3283af6ab5fSopenharmony_ci } 3293af6ab5fSopenharmony_ci 3303af6ab5fSopenharmony_ci explicit SavedCheckerContext(Checker *checker, CheckerStatus newStatus, const ETSObjectType *containingClass, 3313af6ab5fSopenharmony_ci Signature *containingSignature) 3323af6ab5fSopenharmony_ci : checker_(checker), prev_(checker->context_) 3333af6ab5fSopenharmony_ci { 3343af6ab5fSopenharmony_ci const bool inExternal = checker->HasStatus(CheckerStatus::IN_EXTERNAL); 3353af6ab5fSopenharmony_ci checker_->context_ = CheckerContext(checker, newStatus, containingClass, containingSignature); 3363af6ab5fSopenharmony_ci if (inExternal) { 3373af6ab5fSopenharmony_ci // handled here instead of at call sites to make things more foolproof 3383af6ab5fSopenharmony_ci checker_->context_.Status() |= CheckerStatus::IN_EXTERNAL; 3393af6ab5fSopenharmony_ci } 3403af6ab5fSopenharmony_ci } 3413af6ab5fSopenharmony_ci 3423af6ab5fSopenharmony_ci NO_COPY_SEMANTIC(SavedCheckerContext); 3433af6ab5fSopenharmony_ci DEFAULT_MOVE_SEMANTIC(SavedCheckerContext); 3443af6ab5fSopenharmony_ci 3453af6ab5fSopenharmony_ci ~SavedCheckerContext() 3463af6ab5fSopenharmony_ci { 3473af6ab5fSopenharmony_ci checker_->context_ = prev_; 3483af6ab5fSopenharmony_ci } 3493af6ab5fSopenharmony_ci 3503af6ab5fSopenharmony_ciprivate: 3513af6ab5fSopenharmony_ci Checker *checker_; 3523af6ab5fSopenharmony_ci CheckerContext prev_; 3533af6ab5fSopenharmony_ci}; 3543af6ab5fSopenharmony_ci 3553af6ab5fSopenharmony_ci} // namespace ark::es2panda::checker 3563af6ab5fSopenharmony_ci 3573af6ab5fSopenharmony_ci#endif /* CHECKER_H */ 358