Corrected ptr->bool conversion. Avoid checking function body if function is invalid. Switch defer test cases.

This commit is contained in:
Christoffer Lerno
2020-07-27 14:58:02 +02:00
committed by Christoffer Lerno
parent c839eb50c8
commit 90ab4f07b9
18 changed files with 346 additions and 212 deletions

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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;

View 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;
}
}

View 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

View File

@@ -0,0 +1,12 @@
func int testReturnWithConditional()
{
int i = 0;
if (i > 0)
{
return 1;
}
else
{
return 2;
}
}

View 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
}

View 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
}

View 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++)
{
}
}

View 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

View File

@@ -0,0 +1,11 @@
func void testNoReturn()
{
int i = 0;
i = -i;
}
func int testReturn()
{
int i = 0;
return i;
}

View 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
}

View File

@@ -0,0 +1,7 @@
func int testReturnWithOtherAtEnd()
{
int i = 0;
return i;
if (i == 10) i++;
i = i + 2;
}

View 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;
}
}

View 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;

View File

@@ -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'