mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Empty default case in @jump switch does not fallthrough #2147.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
- Incorrect parsing of call attributes #2144.
|
||||
- Error when using named argument on trailing macro body expansion #2139.
|
||||
- Designated const initializers with `{}` would overwrite the parent field.
|
||||
- Empty default case in @jump switch does not fallthrough #2147.
|
||||
|
||||
### Stdlib changes
|
||||
- Added `String.quick_ztr` and `String.is_zstr`
|
||||
|
||||
@@ -825,17 +825,27 @@ static void llvm_emit_switch_jump_table(GenContext *c,
|
||||
Int max = { .type = TYPE_VOID };
|
||||
int min_index = -1;
|
||||
int default_index = -1;
|
||||
bool last_was_default = false;
|
||||
LLVMBasicBlockRef default_block = exit_block;
|
||||
for (unsigned i = 0; i < case_count; i++)
|
||||
{
|
||||
Ast *case_ast = cases[i];
|
||||
if (case_ast->ast_kind == AST_DEFAULT_STMT)
|
||||
{
|
||||
if (!case_ast->case_stmt.body) continue;
|
||||
default_block = case_ast->case_stmt.backend_block;
|
||||
default_index = i;
|
||||
if (!case_ast->case_stmt.body)
|
||||
{
|
||||
last_was_default = true;
|
||||
continue;
|
||||
}
|
||||
default_block = case_ast->case_stmt.backend_block;
|
||||
continue;
|
||||
}
|
||||
if (last_was_default && case_ast->case_stmt.body)
|
||||
{
|
||||
default_block = case_ast->case_stmt.backend_block;
|
||||
last_was_default = false;
|
||||
}
|
||||
Int value, to_value;
|
||||
llvm_set_jump_table_values(case_ast->case_stmt.expr, case_ast->case_stmt.to_expr, &value, &to_value);
|
||||
if (min.type == TYPE_VOID)
|
||||
|
||||
106
test/test_suite/switch/jump_bug_default.c3t
Normal file
106
test/test_suite/switch/jump_bug_default.c3t
Normal file
@@ -0,0 +1,106 @@
|
||||
// #target: macos-aarch64
|
||||
module test;
|
||||
import std;
|
||||
|
||||
fn int main(String[] args)
|
||||
{
|
||||
switch (1) @jump
|
||||
{
|
||||
default:
|
||||
case 3:
|
||||
io::printn("Hello");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @test.main([2 x i64] %0) #0 {
|
||||
entry:
|
||||
%args = alloca %"char[][]", align 8
|
||||
%switch = alloca i32, align 4
|
||||
%len = alloca i64, align 8
|
||||
%error_var = alloca i64, align 8
|
||||
%retparam = alloca i64, align 8
|
||||
%taddr = alloca %"char[]", align 8
|
||||
%error_var2 = alloca i64, align 8
|
||||
%error_var8 = alloca i64, align 8
|
||||
store [2 x i64] %0, ptr %args, align 8
|
||||
store i32 1, ptr %switch, align 4
|
||||
br label %switch.entry
|
||||
|
||||
switch.entry: ; preds = %entry
|
||||
%1 = load i32, ptr %switch, align 4
|
||||
%2 = sub i32 %1, 3
|
||||
%3 = icmp ugt i32 %2, 0
|
||||
br i1 %3, label %switch.case, label %jumpblock
|
||||
|
||||
jumpblock: ; preds = %switch.entry
|
||||
%ptroffset = getelementptr inbounds [8 x i8], ptr @jumptable, i32 %2
|
||||
%target = load ptr, ptr %ptroffset, align 8
|
||||
indirectbr ptr %target, [label %switch.case]
|
||||
|
||||
switch.case: ; preds = %jumpblock, %switch.entry
|
||||
%4 = call ptr @std.io.stdout()
|
||||
store %"char[]" { ptr @.str, i64 5 }, ptr %taddr, align 8
|
||||
%5 = load [2 x i64], ptr %taddr, align 8
|
||||
%6 = call i64 @std.io.File.write(ptr %retparam, ptr %4, [2 x i64] %5)
|
||||
%not_err = icmp eq i64 %6, 0
|
||||
%7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %7, label %after_check, label %assign_optional
|
||||
|
||||
assign_optional: ; preds = %switch.case
|
||||
store i64 %6, ptr %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
after_check: ; preds = %switch.case
|
||||
br label %noerr_block
|
||||
|
||||
guard_block: ; preds = %assign_optional
|
||||
br label %voiderr
|
||||
|
||||
noerr_block: ; preds = %after_check
|
||||
%8 = load i64, ptr %retparam, align 8
|
||||
store i64 %8, ptr %len, align 8
|
||||
%9 = call i64 @std.io.File.write_byte(ptr %4, i8 10)
|
||||
%not_err3 = icmp eq i64 %9, 0
|
||||
%10 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true)
|
||||
br i1 %10, label %after_check5, label %assign_optional4
|
||||
|
||||
assign_optional4: ; preds = %noerr_block
|
||||
store i64 %9, ptr %error_var2, align 8
|
||||
br label %guard_block6
|
||||
|
||||
after_check5: ; preds = %noerr_block
|
||||
br label %noerr_block7
|
||||
|
||||
guard_block6: ; preds = %assign_optional4
|
||||
br label %voiderr
|
||||
|
||||
noerr_block7: ; preds = %after_check5
|
||||
%11 = call i64 @std.io.File.flush(ptr %4)
|
||||
%not_err9 = icmp eq i64 %11, 0
|
||||
%12 = call i1 @llvm.expect.i1(i1 %not_err9, i1 true)
|
||||
br i1 %12, label %after_check11, label %assign_optional10
|
||||
|
||||
assign_optional10: ; preds = %noerr_block7
|
||||
store i64 %11, ptr %error_var8, align 8
|
||||
br label %guard_block12
|
||||
|
||||
after_check11: ; preds = %noerr_block7
|
||||
br label %noerr_block13
|
||||
|
||||
guard_block12: ; preds = %assign_optional10
|
||||
br label %voiderr
|
||||
|
||||
noerr_block13: ; preds = %after_check11
|
||||
%13 = load i64, ptr %len, align 8
|
||||
%add = add i64 %13, 1
|
||||
br label %voiderr
|
||||
|
||||
voiderr: ; preds = %noerr_block13, %guard_block12, %guard_block6, %guard_block
|
||||
br label %switch.exit
|
||||
|
||||
switch.exit: ; preds = %voiderr
|
||||
ret i32 0
|
||||
}
|
||||
Reference in New Issue
Block a user