diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 8f04fc99e..382d6c9a3 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1060,11 +1060,19 @@ static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *value, */ static void llvm_emit_arr_to_subarray_cast(GenContext *c, BEValue *value, Type *to_type) { - llvm_value_rvalue(c, value); ByteSize size = value->type->pointer->array.len; + LLVMValueRef pointer; Type *array_type = value->type->pointer->array.base; - LLVMTypeRef subarray_type = llvm_get_type(c, to_type); - LLVMValueRef pointer = llvm_emit_bitcast(c, value->value, type_get_ptr(array_type)); + if (size) + { + llvm_value_rvalue(c, value); + LLVMTypeRef subarray_type = llvm_get_type(c, to_type); + pointer = llvm_emit_bitcast(c, value->value, type_get_ptr(array_type)); + } + else + { + pointer = llvm_get_zero(c, type_get_ptr(array_type)); + } LLVMValueRef len = llvm_const_int(c, type_usize, size); llvm_set_aggregate_two(c, value, to_type, pointer, len); } diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index 57a1afba1..87512b5a6 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -527,6 +527,11 @@ static inline Ast *parse_decl_or_expr_stmt(ParseContext *c) { ast->ast_kind = AST_EXPR_STMT; ast->expr_stmt = expr; + if (tok_is(c, TOKEN_IDENT) && expr->expr_kind == EXPR_IDENTIFIER) + { + SEMA_ERROR(expr, "Expected a type here."); + return poisoned_ast; + } } CONSUME_OR_RET(TOKEN_EOS, poisoned_ast); return ast; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 5313e7c2b..928240b8d 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -4579,7 +4579,8 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext { if (external_type->type_kind == TYPE_INFERRED_ARRAY) { - REMINDER("Handle zero size inferred array."); + SEMA_ERROR(expr, "Zero length arrays are not permitted."); + return false; } external_type = sema_type_lower_by_size(external_type, 0); expr->type = external_type; @@ -4632,6 +4633,13 @@ static inline bool sema_expr_analyse_initializer_list(SemaContext *context, Type return sema_expr_analyse_initializer(context, to, assigned, expr); case TYPE_SUBARRAY: { + if (expr->expr_kind == EXPR_INITIALIZER_LIST && !vec_size(expr->initializer_list)) + { + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_POINTER; + expr->type = assigned; + return true; + } // Resolve this as an inferred array. Type *type = type_get_inferred_array(assigned->array.base); if (!sema_expr_analyse_initializer(context, type, type, expr)) return false; diff --git a/src/version.h b/src/version.h index 8a933ede8..67d728340 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.18" \ No newline at end of file +#define COMPILER_VERSION "0.2.19" \ No newline at end of file diff --git a/test/test_suite/errors/error_regression_2.c3t b/test/test_suite/errors/error_regression_2.c3t index c1495b0a7..5b43e14bc 100644 --- a/test/test_suite/errors/error_regression_2.c3t +++ b/test/test_suite/errors/error_regression_2.c3t @@ -419,7 +419,7 @@ if.then27: ; preds = %if.exit21 %53 = bitcast %Head* %literal32 to %"char[]"** store %"char[]"* null, %"char[]"** %53, align 8 %54 = getelementptr inbounds %Head, %Head* %literal32, i32 0, i32 0 - store %"char[]" { i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i32 0, i32 0), i64 0 }, %"char[]"* %value34, align 8 + store %"char[]" zeroinitializer, %"char[]"* %value34, align 8 %55 = call i8* @std_core_mem_alloc(i64 16, i64 0) %ptrptr36 = bitcast i8* %55 to %"char[]"* store %"char[]"* %ptrptr36, %"char[]"** %temp35, align 8 @@ -890,7 +890,7 @@ cond.rhs: ; preds = %loop.body br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %38, %cond.lhs ], [ { i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.21, i32 0, i32 0), i64 0 }, %cond.rhs ] + %val = phi %"char[]" [ %38, %cond.lhs ], [ zeroinitializer, %cond.rhs ] store %"char[]" %val, %"char[]"* %title_sure, align 8 %39 = getelementptr inbounds %"char[]", %"char[]"* %title_sure, i32 0, i32 1 %40 = load i64, i64* %39, align 8 diff --git a/test/test_suite/initializer_lists/general_tests.c3t b/test/test_suite/initializer_lists/general_tests.c3t index 1f90bce5e..13fe0bba3 100644 --- a/test/test_suite/initializer_lists/general_tests.c3t +++ b/test/test_suite/initializer_lists/general_tests.c3t @@ -15,7 +15,6 @@ fn int test() { Baz ffe = { .x = 1 }; int[1] azz = {}; - int[*] a = {}; var $foo = { 11, 22, 33 }; static int foo1 = $foo[1]; int foo2 = $foo[2]; @@ -49,7 +48,6 @@ define i32 @general_tests_test() #0 { entry: %ffe = alloca %Baz, align 8 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %foo2 = alloca i32, align 4 %str = alloca i8*, align 8 %x = alloca i8, align 1 @@ -57,9 +55,7 @@ entry: %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal1 = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal2 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 %0 = bitcast %Baz* %ffe to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %0, i8* align 8 bitcast ({ i32, [4 x i8] }* @.__const to i8*), i32 8, i1 false) @@ -86,17 +82,9 @@ entry: store i32 0, i32* %11, align 4 %12 = bitcast %Baz* %z to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %12, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, [0 x i32]* %literal1, align 4 - %13 = bitcast [0 x i32]* %literal1 to i32* - %14 = insertvalue %"int[]" undef, i32* %13, 0 - %15 = insertvalue %"int[]" %14, i64 0, 1 - store %"int[]" %15, %"int[]"* %sub, align 8 - store [0 x %Bar] zeroinitializer, [0 x %Bar]* %literal2, align 4 - %16 = bitcast [0 x %Bar]* %literal2 to %Bar* - %17 = insertvalue %"Bar[]" undef, %Bar* %16, 0 - %18 = insertvalue %"Bar[]" %17, i64 0, 1 - store %"Bar[]" %18, %"Bar[]"* %foo, align 8 - %19 = bitcast [3 x %Baz]* %baz to i8* - call void @llvm.memset.p0i8.i64(i8* align 16 %19, i8 0, i64 24, i1 false) + store %"int[]" zeroinitializer, %"int[]"* %sub, align 8 + store %"Bar[]" zeroinitializer, %"Bar[]"* %foo, align 8 + %13 = bitcast [3 x %Baz]* %baz to i8* + call void @llvm.memset.p0i8.i64(i8* align 16 %13, i8 0, i64 24, i1 false) ret i32 1 } \ No newline at end of file diff --git a/test/test_suite/initializer_lists/subarrays.c3t b/test/test_suite/initializer_lists/subarrays.c3t index d5351dbca..9696251ad 100644 --- a/test/test_suite/initializer_lists/subarrays.c3t +++ b/test/test_suite/initializer_lists/subarrays.c3t @@ -31,7 +31,6 @@ fn int main() libc::printf("Fofeo second element %d\n", fofeo[1]); Baz ffe = { .x = 1 }; int[1] azz = {}; - int[*] a = {}; //var $foo = { 1, 2, 3 }; bool xy = ! int[] { 1, 2, 3 }; @@ -66,6 +65,7 @@ fn int main() @.str.8 = private unnamed_addr constant [25 x i8] c"Fofeo second element %d\0A\00", align 1 @.__const = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 @.str.9 = private unnamed_addr constant [3 x i8] c"Ok\00", align 1 + ; Function Attrs: nounwind define i32 @main() #0 { entry: @@ -76,15 +76,12 @@ entry: %literal2 = alloca [3 x i32], align 4 %ffe = alloca %Baz, align 8 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %xy = alloca i8, align 1 %literal6 = alloca [3 x i32], align 4 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal8 = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal9 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 %0 = load %Bar*, %Bar** getelementptr inbounds (%"Bar[]", %"Bar[]"* @subarrays_arrbar, i32 0, i32 0), align 8 %ptroffset = getelementptr inbounds %Bar, %Bar* %0, i64 1 @@ -152,9 +149,11 @@ entry: %40 = trunc i8 %39 to i1 %not7 = xor i1 %40, true br i1 %not7, label %if.then, label %if.exit + if.then: ; preds = %entry %41 = call i32 @std_io_println(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.9, i32 0, i32 0)) #3 br label %if.exit + if.exit: ; preds = %if.then, %entry %42 = getelementptr inbounds %Bar, %Bar* %b, i32 0, i32 0 store i32 0, i32* %42, align 4 @@ -162,17 +161,9 @@ if.exit: ; preds = %if.then, %entry store i32 0, i32* %43, align 4 %44 = bitcast %Baz* %z to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %44, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, [0 x i32]* %literal8, align 4 - %45 = bitcast [0 x i32]* %literal8 to i32* - %46 = insertvalue %"int[]" undef, i32* %45, 0 - %47 = insertvalue %"int[]" %46, i64 0, 1 - store %"int[]" %47, %"int[]"* %sub, align 8 - store [0 x %Bar] zeroinitializer, [0 x %Bar]* %literal9, align 4 - %48 = bitcast [0 x %Bar]* %literal9 to %Bar* - %49 = insertvalue %"Bar[]" undef, %Bar* %48, 0 - %50 = insertvalue %"Bar[]" %49, i64 0, 1 - store %"Bar[]" %50, %"Bar[]"* %foo, align 8 - %51 = bitcast [3 x %Baz]* %baz to i8* - call void @llvm.memset.p0i8.i64(i8* align 16 %51, i8 0, i64 24, i1 false) + store %"int[]" zeroinitializer, %"int[]"* %sub, align 8 + store %"Bar[]" zeroinitializer, %"Bar[]"* %foo, align 8 + %45 = bitcast [3 x %Baz]* %baz to i8* + call void @llvm.memset.p0i8.i64(i8* align 16 %45, i8 0, i64 24, i1 false) ret i32 1 } diff --git a/test/test_suite/initializer_lists/zero_inferred_array.c3 b/test/test_suite/initializer_lists/zero_inferred_array.c3 new file mode 100644 index 000000000..91d1492b7 --- /dev/null +++ b/test/test_suite/initializer_lists/zero_inferred_array.c3 @@ -0,0 +1,4 @@ +fn void test() +{ + int[*] a = {}; // #error: Zero length arrays are not permitted. +} \ No newline at end of file diff --git a/test/test_suite/initializer_lists/zero_init.c3t b/test/test_suite/initializer_lists/zero_init.c3t index 4717d3c94..78605540f 100644 --- a/test/test_suite/initializer_lists/zero_init.c3t +++ b/test/test_suite/initializer_lists/zero_init.c3t @@ -20,7 +20,6 @@ fn int test() { Mega m = {}; int[1] azz = {}; - int[*] a = {}; Bar b = {}; Baz z = {}; int[] sub = {}; @@ -39,13 +38,10 @@ define i32 @zero_init_test() #0 { entry: %m = alloca %Mega, align 4 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal1 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 %0 = bitcast %Mega* %m to i8* call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 40, i1 false) @@ -57,17 +53,9 @@ entry: store i32 0, i32* %3, align 4 %4 = bitcast %Baz* %z to i8* call void @llvm.memset.p0i8.i64(i8* align 8 %4, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, [0 x i32]* %literal, align 4 - %5 = bitcast [0 x i32]* %literal to i32* - %6 = insertvalue %"int[]" undef, i32* %5, 0 - %7 = insertvalue %"int[]" %6, i64 0, 1 - store %"int[]" %7, %"int[]"* %sub, align 8 - store [0 x %Bar] zeroinitializer, [0 x %Bar]* %literal1, align 4 - %8 = bitcast [0 x %Bar]* %literal1 to %Bar* - %9 = insertvalue %"Bar[]" undef, %Bar* %8, 0 - %10 = insertvalue %"Bar[]" %9, i64 0, 1 - store %"Bar[]" %10, %"Bar[]"* %foo, align 8 - %11 = bitcast [3 x %Baz]* %baz to i8* - call void @llvm.memset.p0i8.i64(i8* align 16 %11, i8 0, i64 24, i1 false) + store %"int[]" zeroinitializer, %"int[]"* %sub, align 8 + store %"Bar[]" zeroinitializer, %"Bar[]"* %foo, align 8 + %5 = bitcast [3 x %Baz]* %baz to i8* + call void @llvm.memset.p0i8.i64(i8* align 16 %5, i8 0, i64 24, i1 false) ret i32 1 } diff --git a/test/test_suite2/errors/error_regression_2.c3t b/test/test_suite2/errors/error_regression_2.c3t index 74e4b44fb..f82bc2f87 100644 --- a/test/test_suite2/errors/error_regression_2.c3t +++ b/test/test_suite2/errors/error_regression_2.c3t @@ -401,7 +401,7 @@ if.then27: ; preds = %if.exit21 %38 = getelementptr inbounds %Doc, ptr %literal29, i32 0, i32 0 store ptr null, ptr %literal32, align 8 %39 = getelementptr inbounds %Head, ptr %literal32, i32 0, i32 0 - store %"char[]" { ptr @.str.4, i64 0 }, ptr %value34, align 8 + store %"char[]" zeroinitializer, ptr %value34, align 8 %40 = call ptr @std_core_mem_alloc(i64 16, i64 0) store ptr %40, ptr %temp35, align 8 %41 = load ptr, ptr %temp35, align 8 @@ -835,7 +835,7 @@ cond.rhs: ; preds = %loop.body br label %cond.phi cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi %"char[]" [ %29, %cond.lhs ], [ { ptr @.str.21, i64 0 }, %cond.rhs ] + %val = phi %"char[]" [ %29, %cond.lhs ], [ zeroinitializer, %cond.rhs ] store %"char[]" %val, ptr %title_sure, align 8 %30 = getelementptr inbounds %"char[]", ptr %title_sure, i32 0, i32 1 %31 = load i64, ptr %30, align 8 diff --git a/test/test_suite2/initializer_lists/general_tests.c3t b/test/test_suite2/initializer_lists/general_tests.c3t index 8945b7924..0789d91ef 100644 --- a/test/test_suite2/initializer_lists/general_tests.c3t +++ b/test/test_suite2/initializer_lists/general_tests.c3t @@ -15,7 +15,6 @@ fn int test() { Baz ffe = { .x = 1 }; int[1] azz = {}; - int[*] a = {}; var $foo = { 11, 22, 33 }; static int foo1 = $foo[1]; int foo2 = $foo[2]; @@ -49,7 +48,6 @@ define i32 @general_tests_test() #0 { entry: %ffe = alloca %Baz, align 8 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %foo2 = alloca i32, align 4 %str = alloca ptr, align 8 %x = alloca i8, align 1 @@ -57,9 +55,7 @@ entry: %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal1 = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal2 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const, i32 8, i1 false) %0 = getelementptr inbounds [1 x i32], ptr %azz, i64 0, i64 0 @@ -83,14 +79,8 @@ entry: %9 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 store i32 0, ptr %9, align 4 call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, ptr %literal1, align 4 - %10 = insertvalue %"int[]" undef, ptr %literal1, 0 - %11 = insertvalue %"int[]" %10, i64 0, 1 - store %"int[]" %11, ptr %sub, align 8 - store [0 x %Bar] zeroinitializer, ptr %literal2, align 4 - %12 = insertvalue %"Bar[]" undef, ptr %literal2, 0 - %13 = insertvalue %"Bar[]" %12, i64 0, 1 - store %"Bar[]" %13, ptr %foo, align 8 + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, ptr %foo, align 8 call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) ret i32 1 } diff --git a/test/test_suite2/initializer_lists/subarrays.c3t b/test/test_suite2/initializer_lists/subarrays.c3t index dabe00d09..e850895e1 100644 --- a/test/test_suite2/initializer_lists/subarrays.c3t +++ b/test/test_suite2/initializer_lists/subarrays.c3t @@ -31,7 +31,6 @@ fn int main() libc::printf("Fofeo second element %d\n", fofeo[1]); Baz ffe = { .x = 1 }; int[1] azz = {}; - int[*] a = {}; //var $foo = { 1, 2, 3 }; bool xy = ! int[] { 1, 2, 3 }; @@ -76,15 +75,12 @@ entry: %literal2 = alloca [3 x i32], align 4 %ffe = alloca %Baz, align 8 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %xy = alloca i8, align 1 %literal6 = alloca [3 x i32], align 4 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal8 = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal9 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 %0 = load ptr, ptr @subarrays_arrbar, align 8 %ptroffset = getelementptr inbounds %Bar, ptr %0, i64 1 @@ -157,14 +153,8 @@ if.exit: ; preds = %if.then, %entry %38 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 store i32 0, ptr %38, align 4 call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, ptr %literal8, align 4 - %39 = insertvalue %"int[]" undef, ptr %literal8, 0 - %40 = insertvalue %"int[]" %39, i64 0, 1 - store %"int[]" %40, ptr %sub, align 8 - store [0 x %Bar] zeroinitializer, ptr %literal9, align 4 - %41 = insertvalue %"Bar[]" undef, ptr %literal9, 0 - %42 = insertvalue %"Bar[]" %41, i64 0, 1 - store %"Bar[]" %42, ptr %foo, align 8 + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, ptr %foo, align 8 call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) ret i32 1 } diff --git a/test/test_suite2/initializer_lists/zero_inferred_array.c3 b/test/test_suite2/initializer_lists/zero_inferred_array.c3 new file mode 100644 index 000000000..91d1492b7 --- /dev/null +++ b/test/test_suite2/initializer_lists/zero_inferred_array.c3 @@ -0,0 +1,4 @@ +fn void test() +{ + int[*] a = {}; // #error: Zero length arrays are not permitted. +} \ No newline at end of file diff --git a/test/test_suite2/initializer_lists/zero_init.c3t b/test/test_suite2/initializer_lists/zero_init.c3t index f59a1f436..7c6fbf1bc 100644 --- a/test/test_suite2/initializer_lists/zero_init.c3t +++ b/test/test_suite2/initializer_lists/zero_init.c3t @@ -20,7 +20,6 @@ fn int test() { Mega m = {}; int[1] azz = {}; - int[*] a = {}; Bar b = {}; Baz z = {}; int[] sub = {}; @@ -31,7 +30,6 @@ fn int test() /* #expect: zero_init.ll - %Mega = type { [10 x i32] } %Bar = type { i32, i32 } %Baz = type { double } @@ -40,13 +38,10 @@ define i32 @zero_init_test() #0 { entry: %m = alloca %Mega, align 4 %azz = alloca [1 x i32], align 4 - %a = alloca [0 x i32], align 4 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 - %literal = alloca [0 x i32], align 4 %foo = alloca %"Bar[]", align 8 - %literal1 = alloca [0 x %Bar], align 4 %baz = alloca [3 x %Baz], align 16 call void @llvm.memset.p0.i64(ptr align 4 %m, i8 0, i64 40, i1 false) %0 = getelementptr inbounds [1 x i32], ptr %azz, i64 0, i64 0 @@ -56,14 +51,8 @@ entry: %2 = getelementptr inbounds %Bar, ptr %b, i32 0, i32 1 store i32 0, ptr %2, align 4 call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) - store [0 x i32] zeroinitializer, ptr %literal, align 4 - %3 = insertvalue %"int[]" undef, ptr %literal, 0 - %4 = insertvalue %"int[]" %3, i64 0, 1 - store %"int[]" %4, ptr %sub, align 8 - store [0 x %Bar] zeroinitializer, ptr %literal1, align 4 - %5 = insertvalue %"Bar[]" undef, ptr %literal1, 0 - %6 = insertvalue %"Bar[]" %5, i64 0, 1 - store %"Bar[]" %6, ptr %foo, align 8 + store %"int[]" zeroinitializer, ptr %sub, align 8 + store %"Bar[]" zeroinitializer, ptr %foo, align 8 call void @llvm.memset.p0.i64(ptr align 16 %baz, i8 0, i64 24, i1 false) ret i32 1 }