Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion tslang/lib/TypeScript/MLIRGenClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2099,8 +2099,19 @@ genContext);

auto location = loc(classMember);

auto accessLevel = getAccessLevel(classMember);
auto accessLevel = getAccessLevel(classMember);
auto funcLikeDeclaration = classMember.as<FunctionLikeDeclarationBase>();

// an overload signature of a method or a constructor, as for a function: the implementation
// that follows it is the member
auto isAmbientMember = newClassPtr->isDeclaration || newClassPtr->isImport
|| (classMember->flags & NodeFlags::Ambient) == NodeFlags::Ambient;
if (!funcLikeDeclaration->body && !classMethodMemberInfo.isAbstract && !isAmbientMember
&& (classMember == SyntaxKind::MethodDeclaration || classMember == SyntaxKind::Constructor))
{
return mlir::success();
}

if (mlir::failed(getMethodNameOrPropertyName(
newClassPtr->isStatic,
funcLikeDeclaration,
Expand Down
10 changes: 10 additions & 0 deletions tslang/lib/TypeScript/MLIRGenFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,16 @@ namespace mlirgen

mlir::LogicalResult MLIRGenImpl::mlirGen(FunctionDeclaration functionDeclarationAST, const GenContext &genContext)
{
// Outside an ambient context (`declare`, a .d.ts) a function without a body is an overload
// signature, and the implementation that follows it is the function. Registering the
// signature too made the implementation take its parameter list.
auto isAmbient = (functionDeclarationAST->flags & NodeFlags::Ambient) == NodeFlags::Ambient
|| hasModifier(functionDeclarationAST, SyntaxKind::DeclareKeyword);
if (!functionDeclarationAST->body && !isAmbient)
{
return mlir::success();
}

auto funcGenContext = GenContext(genContext);
funcGenContext.clearScopeVars();
// declaring function which is nested and object should not have this context (unless it is part of object declaration)
Expand Down
3 changes: 3 additions & 0 deletions tslang/test/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ tslang_add_test(NAME test-compile-00-global-const-object-method COMMAND test-run
tslang_add_test(NAME test-compile-00-funcs COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs.ts")
tslang_add_test(NAME test-compile-00-funcs-capture COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs_capture.ts")
tslang_add_test(NAME test-compile-00-funcs-vararg COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs_vararg.ts")
tslang_add_test(NAME test-compile-00-function-overloads COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00function_overloads.ts")
tslang_add_test(NAME test-compile-01-funcs-vararg COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/01funcs_vararg.ts")
# printf is avaliable in JIT only, C has snprintf
#tslang_add_test(NAME test-compile-02-funcs-vararg COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/02funcs_vararg.ts")
Expand Down Expand Up @@ -716,6 +717,7 @@ tslang_add_test(NAME test-jit-00-global-const-object-method COMMAND test-runner
tslang_add_test(NAME test-jit-00-funcs COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs.ts")
tslang_add_test(NAME test-jit-00-funcs-capture COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs_capture.ts")
tslang_add_test(NAME test-jit-00-funcs-vararg COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs_vararg.ts")
tslang_add_test(NAME test-jit-00-function-overloads COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00function_overloads.ts")
tslang_add_test(NAME test-jit-01-funcs-vararg COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/01funcs_vararg.ts")
tslang_add_test(NAME test-jit-02-funcs-vararg COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/02funcs_vararg.ts")
tslang_add_test(NAME test-jit-00-funcs-bindings COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00funcs_bindings.ts")
Expand Down Expand Up @@ -1634,6 +1636,7 @@ set(TSLANG_CORPUS
00funcs_typed_generic_iterator.ts
00funcs_typeless_function_as_generic.ts
00funcs_vararg.ts
00function_overloads.ts
00funcs.ts
00generator_manual_next.ts
00generator_manual_next2.ts
Expand Down
99 changes: 99 additions & 0 deletions tslang/test/tester/tests/00function_overloads.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Overload signatures: the body-less signatures are types only, and the implementation that
// follows is the one function. Registering a signature as a function crashed the compiler (#343).

function f(a: number): number;
function f(a: number, b: number): number;
function f(a: number, b?: number) {
return b === undefined ? a : a + b;
}

function g(s: string): string;
function g(n: number): string;
function g(x: string | number): string {
return typeof x === "string" ? "s" : "n";
}

// signatures that are never called still compile
function unused(a: number): number;
function unused(a: number, b: number): number;
function unused(a: number, b?: number) {
return a;
}

namespace NS {
export function h(a: number): number;
export function h(a: number, b: number): number;
export function h(a: number, b?: number) {
return b === undefined ? a : a * b;
}
}

function outer() {
function inner(a: number): number;
function inner(a: number, b: number): number;
function inner(a: number, b?: number) {
return b === undefined ? -a : a - b;
}

return inner(1) + inner(5, 2);
}

class C {
k: number;

constructor();
constructor(k: number);
constructor(k?: number) {
this.k = k === undefined ? 10 : k;
}

m(a: number): number;
m(a: number, b: number): number;
m(a: number, b?: number) {
return (b === undefined ? a : a + b) * this.k;
}

static s(a: number): number;
static s(a: number, b: number): number;
static s(a: number, b?: number) {
return b === undefined ? a : a - b;
}
}

abstract class Base {
abstract get(): number;

twice() {
return this.get() * 2;
}
}

class Impl extends Base {
get(): number;
get(scale: number): number;
get(scale?: number) {
return scale === undefined ? 3 : 3 * scale;
}
}

function main() {
assert(f(1) == 1);
assert(f(1, 2) == 3);
assert(g("a") == "s");
assert(g(1) == "n");
assert(NS.h(5) == 5);
assert(NS.h(5, 2) == 10);
assert(outer() == 2);

const c = new C();
const c2 = new C(2);
assert(c.m(1) == 10);
assert(c2.m(1, 2) == 6);
assert(C.s(5) == 5);
assert(C.s(5, 2) == 3);

const b: Base = new Impl();
assert(b.twice() == 6);

print("done.");
}
Loading