diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 8884209deeb53ba3a8b4dd0b72fc0040d12aa4f8..8082d9d9227c09e3983084d3c80db3e70be71a37 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1830,7 +1830,8 @@ checker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::S funcReturnType = returnTypeAnnotation->GetType(checker); if (st->argument_ == nullptr) { - if (!funcReturnType->IsETSVoidType() && funcReturnType != checker->GlobalVoidType()) { + if (!funcReturnType->IsETSVoidType() && funcReturnType != checker->GlobalVoidType() && + !funcReturnType->IsETSAsyncFuncReturnType()) { checker->ThrowTypeError("Missing return value.", st->Start()); } funcReturnType = checker->GlobalVoidType(); @@ -1857,10 +1858,13 @@ checker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::S } else { // Case when function's return type should be inferred from return statement(s): if (containingFunc->Signature()->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { - InferReturnType(checker, containingFunc, funcReturnType, st->argument_); + InferReturnType(checker, containingFunc, funcReturnType, + st->argument_); // This removes the NEED_RETURN_TYPE flag, so only the first return + // statement going to land here... } else { // All subsequent return statements: - ProcessReturnStatements(checker, containingFunc, funcReturnType, st, st->argument_); + ProcessReturnStatements(checker, containingFunc, funcReturnType, st, + st->argument_); // and the remaining return statements will get processed here. } } @@ -1888,6 +1892,11 @@ checker::Type *ETSAnalyzer::Check(ir::ReturnStatement *st) const } st->returnType_ = GetFunctionReturnType(st, containingFunc); + + if (containingFunc->ReturnTypeAnnotation() == nullptr) { + containingFunc->AddReturnStatement(st); + } + return nullptr; } diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index bc4ac968a0b6d7ab69d3d169fc245beb543726b4..d4bfbcc30cb9b187ca2314cd392c7d398afc41ad 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -111,11 +111,10 @@ void DoBodyTypeChecking(ETSChecker *checker, ir::MethodDefinition *node, ir::Scr scriptFunc->Body()->Check(checker); - // In case of inferred function's return type set it forcedly to all return statements; - if (scriptFunc->Signature()->HasSignatureFlag(checker::SignatureFlags::INFERRED_RETURN_TYPE) && - scriptFunc->ReturnTypeAnnotation() == nullptr && scriptFunc->Body() != nullptr && - scriptFunc->Body()->IsStatement()) { - scriptFunc->Body()->AsStatement()->SetReturnType(checker, scriptFunc->Signature()->ReturnType()); + if (scriptFunc->ReturnTypeAnnotation() == nullptr) { + for (auto &returnStatement : scriptFunc->ReturnStatements()) { + returnStatement->SetReturnType(checker, scriptFunc->Signature()->ReturnType()); + } } checker->Context().SetContainingSignature(nullptr); diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index 80ac4bd6982c1020830426c4b35b220fed99bd33..aa88bf411fcfefed43a1c8ac51e350ae89ef947d 100644 --- a/ets2panda/checker/ets/dynamic.cpp +++ b/ets2panda/checker/ets/dynamic.cpp @@ -129,10 +129,11 @@ ir::ScriptFunction *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *calle params.push_back(param); info->params.push_back(param->Ident()->Variable()->AsLocalVariable()); } - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + + auto funcSignature = ir::FunctionSignature(nullptr, std::move(params), nullptr); auto *func = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), nullptr), nullptr, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::NONE}); + Allocator(), ir::ScriptFunction::ScriptFunctionData {nullptr, std::move(funcSignature), + ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::NONE}); func->SetScope(scope); scope->BindNode(func); @@ -268,23 +269,28 @@ std::pair ETSChecker::CreateScriptFuncti body->SetScope(scope); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) id = AllocNode(compiler::Signatures::CCTOR, Allocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto signature = ir::FunctionSignature(nullptr, std::move(params), nullptr); + // clang-format off func = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::STATIC_BLOCK | - ir::ScriptFunctionFlags::EXPRESSION, - ir::ModifierFlags::STATIC}); + Allocator(), ir::ScriptFunction::ScriptFunctionData { + body, + std::move(signature), + ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::EXPRESSION, + ir::ModifierFlags::STATIC, + }); + // clang-format on } else { builder(scope, &statements, ¶ms); auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) id = AllocNode(compiler::Signatures::CTOR, Allocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto funcSignature = ir::FunctionSignature(nullptr, std::move(params), nullptr); func = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData { - ir::ScriptFunctionFlags::CONSTRUCTOR | ir::ScriptFunctionFlags::EXPRESSION, ir::ModifierFlags::PUBLIC}); + Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(funcSignature), + ir::ScriptFunctionFlags::CONSTRUCTOR | + ir::ScriptFunctionFlags::EXPRESSION, + ir::ModifierFlags::PUBLIC}); } func->SetScope(scope); @@ -578,10 +584,11 @@ ir::MethodDefinition *ETSChecker::CreateClassMethod(varbinder::ClassScope *class // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + + auto funcSignature = ir::FunctionSignature(nullptr, std::move(params), nullptr); auto *func = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, modifierFlags}); + Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(funcSignature), + ir::ScriptFunctionFlags::METHOD, modifierFlags}); func->SetScope(scope); scope->BindNode(func); diff --git a/ets2panda/checker/ets/enum.cpp b/ets2panda/checker/ets/enum.cpp index 771ab0d6f2427984e4e0280e14602062efda0ddd..206035f1ab3524cb5ec9f2dfa88448f4e92b848e 100644 --- a/ets2panda/checker/ets/enum.cpp +++ b/ets2panda/checker/ets/enum.cpp @@ -162,9 +162,12 @@ template flags |= ir::ModifierFlags::DECLARE; } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + // clang-format off auto *const function = checker->AllocNode( - ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), bodyBlock, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, flags, isDeclare}); + checker->Allocator(), ir::ScriptFunction::ScriptFunctionData { + bodyBlock, ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation), + ir::ScriptFunctionFlags::METHOD, flags, isDeclare}); + // clang-format on function->SetScope(functionScope); varbinder->AsETSBinder()->BuildInternalName(function); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index ad7093bf74455d8555cc2fc40495811f8bfff915..340dab4fc49ab2f0497e4445ed047375c8bd9148 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1930,8 +1930,10 @@ ir::ScriptFunction *ETSChecker::CreateProxyFunc(ir::ArrowFunctionExpression *lam } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *func = Allocator()->New( - ir::FunctionSignature(nullptr, std::move(params), lambda->Function()->ReturnTypeAnnotation()), body, - ir::ScriptFunction::ScriptFunctionData {funcFlags, GetFlagsForProxyLambda(isStatic)}); + Allocator(), + ir::ScriptFunction::ScriptFunctionData { + body, ir::FunctionSignature(nullptr, std::move(params), lambda->Function()->ReturnTypeAnnotation()), + funcFlags, GetFlagsForProxyLambda(isStatic)}); func->SetScope(scope); if (!func->IsAsyncFunc()) { @@ -2223,10 +2225,10 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(ArenaVector(Allocator(), std::move(statements)); body->SetScope(scope); - auto *func = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::CONSTRUCTOR}); + auto *func = AllocNode( + Allocator(), + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::CONSTRUCTOR}); func->SetScope(scope); // Set the scopes @@ -2419,10 +2421,10 @@ ir::MethodDefinition *ETSChecker::CreateLambdaImplicitCtor(const lexer::SourceRa // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(scope); - auto *func = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::CONSTRUCTOR}); + auto *func = AllocNode( + Allocator(), + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::CONSTRUCTOR}); func->SetScope(scope); // Bind the scopes scope->BindNode(func); @@ -2491,8 +2493,9 @@ ir::MethodDefinition *ETSChecker::CreateLambdaInvokeProto(util::StringView invok body->SetScope(scope); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *func = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC}); + Allocator(), + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC}); func->SetScope(scope); scope->BindNode(func); @@ -3000,9 +3003,11 @@ ir::MethodDefinition *ETSChecker::CreateMethod(const util::StringView &name, ir: auto *nameId = AllocNode(name, Allocator()); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *scope = VarBinder()->Allocator()->New(Allocator(), paramScope); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *const func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), returnType), - body, ir::ScriptFunction::ScriptFunctionData {flags, modifiers}); + // clang-format off + auto *const func = AllocNode( + Allocator(), ir::ScriptFunction::ScriptFunctionData { + body, ir::FunctionSignature(nullptr, std::move(params), returnType), flags, modifiers}); + // clang-format on func->SetScope(scope); func->SetIdent(nameId); if (body != nullptr && body->IsBlockStatement()) { @@ -3113,10 +3118,10 @@ void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr) } ArenaVector params(Allocator()->Adapter()); - auto *funcNode = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), trailingBlock, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::ARROW}); + auto *funcNode = AllocNode( + Allocator(), ir::ScriptFunction::ScriptFunctionData {trailingBlock, + ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::ARROW}); funcNode->SetScope(funcScope); funcScope->BindNode(funcNode); funcParamScope->BindNode(funcNode); @@ -3144,10 +3149,10 @@ ArenaVector ETSChecker::ExtendArgumentsWithFakeLamda(ir::CallE auto *body = AllocNode(Allocator(), std::move(statements)); body->SetScope(funcScope); - auto *funcNode = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::ARROW}); + auto *funcNode = AllocNode( + Allocator(), + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::ARROW}); funcNode->SetScope(funcScope); funcScope->BindNode(funcNode); auto *arrowFuncNode = AllocNode(Allocator(), funcNode); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 3ec818dcc75b05e7613fff394cb4c2d5fcbffd0a..c45a3c923e1c50ab7333107b4f6c8d1a930bb044 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -2837,10 +2837,10 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty auto *body = checker->AllocNode(checker->Allocator(), std::move(stmts)); auto funcFlags = isSetter ? ir::ScriptFunctionFlags::SETTER : ir::ScriptFunctionFlags::GETTER; auto *const returnTypeAnn = isSetter ? nullptr : field->TypeAnnotation()->Clone(checker->Allocator(), nullptr); - auto *func = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - checker->AllocNode(ir::FunctionSignature(nullptr, std::move(params), returnTypeAnn), body, - ir::ScriptFunction::ScriptFunctionData {funcFlags, flags, true}); + auto *func = checker->AllocNode( + checker->Allocator(), + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), returnTypeAnn), + funcFlags, flags, true}); func->SetRange(field->Range()); func->SetScope(functionScope); diff --git a/ets2panda/compiler/lowering/ets/defaultParameterLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParameterLowering.cpp index 880682ea72285aea7dcb118eb9baa3cb41bf5427..1da70f9e68e585a6040362b1d8e61809e381a0da 100644 --- a/ets2panda/compiler/lowering/ets/defaultParameterLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParameterLowering.cpp @@ -210,8 +210,11 @@ ir::FunctionExpression *DefaultParameterLowering::CreateFunctionExpression( ir::AstNode *body = CreateFunctionBody(method, ctx, std::move(funcCallArgs)); - auto *funcNode = checker->AllocNode(std::move(signature), body, method->Function()->Flags(), - false, method->Function()->Language()); + auto *funcNode = checker->AllocNode( + checker->Allocator(), + ir::ScriptFunction::ScriptFunctionData { + body, std::move(signature), method->Function()->Flags(), {}, false, method->Function()->Language()}); + body->SetParent(funcNode); funcNode->AddModifier(method->Function()->Modifiers()); funcNode->SetRange({startLoc, endLoc}); diff --git a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp index e5fb7fee43d2675ac437e2ff6744f972fd066ddd..53e8181d14b5b8e19a8af644ea25b03822904168 100644 --- a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp @@ -100,12 +100,12 @@ static ir::MethodDefinition *GenerateGetterOrSetter(checker::ETSChecker *const c auto signature = ir::FunctionSignature(nullptr, std::move(params), isSetter ? nullptr : field->TypeAnnotation()); - auto *func = isSetter ? checker->AllocNode( - std::move(signature), nullptr, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::SETTER, flags, true}) - : checker->AllocNode( - std::move(signature), nullptr, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::GETTER, flags, true}); + auto *func = checker->AllocNode( + checker->Allocator(), ir::ScriptFunction::ScriptFunctionData {nullptr, std::move(signature), + isSetter ? ir::ScriptFunctionFlags::SETTER + : ir::ScriptFunctionFlags::GETTER, + flags, true}); + func->SetRange(field->Range()); func->SetScope(functionScope); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index 66c8ff2453e5eb0e24ebdbabf6b47c2e2b8b18f5..e8a5d5e635c3992b2f28dfc455f78950a07f2925 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -88,9 +88,12 @@ ir::MethodDefinition *GlobalClassHandler::CreateInitMethod() ArenaVector statements(allocator_->Adapter()); auto *initBody = NodeAllocator::Alloc(allocator_, allocator_, std::move(statements)); - auto *initFunc = - NodeAllocator::Alloc(allocator_, ir::FunctionSignature(nullptr, std::move(params), nullptr), - initBody, functionFlags, false, Language(Language::Id::ETS)); + auto funcSignature = ir::FunctionSignature(nullptr, std::move(params), nullptr); + + auto *initFunc = NodeAllocator::Alloc( + allocator_, allocator_, + ir::ScriptFunction::ScriptFunctionData { + initBody, std::move(funcSignature), functionFlags, {}, false, Language(Language::Id::ETS)}); initFunc->SetIdent(initIdent); initFunc->AddModifier(functionModifiers); @@ -162,9 +165,11 @@ ir::ClassStaticBlock *GlobalClassHandler::CreateCCtor(const ArenaVector(allocator_, allocator_, std::move(statements)); auto *func = NodeAllocator::Alloc( - allocator_, ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData {ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::HIDDEN, + allocator_, allocator_, + ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::STATIC_BLOCK | ir::ScriptFunctionFlags::HIDDEN, ir::ModifierFlags::STATIC, false, Language(Language::Id::ETS)}); + func->SetIdent(id); auto *funcExpr = NodeAllocator::Alloc(allocator_, func); diff --git a/ets2panda/ir/base/scriptFunction.cpp b/ets2panda/ir/base/scriptFunction.cpp index 3292f45dac8cdd8696783c6545b11703d6f0d4e8..ee693836604b71b63f2fbbd1d1b86d9fdf1d0d10 100644 --- a/ets2panda/ir/base/scriptFunction.cpp +++ b/ets2panda/ir/base/scriptFunction.cpp @@ -23,13 +23,14 @@ namespace ark::es2panda::ir { -ScriptFunction::ScriptFunction(FunctionSignature &&signature, AstNode *body, ScriptFunctionData &&data) +ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data) : AstNode(AstNodeType::SCRIPT_FUNCTION, data.flags), - irSignature_(std::move(signature)), - body_(body), + irSignature_(std::move(data.signature)), + body_(data.body), funcFlags_(data.funcFlags), declare_(data.declare), - lang_(data.lang) + lang_(data.lang), + returnStatements_(allocator->Adapter()) { for (auto *param : irSignature_.Params()) { param->SetParent(this); diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index 6101c12aeb256f8c599b2f698d4136493ac3da84..9dcf2884ef2ab92d54c7052378af19f66124ba0c 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_PARSER_INCLUDE_AST_SCRIPT_FUNCTION_H #define ES2PANDA_PARSER_INCLUDE_AST_SCRIPT_FUNCTION_H +#include "ir/statements/returnStatement.h" #include "ir/astNode.h" #include "varbinder/scope.h" #include "util/enumbitops.h" @@ -38,6 +39,8 @@ class ScriptFunction : public AstNode { public: // Need to reduce the number of constructor parameters to pass OHOS CI code check struct ScriptFunctionData { + AstNode *body = nullptr; + FunctionSignature &&signature; ir::ScriptFunctionFlags funcFlags = ir::ScriptFunctionFlags::NONE; ir::ModifierFlags flags = ir::ModifierFlags::NONE; bool declare = false; @@ -50,13 +53,7 @@ public: NO_COPY_SEMANTIC(ScriptFunction); NO_MOVE_SEMANTIC(ScriptFunction); - explicit ScriptFunction(FunctionSignature &&signature, AstNode *body, ScriptFunctionData &&data); - - explicit ScriptFunction(FunctionSignature &&signature, AstNode *body, ir::ScriptFunctionFlags funcFlags, - bool declare, Language lang) - : ScriptFunction(std::move(signature), body, {funcFlags, {}, declare, lang}) - { - } + explicit ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data); [[nodiscard]] const Identifier *Id() const noexcept { @@ -88,6 +85,16 @@ public: return irSignature_.Params(); } + const ArenaVector &ReturnStatements() const + { + return returnStatements_; + } + + ArenaVector &ReturnStatements() + { + return returnStatements_; + } + [[nodiscard]] const TSTypeParameterDeclaration *TypeParams() const noexcept { return irSignature_.TypeParams(); @@ -108,6 +115,11 @@ public: return body_; } + void AddReturnStatement(ReturnStatement *returnStatement) + { + returnStatements_.push_back(returnStatement); + } + void SetBody(AstNode *body) noexcept { body_ = body; @@ -298,6 +310,7 @@ private: checker::Signature *signature_ {}; bool declare_; es2panda::Language lang_; + ArenaVector returnStatements_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/statements/blockStatement.h b/ets2panda/ir/statements/blockStatement.h index b13c357fc7557061ddcfeed07e993d5c76791246..5d2548470491b2909e6140520b32f056bb149cea 100644 --- a/ets2panda/ir/statements/blockStatement.h +++ b/ets2panda/ir/statements/blockStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -66,14 +66,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - for (auto *statement : statements_) { - if (statement != nullptr) { - statement->SetReturnType(checker, type); - } - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/doWhileStatement.h b/ets2panda/ir/statements/doWhileStatement.h index 2a63bb2731922071ee32a7315143d11db0e79b08..734fa981605b818681ff270044abf05e36d0ba63 100644 --- a/ets2panda/ir/statements/doWhileStatement.h +++ b/ets2panda/ir/statements/doWhileStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -53,12 +53,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/forInStatement.h b/ets2panda/ir/statements/forInStatement.h index 7d8761d602d91ff266583d195e618f2b1eb44382..66dc9ef3743667149af9d9d93ded914386325137 100644 --- a/ets2panda/ir/statements/forInStatement.h +++ b/ets2panda/ir/statements/forInStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -63,12 +63,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/forOfStatement.h b/ets2panda/ir/statements/forOfStatement.h index 5d61f1a80255e8244d3047d926735b24b22c5cde..9a85af45df0e272036165c8a2731e5b40425b3f7 100644 --- a/ets2panda/ir/statements/forOfStatement.h +++ b/ets2panda/ir/statements/forOfStatement.h @@ -89,12 +89,6 @@ public: [[nodiscard]] ForOfStatement *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/forUpdateStatement.h b/ets2panda/ir/statements/forUpdateStatement.h index 5a172f4faf669f4c204b62cfbca642d9cefc66b1..7477d9252ac62791fe22f623a966f24b29a70cb3 100644 --- a/ets2panda/ir/statements/forUpdateStatement.h +++ b/ets2panda/ir/statements/forUpdateStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -73,12 +73,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/ifStatement.h b/ets2panda/ir/statements/ifStatement.h index 3541f32ee2a59b79de018f0409bff8f19babcc7c..328c785f35542aa95c425c2b9907db41ef441795 100644 --- a/ets2panda/ir/statements/ifStatement.h +++ b/ets2panda/ir/statements/ifStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -58,16 +58,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (consequent_ != nullptr) { - consequent_->SetReturnType(checker, type); - } - if (alternate_ != nullptr) { - alternate_->SetReturnType(checker, type); - } - } - void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Dump(ir::SrcDumper *dumper) const override; diff --git a/ets2panda/ir/statements/labelledStatement.cpp b/ets2panda/ir/statements/labelledStatement.cpp index 7f5c185ba5a65fbba356a7c69a92cca0a8c3070a..f0d65e3417f92bb5a56ea2e49d477fe696caca05 100644 --- a/ets2panda/ir/statements/labelledStatement.cpp +++ b/ets2panda/ir/statements/labelledStatement.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/ets2panda/ir/statements/labelledStatement.h b/ets2panda/ir/statements/labelledStatement.h index 82e5fe5cb0f7decd9ba9405c6c91733ddb96fe40..be415785939c6690f7ae38f23f42cbf8a2e03562 100644 --- a/ets2panda/ir/statements/labelledStatement.h +++ b/ets2panda/ir/statements/labelledStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -49,12 +49,6 @@ public: const ir::AstNode *GetReferencedStatement() const; void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/switchCaseStatement.h b/ets2panda/ir/statements/switchCaseStatement.h index a90befde22a1e792332d9e6115f9d41481f2a731..c8bfb6425e76eeb26114f93539e032f045da2ffc 100644 --- a/ets2panda/ir/statements/switchCaseStatement.h +++ b/ets2panda/ir/statements/switchCaseStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -44,14 +44,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - for (auto *statement : consequent_) { - if (statement != nullptr) { - statement->SetReturnType(checker, type); - } - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/switchStatement.cpp b/ets2panda/ir/statements/switchStatement.cpp index 6b0d01ea019fa17aa05d4250badd39a1b537ec43..755d568e257d5809768b3bad6049043d24c8dbdd 100644 --- a/ets2panda/ir/statements/switchStatement.cpp +++ b/ets2panda/ir/statements/switchStatement.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -88,12 +88,4 @@ checker::Type *SwitchStatement::Check(checker::ETSChecker *const checker) return checker->GetAnalyzer()->Check(this); } -void SwitchStatement::SetReturnType(checker::ETSChecker *checker, checker::Type *type) -{ - for (auto *cs : cases_) { - if (cs != nullptr) { - cs->SetReturnType(checker, type); - } - } -} } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/statements/switchStatement.h b/ets2panda/ir/statements/switchStatement.h index fa533dc9562ff3205fe7a59dfa140454a9090894..35eb529644963eeb479354deb6cdf146fca7e3a1 100644 --- a/ets2panda/ir/statements/switchStatement.h +++ b/ets2panda/ir/statements/switchStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -75,7 +75,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/tryStatement.cpp b/ets2panda/ir/statements/tryStatement.cpp index b74000469dfdc07657dc630d394213fd967c23a5..05e79264d67a47b271354e44c1ca030f41932f9a 100644 --- a/ets2panda/ir/statements/tryStatement.cpp +++ b/ets2panda/ir/statements/tryStatement.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -110,18 +110,4 @@ checker::Type *TryStatement::Check([[maybe_unused]] checker::ETSChecker *checker return checker->GetAnalyzer()->Check(this); } -void TryStatement::SetReturnType(checker::ETSChecker *checker, checker::Type *type) -{ - if (block_ != nullptr) { - block_->SetReturnType(checker, type); - } - if (finalizer_ != nullptr) { - finalizer_->SetReturnType(checker, type); - } - for (auto *catchClause : catchClauses_) { - if (catchClause != nullptr) { - catchClause->SetReturnType(checker, type); - } - } -} } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/statements/tryStatement.h b/ets2panda/ir/statements/tryStatement.h index f9b0b5c44092ce6716f1e41ba79e1233e46ff5fa..a861eaf9b17b8c6217d17c91e0da399f50b2936e 100644 --- a/ets2panda/ir/statements/tryStatement.h +++ b/ets2panda/ir/statements/tryStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -83,7 +83,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override; void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/ir/statements/whileStatement.h b/ets2panda/ir/statements/whileStatement.h index f9b00bb98f2009a90ec934f0b526817e092dd581..ddac1e4ea7e7e05ac620f1568aa416e94fce46c5 100644 --- a/ets2panda/ir/statements/whileStatement.h +++ b/ets2panda/ir/statements/whileStatement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -53,12 +53,6 @@ public: } void TransformChildren(const NodeTransformer &cb) override; - void SetReturnType(checker::ETSChecker *checker, checker::Type *type) override - { - if (body_ != nullptr) { - body_->SetReturnType(checker, type); - } - } void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index b2a5cf63c1182fab6148c7aac07d61b17fda9b3a..f35a5d1baaa0bc6511fbfd908f8c958e95c9774e 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -788,8 +788,12 @@ ir::ScriptFunction *ETSParser::ParseFunction(ParserStatus newStatus, ir::Identif } functionContext.AddFlag(throwMarker); - auto *funcNode = AllocNode(std::move(signature), body, functionContext.Flags(), false, - GetContext().GetLanguage()); + // clang-format off + auto *funcNode = AllocNode( + Allocator(), ir::ScriptFunction::ScriptFunctionData { + body, std::move(signature), functionContext.Flags(), {}, false, GetContext().GetLanguage()}); + // clang-format on + funcNode->SetRange({startLoc, endLoc}); return funcNode; @@ -1507,8 +1511,8 @@ ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, i } auto *func = AllocNode( - std::move(signature), body, - ir::ScriptFunction::ScriptFunctionData {functionContext.Flags(), flags, true, GetContext().GetLanguage()}); + Allocator(), ir::ScriptFunction::ScriptFunctionData {body, std::move(signature), functionContext.Flags(), flags, + true, GetContext().GetLanguage()}); if ((flags & ir::ModifierFlags::STATIC) == 0 && body == nullptr) { func->AddModifier(ir::ModifierFlags::ABSTRACT); diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 275f6ca5b824782571911bc7dd422980d0f96cc8..e6a519718b1371604325b42bf2b1b337d567dca4 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -325,9 +325,16 @@ ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowF endLoc = body->End(); } + // clang-format off funcNode = AllocNode( - ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation), body, - arrowFunctionContext->Flags(), false, context_.GetLanguage()); + Allocator(), ir::ScriptFunction::ScriptFunctionData { + body, + ir::FunctionSignature(typeParamDecl, std::move(desc->params), returnTypeAnnotation), + arrowFunctionContext->Flags(), + {}, + false, + context_.GetLanguage()}); + // clang-format on funcNode->SetRange({desc->startLoc, endLoc}); auto *arrowFuncNode = AllocNode(Allocator(), funcNode); diff --git a/ets2panda/parser/parserImpl.cpp b/ets2panda/parser/parserImpl.cpp index 3e147ba831d077c7958f22e3cf6a650c0e428173..e43f19186194e2b10f807757e61aa34d6fb9f835 100644 --- a/ets2panda/parser/parserImpl.cpp +++ b/ets2panda/parser/parserImpl.cpp @@ -570,11 +570,13 @@ ir::ClassElement *ParserImpl::ParseClassStaticBlock() ArenaVector statements = ParseStatementList(); auto *body = AllocNode(Allocator(), std::move(statements)); - auto *func = - AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunction::ScriptFunctionData { - ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK, - ir::ModifierFlags::STATIC, false, context_.GetLanguage()}); + // clang-format off + auto *func = AllocNode( + Allocator(), ir::ScriptFunction::ScriptFunctionData { + body, ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::EXPRESSION | ir::ScriptFunctionFlags::STATIC_BLOCK, + ir::ModifierFlags::STATIC, false, context_.GetLanguage()}); + // clang-format on auto *funcExpr = AllocNode(func); auto *staticBlock = AllocNode(funcExpr, Allocator()); @@ -657,10 +659,14 @@ ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionMo } auto *body = AllocNode(Allocator(), std::move(statements)); - auto *func = AllocNode(ir::FunctionSignature(nullptr, std::move(params), nullptr), body, - ir::ScriptFunctionFlags::CONSTRUCTOR | - ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED, - false, context_.GetLanguage()); + auto *func = AllocNode( + Allocator(), ir::ScriptFunction::ScriptFunctionData {body, + ir::FunctionSignature(nullptr, std::move(params), nullptr), + ir::ScriptFunctionFlags::CONSTRUCTOR | + ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED, + {}, + false, + context_.GetLanguage()}); auto *funcExpr = AllocNode(func); auto *key = AllocNode("constructor", Allocator()); @@ -915,8 +921,10 @@ ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus) } functionContext.AddFlag(throw_marker); - auto *funcNode = AllocNode(std::move(signature), body, functionContext.Flags(), - isDeclare && letDeclare, context_.GetLanguage()); + auto *funcNode = AllocNode( + Allocator(), + ir::ScriptFunction::ScriptFunctionData { + body, std::move(signature), functionContext.Flags(), {}, isDeclare && letDeclare, context_.GetLanguage()}); funcNode->SetRange({startLoc, endLoc}); return funcNode; diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index c8479d029118958bd835aeba3d924609e5ef284a..ae8e853a21288edf2e779b223a670760ef51e63d 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -2012,7 +2012,8 @@ extern "C" es2panda_AstNode *CreateScriptFunction(es2panda_Context *context, es2 ir::FunctionSignature sig(irTypeParams, std::move(irParams), irReturnTypeAnnotation); auto func = allocator->New( - std::move(sig), nullptr, ir::ScriptFunction::ScriptFunctionData {irFunctionFlags, irModifierFlags, isDeclare}); + allocator, + ir::ScriptFunction::ScriptFunctionData {nullptr, std::move(sig), irFunctionFlags, irModifierFlags, isDeclare}); return reinterpret_cast(func); } diff --git a/ets2panda/test/test-lists/parser/parser-js-ignored.txt b/ets2panda/test/test-lists/parser/parser-js-ignored.txt index b626e32de250e1a61fe5522167201ce863aced47..1c178a7f1ebd63d931d19101a6b6ccaf5951d977 100644 --- a/ets2panda/test/test-lists/parser/parser-js-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-js-ignored.txt @@ -104,4 +104,7 @@ compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets # Related to void revert compiler/ets/lambda_infer_type/lambda_cast_infer_type_void.ets + +# panda#15575 compiler/ets/promiseVoid.ets +