From adc3dffddfb5ed9f92d5d787d253688c8990db8f Mon Sep 17 00:00:00 2001 From: shawn_hu_ls Date: Sat, 19 Nov 2022 03:00:37 +0800 Subject: [PATCH] Fix es2abc nobody function coredump in emitter Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I61ZQ3?from=project-issue Signed-off-by: shawn_hu_ls --- es2panda/ir/base/classDefinition.cpp | 5 + es2panda/ir/base/methodDefinition.cpp | 1 + es2panda/ir/base/methodDefinition.h | 5 + es2panda/parser/parserImpl.cpp | 59 ++++++++ es2panda/parser/parserImpl.h | 1 + es2panda/parser/statementParser.cpp | 2 +- .../test/compiler/dts/test-dts-1-expected.txt | 0 es2panda/test/compiler/dts/test-dts-1.d.ts | 19 +++ .../classes/test-ts-classes-9-expected.txt | 1 + .../conformance/classes/test-ts-classes-9.ts | 28 ++++ ...test-export-named-declaration-expected.txt | 139 ++++++++++++++++++ .../test-export-named-declaration.d.ts | 17 +++ ...est-export-named-declaration1-expected.txt | 1 + .../test-export-named-declaration1.d.ts | 17 +++ .../test-expression-statement-expected.txt | 1 + .../test-expression-statement.d.ts | 17 +++ ...-namespace-export-declaration-expected.txt | 38 ++--- .../test-namespace-export-declaration.d.ts | 1 + .../ts/test-class-definition-expected.txt | 1 + .../ts/test-class-definiton18-expected.txt | 1 + es2panda/test/runner.py | 5 +- 21 files changed, 338 insertions(+), 21 deletions(-) create mode 100644 es2panda/test/compiler/dts/test-dts-1-expected.txt create mode 100644 es2panda/test/compiler/dts/test-dts-1.d.ts create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9-expected.txt create mode 100644 es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9.ts create mode 100644 es2panda/test/parser/ts/cases/declaration/test-export-named-declaration-expected.txt create mode 100644 es2panda/test/parser/ts/cases/declaration/test-export-named-declaration.d.ts create mode 100644 es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1-expected.txt create mode 100644 es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1.d.ts create mode 100644 es2panda/test/parser/ts/cases/declaration/test-expression-statement-expected.txt create mode 100644 es2panda/test/parser/ts/cases/declaration/test-expression-statement.d.ts diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index ed8938dd01..c86648d2e6 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -155,6 +155,11 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti break; } + if (prop->IsAbstract()) { + compiled.Set(i); + continue; + } + util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); compiler::LiteralBuffer *literalBuf = prop->IsStatic() ? &staticBuf : buf; auto &nameMap = prop->IsStatic() ? staticPropNameMap : propNameMap; diff --git a/es2panda/ir/base/methodDefinition.cpp b/es2panda/ir/base/methodDefinition.cpp index 3975b528ca..25c6ab407c 100644 --- a/es2panda/ir/base/methodDefinition.cpp +++ b/es2panda/ir/base/methodDefinition.cpp @@ -79,6 +79,7 @@ void MethodDefinition::Dump(ir::AstDumper *dumper) const {"key", key_}, {"kind", kind}, {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(modifiers_))}, + {"abstract", AstDumper::Optional((modifiers_ & ModifierFlags::ABSTRACT) != 0)}, {"static", (modifiers_ & ModifierFlags::STATIC) != 0}, {"optional", (modifiers_ & ModifierFlags::OPTIONAL) != 0}, {"computed", isComputed_}, diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index ff51e020bf..1d3a1e2efa 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -91,6 +91,11 @@ public: return isComputed_; } + bool IsAbstract() const + { + return (modifiers_ & ModifierFlags::ABSTRACT) != 0; + } + bool IsStatic() const { return (modifiers_ & ModifierFlags::STATIC) != 0; diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 908c246cd9..c411dbefc6 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -45,9 +45,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -66,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -169,6 +172,10 @@ void ParserImpl::ParseProgram(ScriptKind kind) lexer_->NextToken(); auto statements = ParseStatementList(StatementParsingFlags::STMT_GLOBAL_LEXICAL); + if (IsDtsFile() && !CheckTopStatementsForRequiredDeclare(statements)) { + ThrowSyntaxError( + "Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier."); + } auto *blockStmt = AllocNode(Binder()->GetScope(), std::move(statements)); Binder()->GetScope()->BindNode(blockStmt); @@ -177,6 +184,58 @@ void ParserImpl::ParseProgram(ScriptKind kind) program_.SetAst(blockStmt); } +bool ParserImpl::CheckTopStatementsForRequiredDeclare(const ArenaVector &statements) +{ + for (auto *statement : statements) { + switch (statement->Type()) { + case ir::AstNodeType::TS_INTERFACE_DECLARATION: + case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: + case ir::AstNodeType::IMPORT_DECLARATION: + case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION: + case ir::AstNodeType::EXPORT_ALL_DECLARATION: + case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: + case ir::AstNodeType::EXPORT_NAMED_DECLARATION: + case ir::AstNodeType::TS_NAMESPACE_EXPORT_DECLARATION: + continue; + case ir::AstNodeType::CLASS_DECLARATION: { + if (!statement->AsClassDeclaration()->Definition()->Declare()) { + return false; + } + break; + } + case ir::AstNodeType::FUNCTION_DECLARATION: { + if (!statement->AsFunctionDeclaration()->Function()->Declare() && + !statement->AsFunctionDeclaration()->Function()->IsOverload()) { + return false; + } + break; + } + case ir::AstNodeType::VARIABLE_DECLARATION: { + if (!statement->AsVariableDeclaration()->Declare()) { + return false; + } + break; + } + case ir::AstNodeType::TS_MODULE_DECLARATION: { + if (!statement->AsTSModuleDeclaration()->Declare()) { + return false; + } + break; + } + case ir::AstNodeType::TS_ENUM_DECLARATION: { + if (!statement->AsTSEnumDeclaration()->IsDeclare()) { + return false; + } + break; + } + default: + ThrowSyntaxError("Statements are not allowed in ambient contexts."); + UNREACHABLE(); + } + } + return true; +} + /* * Definitions of private methods */ diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 7b50fd675c..03288da0b3 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -228,6 +228,7 @@ private: void AddCommonjsParams(ArenaVector ¶ms); void AddCommonjsArgs(ArenaVector &args); void ParseProgram(ScriptKind kind); + bool CheckTopStatementsForRequiredDeclare(const ArenaVector &statements); static ExpressionParseFlags CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry); static ExpressionParseFlags CarryPatternFlags(ExpressionParseFlags flags); bool CurrentIsBasicType(); diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index b9c73c0ad8..3ab35b02e0 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -2512,7 +2512,7 @@ ir::ExportNamedDeclaration *ParserImpl::ParseNamedExportDeclaration(const lexer: break; } case lexer::TokenType::KEYW_CLASS: { - decl = ParseClassDeclaration(true, std::move(decorators), isDeclare, false, !isTsModule); + decl = ParseClassDeclaration(true, std::move(decorators), isDeclare || IsDtsFile(), false, !isTsModule); break; } case lexer::TokenType::LITERAL_IDENT: { diff --git a/es2panda/test/compiler/dts/test-dts-1-expected.txt b/es2panda/test/compiler/dts/test-dts-1-expected.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/es2panda/test/compiler/dts/test-dts-1.d.ts b/es2panda/test/compiler/dts/test-dts-1.d.ts new file mode 100644 index 0000000000..dfe041495d --- /dev/null +++ b/es2panda/test/compiler/dts/test-dts-1.d.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export class A { + test() : number; +} diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9-expected.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9.ts new file mode 100644 index 0000000000..a61da3518a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-9.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +abstract class A { + abstract test() : number; +} + +class B extends A { + test() : number { + return 1; + } +} + +var b : A = new B(); +print(b.test()); diff --git a/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration-expected.txt b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration-expected.txt new file mode 100644 index 0000000000..9eaa59407c --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration-expected.txt @@ -0,0 +1,139 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ExportNamedDeclaration", + "declaration": { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "A", + "loc": { + "start": { + "line": 17, + "column": 14 + }, + "end": { + "line": 17, + "column": 15 + } + } + }, + "superClass": null, + "implements": [], + "constructor": { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "constructor", + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "constructor", + "static": false, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": null, + "generator": false, + "async": false, + "expression": false, + "params": [], + "declare": true, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "body": [], + "indexSignatures": [], + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "source": null, + "specifiers": [], + "loc": { + "start": { + "line": 17, + "column": 1 + }, + "end": { + "line": 17, + "column": 18 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration.d.ts b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration.d.ts new file mode 100644 index 0000000000..415c0cea6c --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +export class A {} diff --git a/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1-expected.txt b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1-expected.txt new file mode 100644 index 0000000000..275199decf --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1-expected.txt @@ -0,0 +1 @@ +SyntaxError: Top-level declarations in .d.ts files must start with either a 'declare' or 'export' modifier. [test-export-named-declaration1.d.ts:18:1] diff --git a/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1.d.ts b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1.d.ts new file mode 100644 index 0000000000..0238c3ad34 --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-export-named-declaration1.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class A {} diff --git a/es2panda/test/parser/ts/cases/declaration/test-expression-statement-expected.txt b/es2panda/test/parser/ts/cases/declaration/test-expression-statement-expected.txt new file mode 100644 index 0000000000..ca757c3654 --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-expression-statement-expected.txt @@ -0,0 +1 @@ +SyntaxError: Statements are not allowed in ambient contexts. [test-expression-statement.d.ts:18:1] diff --git a/es2panda/test/parser/ts/cases/declaration/test-expression-statement.d.ts b/es2panda/test/parser/ts/cases/declaration/test-expression-statement.d.ts new file mode 100644 index 0000000000..859b55cb81 --- /dev/null +++ b/es2panda/test/parser/ts/cases/declaration/test-expression-statement.d.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +print(1) diff --git a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt index 09e146d85d..d9d6beb4ed 100644 --- a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt +++ b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration-expected.txt @@ -12,11 +12,11 @@ "name": "isPrime", "loc": { "start": { - "line": 16, + "line": 17, "column": 17 }, "end": { - "line": 16, + "line": 17, "column": 24 } } @@ -32,22 +32,22 @@ "type": "TSNumberKeyword", "loc": { "start": { - "line": 16, + "line": 17, "column": 28 }, "end": { - "line": 16, + "line": 17, "column": 34 } } }, "loc": { "start": { - "line": 16, + "line": 17, "column": 25 }, "end": { - "line": 16, + "line": 17, "column": 26 } } @@ -57,33 +57,33 @@ "type": "TSBooleanKeyword", "loc": { "start": { - "line": 16, + "line": 17, "column": 37 }, "end": { - "line": 16, + "line": 17, "column": 44 } } }, "loc": { "start": { - "line": 16, + "line": 17, "column": 8 }, "end": { - "line": 16, + "line": 17, "column": 45 } } }, "loc": { "start": { - "line": 16, + "line": 17, "column": 8 }, "end": { - "line": 16, + "line": 17, "column": 45 } } @@ -92,11 +92,11 @@ "specifiers": [], "loc": { "start": { - "line": 16, + "line": 17, "column": 1 }, "end": { - "line": 16, + "line": 17, "column": 45 } } @@ -108,22 +108,22 @@ "name": "mathLib", "loc": { "start": { - "line": 17, + "line": 18, "column": 21 }, "end": { - "line": 17, + "line": 18, "column": 28 } } }, "loc": { "start": { - "line": 17, + "line": 18, "column": 1 }, "end": { - "line": 17, + "line": 18, "column": 29 } } @@ -135,7 +135,7 @@ "column": 1 }, "end": { - "line": 17, + "line": 18, "column": 29 } } diff --git a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts index 79d7ad4637..54b6d5bd2e 100644 --- a/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts +++ b/es2panda/test/parser/ts/cases/declaration/test-namespace-export-declaration.d.ts @@ -13,5 +13,6 @@ * limitations under the License. */ + export function isPrime(x: number): boolean; export as namespace mathLib; \ No newline at end of file diff --git a/es2panda/test/parser/ts/test-class-definition-expected.txt b/es2panda/test/parser/ts/test-class-definition-expected.txt index 4380377952..2e0056d63b 100644 --- a/es2panda/test/parser/ts/test-class-definition-expected.txt +++ b/es2panda/test/parser/ts/test-class-definition-expected.txt @@ -2118,6 +2118,7 @@ } }, "kind": "method", + "abstract": true, "static": false, "optional": false, "computed": false, diff --git a/es2panda/test/parser/ts/test-class-definiton18-expected.txt b/es2panda/test/parser/ts/test-class-definiton18-expected.txt index ccc182e09e..05ccf9db3b 100644 --- a/es2panda/test/parser/ts/test-class-definiton18-expected.txt +++ b/es2panda/test/parser/ts/test-class-definiton18-expected.txt @@ -180,6 +180,7 @@ } }, "kind": "method", + "abstract": true, "static": false, "optional": false, "computed": false, diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 20ed0d8f18..8515d2e4e4 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -148,7 +148,9 @@ class Test: self.reproduce += "\n" + ' '.join(cmd) def get_path_to_expected(self): - return "%s-expected.txt" % (path.splitext(self.path)[0]) + if self.path.find(".d.ts") == -1: + return "%s-expected.txt" % (path.splitext(self.path)[0]) + return "%s-expected.txt" % (self.path[:self.path.find(".d.ts")]) def run(self, runner): cmd = runner.cmd_prefix + [runner.es2panda, "--dump-ast"] @@ -869,6 +871,7 @@ def main(): runner = CompilerRunner(args) runner.add_directory("compiler/js", "js", []) runner.add_directory("compiler/ts", "ts", ["--extension=ts"]) + runner.add_directory("compiler/dts", "d.ts", ["--module", "--extension=ts"]) runners.append(runner) -- Gitee