mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Corrected ptr->bool conversion. Avoid checking function body if function is invalid. Switch defer test cases.
This commit is contained in:
committed by
Christoffer Lerno
parent
c839eb50c8
commit
90ab4f07b9
@@ -2,6 +2,7 @@ module bar;
|
||||
import baz;
|
||||
import gen;
|
||||
|
||||
|
||||
typedef int as Bob;
|
||||
/*
|
||||
macro namespaceFor(ns; void(int i) $body)
|
||||
@@ -103,21 +104,6 @@ enum EnumTestOverflowAfter
|
||||
|
||||
|
||||
|
||||
enum Inf
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = 10000
|
||||
}
|
||||
|
||||
enum Inf2 : byte
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = 129,
|
||||
}
|
||||
|
||||
typedef Inf as BooInf;
|
||||
|
||||
|
||||
struct TestStruct
|
||||
@@ -201,8 +187,8 @@ func void testUnion()
|
||||
|
||||
SimpleUnion y = s = { 2 };
|
||||
double yval = SimpleUnion{ f = 3.333 }.f;
|
||||
printf("Union y: %d\n" as y.a);
|
||||
printf("Union simple: %f\n" as yval);
|
||||
printf("Union y: %d\n", y.a);
|
||||
printf("Union simple: %f\n", yval);
|
||||
}
|
||||
|
||||
func TestStruct2 structTest(int i)
|
||||
@@ -216,31 +202,6 @@ func TestStruct2 structTest(int i)
|
||||
return bar2;
|
||||
}
|
||||
|
||||
func void enumInferenceTest()
|
||||
{
|
||||
Inf x = Inf.A;
|
||||
x = BooInf.B;
|
||||
x = A;
|
||||
int x1 = 0;
|
||||
bool y = x1 == x1;
|
||||
Inf2 z = C;
|
||||
if (z == Inf2.A) return;
|
||||
if (z == 1) return;
|
||||
z = 2;
|
||||
switch (z)
|
||||
{
|
||||
case Inf2.A:
|
||||
x1++;
|
||||
return;
|
||||
case B:
|
||||
return;
|
||||
case 111:
|
||||
x1 += 1;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
func void switchTest()
|
||||
{
|
||||
@@ -288,78 +249,8 @@ func int! borok()
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
func void testNoReturn()
|
||||
{
|
||||
int i = 0;
|
||||
i = -i;
|
||||
}
|
||||
|
||||
func int testReturn()
|
||||
{
|
||||
int i = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
func int testReturnWithOtherAtEnd()
|
||||
{
|
||||
int i = 0;
|
||||
return i;
|
||||
if (i == 10) i++;
|
||||
i = i + 2;
|
||||
}
|
||||
|
||||
func int testReturnWithConditional()
|
||||
{
|
||||
int i = 0;
|
||||
if (i > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
/*
|
||||
func int testReturnWithCondThrow() throws Error
|
||||
{
|
||||
int i = 0;
|
||||
if (i > 0)
|
||||
{
|
||||
throw Error.NO_SUCH_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Error.NO_SUCH_FILE;
|
||||
}
|
||||
}
|
||||
*/
|
||||
func int testReturnSwitch()
|
||||
{
|
||||
int i = 0;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 3:
|
||||
case 1:
|
||||
return 2;
|
||||
case 2:
|
||||
return 3;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func int barok() throws Error as OtherError
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
throw Error.NO_SUCH_FILE;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
*/
|
||||
|
||||
struct SimpleStruct
|
||||
{
|
||||
@@ -373,11 +264,11 @@ struct SimpleStruct
|
||||
func void testSimpleStruct(int x)
|
||||
{
|
||||
SimpleStruct snoinit;
|
||||
SimpleStruct sinit = { b = 1 as d = 3.0, z1 = 1 };
|
||||
SimpleStruct sinit = { b = 1, d = 3.0, z1 = 1 };
|
||||
sinit.a = 1;
|
||||
sinit.b = 2;
|
||||
printf("Testing:\n");
|
||||
printf("a = %d, b = %d (2), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1 as int) as cast(sinit.z2 as int));
|
||||
printf("a = %d, b = %d (2), c = %f, d = %f (3.0), z1 = %d (1), z2 = %d\n", sinit.a, sinit.b, sinit.c, sinit.d, cast(sinit.z1 as int), cast(sinit.z2 as int));
|
||||
if (sinit.a != 1) printf("ERROR a\n");
|
||||
if (sinit.b != 2) printf("ERROR b\n");
|
||||
if (sinit.d != 3.0) printf("ERROR d\n");
|
||||
@@ -388,7 +279,7 @@ func void testSimpleStruct(int x)
|
||||
snoinit.c = 2.0;
|
||||
snoinit.z1 = 1;
|
||||
snoinit.z2 = 2;
|
||||
printf("b = %d (1) as d = %f (3.0) as z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1);
|
||||
printf("b = %d (1), d = %f (3.0), z1 = %d (1)\n", snoinit.b, snoinit.d, snoinit.z1);
|
||||
if (snoinit.b != 1) printf("ERROR b\n");
|
||||
if (snoinit.d != 3.0) printf("ERROR d\n");
|
||||
if (snoinit.z1 != 1) printf("ERROR z1\n");
|
||||
@@ -506,19 +397,6 @@ func int boba(int y, int j)
|
||||
//Test3 xc = { eo = 1, t.a = 1 };
|
||||
// throw Error.NO_SUCH_FILE;
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
|
||||
}
|
||||
for (int i = 0, int foo = 0; i < 10; i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0, j = 1; i < 10; i++, j++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Test2 bar;
|
||||
bar.b = 1;
|
||||
@@ -563,10 +441,7 @@ func int test(int x = 100)
|
||||
return y;
|
||||
}
|
||||
|
||||
func int* elvis(int *x, int *y)
|
||||
{
|
||||
return x ?: y;
|
||||
}
|
||||
|
||||
|
||||
func int test3()
|
||||
{
|
||||
@@ -749,22 +624,7 @@ func int! testThrow1()
|
||||
{
|
||||
return TestErr1!;
|
||||
}
|
||||
/*
|
||||
func void syntaxErrors()
|
||||
{
|
||||
int! i = 0;
|
||||
while (i + 1) {}
|
||||
if (i + 1) {}
|
||||
for (int x = i;;) {}
|
||||
for (int x = 0; x < i + 1;) {}
|
||||
for (int x = 0; x < 10; x += i + 1) {}
|
||||
switch (i + 1)
|
||||
{
|
||||
default:
|
||||
i + 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func int frob(int i)
|
||||
{
|
||||
@@ -830,7 +690,7 @@ func void! testAllErrors()
|
||||
printf("Fex: %d\n", fex.x);
|
||||
error test33 = fex;
|
||||
FooErr fex2 = cast(test33 as FooErr);
|
||||
printf("Fex2: %d\n" as fex.x);
|
||||
printf("Fex2: %d\n", fex.x);
|
||||
TestErr1 eok = TestErr1{};
|
||||
error e = eok;
|
||||
catch (err = x)
|
||||
@@ -1070,22 +930,7 @@ func void testArray()
|
||||
}
|
||||
|
||||
}
|
||||
func void testBreak1()
|
||||
{
|
||||
for FOO: (int i = 0; i < 10; i++)
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
for BAR: (int k = 0; k < 10; k++)
|
||||
{
|
||||
printf("%d %d %d\n", i, j, k);
|
||||
continue FOO;
|
||||
}
|
||||
printf("ERROR\n");
|
||||
}
|
||||
printf("ERROR\n");
|
||||
}
|
||||
}
|
||||
|
||||
func void testDefer()
|
||||
{
|
||||
printf("1 == %d\n", testReturnDefer());
|
||||
@@ -1372,8 +1217,13 @@ public func int! decode(char[] infile, byte[] out)
|
||||
*/
|
||||
func int main(int x)
|
||||
{
|
||||
|
||||
int[3] feok2 = { 1, 8, 100};
|
||||
int[] feok = &feok2;
|
||||
printf("Feok: %d\n", feok[0]);
|
||||
printf("Feok: %d\n", feok[1]);
|
||||
printf("Len: %d", feok.len);
|
||||
baz::runBaz();
|
||||
testBreak();
|
||||
show();
|
||||
testMacros();
|
||||
testTypeof();
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
module arithmetics;
|
||||
|
||||
func void testAdd(int a, int b)
|
||||
{
|
||||
a = a + b;
|
||||
a = a +% b;
|
||||
a +%= b;
|
||||
a += b;
|
||||
a += 1;
|
||||
a +%= 1;
|
||||
}
|
||||
|
||||
func void testSub(int a, int b)
|
||||
{
|
||||
a = a - b;
|
||||
a = a -% b;
|
||||
a -%= b;
|
||||
a -= b;
|
||||
a -%= 1;
|
||||
a -= 1;
|
||||
}
|
||||
|
||||
func void testMult(int a, int b)
|
||||
{
|
||||
a = a * b;
|
||||
a = a *% b;
|
||||
a *%= b;
|
||||
/*a *= b;
|
||||
a *%= 1;
|
||||
a *= 1;*/
|
||||
}
|
||||
|
||||
func void testDiv(int a, int b)
|
||||
{
|
||||
a = a / b;
|
||||
a /= b;
|
||||
a /= 1;
|
||||
}
|
||||
@@ -294,7 +294,7 @@ LLVMValueRef gencontext_emit_cast(GenContext *context, CastKind cast_kind, LLVMV
|
||||
case CAST_EUBOOL:
|
||||
return LLVMBuildICmp(context->builder, LLVMIntNE, value, gencontext_emit_no_error_union(context), "eubool");
|
||||
case CAST_PTRBOOL:
|
||||
return LLVMBuildICmp(context->builder, LLVMIntNE, value, LLVMConstPointerNull(llvm_type(from_type->canonical)), "ptrbool");
|
||||
return LLVMBuildIsNotNull(context->builder, value, "ptrbool");
|
||||
case CAST_BOOLINT:
|
||||
return LLVMBuildTrunc(context->builder, value, llvm_type(to_type), "boolsi");
|
||||
case CAST_FPBOOL:
|
||||
|
||||
@@ -333,7 +333,7 @@ static inline bool sema_analyse_declare_stmt(Context *context, Ast *statement)
|
||||
if (decl->var.unwrap && !decl->var.init_expr->failable)
|
||||
{
|
||||
SEMA_ERROR(decl->var.init_expr, "A failable expression was expected here.");
|
||||
return false;
|
||||
return decl_poison(decl);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1316,6 +1316,7 @@ bool sema_analyse_statement(Context *context, Ast *statement)
|
||||
|
||||
bool sema_analyse_function_body(Context *context, Decl *func)
|
||||
{
|
||||
if (!decl_ok(func)) return false;
|
||||
FunctionSignature *signature = &func->func.function_signature;
|
||||
context->active_function_for_analysis = func;
|
||||
context->rtype = signature->rtype->type;
|
||||
|
||||
14
test/test_suite/errors/illegal_use_of_failable.c3
Normal file
14
test/test_suite/errors/illegal_use_of_failable.c3
Normal file
@@ -0,0 +1,14 @@
|
||||
func void syntaxErrors()
|
||||
{
|
||||
int! i = 0;
|
||||
while (i + 1) {} // #error: 'int!' cannot be converted into 'bool'
|
||||
if (i + 1) {} // #error: 'int!' cannot be converted into 'bool'
|
||||
for (int x = i;;) {} // #error: 'int!' cannot be implicitly cast to 'int'.
|
||||
for (int x = 0; x < i + 1;) {} // #error: 'bool!' cannot be implicitly cast to 'bool'
|
||||
for (int x = 0; x < 10; x += i + 1) {} // #error: 'int!' cannot be implicitly cast to 'int'
|
||||
switch (i + 1) // #error: 'int!' cannot be converted into 'int'
|
||||
{
|
||||
default:
|
||||
i + 1;
|
||||
}
|
||||
}
|
||||
45
test/test_suite/expressions/elvis.c3t
Normal file
45
test/test_suite/expressions/elvis.c3t
Normal file
@@ -0,0 +1,45 @@
|
||||
func int* elvis(int *x, int *y)
|
||||
{
|
||||
return x ?: y;
|
||||
}
|
||||
|
||||
func int* elvis2(int *x, int *y)
|
||||
{
|
||||
return x ?: (y ?: x);
|
||||
}
|
||||
|
||||
// #expect: elvis.ll
|
||||
|
||||
store i32* %0, i32** %x
|
||||
store i32* %1, i32** %y
|
||||
%2 = load i32*, i32** %x
|
||||
%ptrbool = icmp ne i32* %2, null
|
||||
br i1 %ptrbool, label %cond.phi, label %cond.rhs
|
||||
cond.rhs:
|
||||
%3 = load i32*, i32** %y
|
||||
br label %cond.phi
|
||||
cond.phi:
|
||||
%val = phi i32* [ %2, %entry ], [ %3, %cond.rhs ]
|
||||
ret i32* %val
|
||||
|
||||
store i32* %0, i32** %x
|
||||
store i32* %1, i32** %y
|
||||
%2 = load i32*, i32** %x
|
||||
%ptrbool = icmp ne i32* %2, null
|
||||
br i1 %ptrbool, label %cond.phi3, label %cond.rhs
|
||||
cond.rhs:
|
||||
%3 = load i32*, i32** %y
|
||||
%ptrbool1 = icmp ne i32* %3, null
|
||||
br i1 %ptrbool1, label %cond.phi, label %cond.rhs2
|
||||
|
||||
cond.rhs2:
|
||||
%4 = load i32*, i32** %x
|
||||
br label %cond.phi
|
||||
|
||||
cond.phi:
|
||||
%val = phi i32* [ %3, %cond.rhs ], [ %4, %cond.rhs2 ]
|
||||
br label %cond.phi3
|
||||
|
||||
cond.phi3:
|
||||
%val4 = phi i32* [ %2, %entry ], [ %val, %cond.phi ]
|
||||
ret i32* %val4
|
||||
12
test/test_suite/statements/conditional_return.c3
Normal file
12
test/test_suite/statements/conditional_return.c3
Normal file
@@ -0,0 +1,12 @@
|
||||
func int testReturnWithConditional()
|
||||
{
|
||||
int i = 0;
|
||||
if (i > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
49
test/test_suite/statements/defer_break_switch.c3t
Normal file
49
test/test_suite/statements/defer_break_switch.c3t
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
func void test1()
|
||||
{}
|
||||
|
||||
func void test2()
|
||||
{}
|
||||
|
||||
func void test(int i)
|
||||
{
|
||||
bool b = true;
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
defer test2();
|
||||
if (b) break;
|
||||
test1();
|
||||
case 2:
|
||||
test1();
|
||||
}
|
||||
}
|
||||
|
||||
// #expect: defer_break_switch.ll
|
||||
|
||||
switch.case:
|
||||
%4 = load i1, i1* %b
|
||||
br i1 %4, label %if.then, label %if.exit
|
||||
|
||||
if.then:
|
||||
call void @defer_break_switch.test2()
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
br label %switch.exit
|
||||
|
||||
if.exit:
|
||||
call void @defer_break_switch.test1()
|
||||
call void @defer_break_switch.test2()
|
||||
br label %exit1
|
||||
|
||||
exit1:
|
||||
br label %switch.exit
|
||||
|
||||
switch.case2:
|
||||
call void @defer_break_switch.test1()
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit:
|
||||
ret void
|
||||
}
|
||||
49
test/test_suite/statements/defer_next_switch.c3t
Normal file
49
test/test_suite/statements/defer_next_switch.c3t
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
func void test1()
|
||||
{}
|
||||
|
||||
func void test2()
|
||||
{}
|
||||
|
||||
func void test(int i)
|
||||
{
|
||||
bool b = true;
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
defer test2();
|
||||
if (b) next;
|
||||
test1();
|
||||
case 2:
|
||||
test1();
|
||||
}
|
||||
}
|
||||
|
||||
// #expect: defer_next_switch.ll
|
||||
|
||||
switch.case:
|
||||
%4 = load i1, i1* %b
|
||||
br i1 %4, label %if.then, label %if.exit
|
||||
|
||||
if.then:
|
||||
call void @defer_next_switch.test2()
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
br label %switch.case2
|
||||
|
||||
if.exit:
|
||||
call void @defer_next_switch.test1()
|
||||
call void @defer_next_switch.test2()
|
||||
br label %exit1
|
||||
|
||||
exit1:
|
||||
br label %switch.exit
|
||||
|
||||
switch.case2:
|
||||
call void @defer_next_switch.test1()
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit:
|
||||
ret void
|
||||
}
|
||||
17
test/test_suite/statements/for_with_extra_declarations.c3
Normal file
17
test/test_suite/statements/for_with_extra_declarations.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
func void test()
|
||||
{
|
||||
int j;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
|
||||
}
|
||||
for (int i = 0, int foo = 0; i < 10; i++)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0, j = 1; i < 10; i++, j++)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
35
test/test_suite/statements/labelled_continue_for.c3t
Normal file
35
test/test_suite/statements/labelled_continue_for.c3t
Normal file
@@ -0,0 +1,35 @@
|
||||
func void errored()
|
||||
{}
|
||||
|
||||
func void test() {}
|
||||
|
||||
func void testBreak()
|
||||
{
|
||||
for FOO: (int i = 0; i < 10; i++)
|
||||
{
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
for BAR: (int k = 0; k < 10; k++)
|
||||
{
|
||||
test();
|
||||
continue FOO;
|
||||
}
|
||||
errored();
|
||||
}
|
||||
errored();
|
||||
}
|
||||
}
|
||||
|
||||
// #expect: labelled_continue_for.ll
|
||||
|
||||
for.cond:
|
||||
|
||||
call void @labelled_continue_for.test()
|
||||
br label %for.inc8
|
||||
|
||||
for.inc8:
|
||||
%4 = load i32, i32* %i
|
||||
%add9 = add nsw i32 %4, 1
|
||||
store i32 %add9, i32* %i
|
||||
br label %for.cond
|
||||
|
||||
11
test/test_suite/statements/return_stmt.c3
Normal file
11
test/test_suite/statements/return_stmt.c3
Normal file
@@ -0,0 +1,11 @@
|
||||
func void testNoReturn()
|
||||
{
|
||||
int i = 0;
|
||||
i = -i;
|
||||
}
|
||||
|
||||
func int testReturn()
|
||||
{
|
||||
int i = 0;
|
||||
return i;
|
||||
}
|
||||
36
test/test_suite/statements/return_switch.c3t
Normal file
36
test/test_suite/statements/return_switch.c3t
Normal file
@@ -0,0 +1,36 @@
|
||||
func int testReturnSwitch()
|
||||
{
|
||||
int i = 0;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
case 3:
|
||||
case 1:
|
||||
return 2;
|
||||
case 2:
|
||||
return 3;
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
// #expect: return_switch.ll
|
||||
|
||||
switch.entry:
|
||||
%2 = load i32, i32* %0
|
||||
switch i32 %2, label %switch.default [
|
||||
i32 0, label %switch.case
|
||||
i32 3, label %switch.case
|
||||
i32 1, label %switch.case
|
||||
i32 2, label %switch.case1
|
||||
]
|
||||
|
||||
switch.case:
|
||||
ret i32 2
|
||||
|
||||
switch.case1:
|
||||
ret i32 3
|
||||
|
||||
switch.default:
|
||||
ret i32 4
|
||||
}
|
||||
7
test/test_suite/statements/return_with_other_at_end.c3
Normal file
7
test/test_suite/statements/return_with_other_at_end.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
func int testReturnWithOtherAtEnd()
|
||||
{
|
||||
int i = 0;
|
||||
return i;
|
||||
if (i == 10) i++;
|
||||
i = i + 2;
|
||||
}
|
||||
43
test/test_suite/types/enum_inference.c3
Normal file
43
test/test_suite/types/enum_inference.c3
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
enum Inf
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = 10000
|
||||
}
|
||||
|
||||
enum Inf2 : byte
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C = 129,
|
||||
}
|
||||
|
||||
typedef Inf as BooInf;
|
||||
|
||||
|
||||
func void enumInferenceTest()
|
||||
{
|
||||
Inf x = Inf.A;
|
||||
x = BooInf.B;
|
||||
x = A;
|
||||
int x1 = 0;
|
||||
bool y = x1 == x1;
|
||||
Inf2 z = C;
|
||||
if (z == Inf2.A) return;
|
||||
if (z == 1) return;
|
||||
z = 2;
|
||||
switch (z)
|
||||
{
|
||||
case Inf2.A:
|
||||
x1++;
|
||||
return;
|
||||
case B:
|
||||
return;
|
||||
case 111:
|
||||
x1 += 1;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
9
test/test_suite/types/recursive_typedef.c3
Normal file
9
test/test_suite/types/recursive_typedef.c3
Normal file
@@ -0,0 +1,9 @@
|
||||
typedef Number1 as Number2; // #error: Recursive definition of 'Number2'
|
||||
typedef Number2 as Number1;
|
||||
|
||||
typedef Number as Number; // #error: Recursive definition of 'Number'
|
||||
|
||||
|
||||
typedef Loop as Loop2; // #error: Recursive definition of 'Loop2'
|
||||
typedef Loop2 as Loop3;
|
||||
typedef Loop3 as Loop;
|
||||
@@ -9,9 +9,3 @@ func void test1()
|
||||
int d = a; // #error: cast 'Arr' (int[4]) to 'int'
|
||||
}
|
||||
|
||||
typedef Number1 as Number2; // #error: Recursive definition of 'Number2'
|
||||
typedef Number2 as Number1;
|
||||
|
||||
typedef Number as Number; // #error: Recursive definition of 'Number'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user