mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- Initializer did not correctly handle second rethrow #2870
- Crash encountering panic in if-else style switch #2871
This commit is contained in:
@@ -146,6 +146,8 @@
|
||||
- Converting static "make_slice" to array failed to be handled #2866
|
||||
- Narrowing a not expression was incorrectly handled #2867
|
||||
- Vector shift by optional scalar failed #2868
|
||||
- Initializer did not correctly handle second rethrow #2870
|
||||
- Crash encountering panic in if-else style switch #2871
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
@@ -1727,7 +1727,9 @@ static void llvm_emit_initialize_designated_element(GenContext *c, BEValue *ref,
|
||||
return;
|
||||
}
|
||||
BEValue val;
|
||||
RETURN_ON_EMPTY_BLOCK(ref);
|
||||
llvm_emit_expr(c, &val, expr);
|
||||
RETURN_ON_EMPTY_BLOCK(ref);
|
||||
llvm_store(c, ref, &val);
|
||||
return;
|
||||
}
|
||||
@@ -1884,6 +1886,7 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
||||
{
|
||||
BEValue splat_value;
|
||||
llvm_emit_expr(c, &splat_value, splat);
|
||||
RETURN_ON_EMPTY_BLOCK(ref);
|
||||
llvm_store(c, ref, &splat_value);
|
||||
}
|
||||
else
|
||||
@@ -1897,6 +1900,7 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
||||
DesignatorElement **last_element = designator->designator_expr.path + vec_size(designator->designator_expr.path) - 1;
|
||||
llvm_emit_initialize_designated_element(c, ref, 0, designator->designator_expr.path, last_element,
|
||||
designator->designator_expr.value, NULL);
|
||||
RETURN_ON_EMPTY_BLOCK(ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4622,9 +4626,11 @@ void gencontext_emit_ternary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
|
||||
// Generate condition and conditional branch
|
||||
Expr *cond = exprptr(expr->ternary_expr.cond);
|
||||
llvm_emit_expr(c, value, cond);
|
||||
llvm_value_rvalue(c, value);
|
||||
RETURN_ON_EMPTY_BLOCK(value);
|
||||
if (!llvm_emit_rvalue_in_block(c, value, cond))
|
||||
{
|
||||
llvm_value_set_empty(value);
|
||||
return;
|
||||
}
|
||||
|
||||
Expr *else_expr = exprptr(expr->ternary_expr.else_expr);
|
||||
Expr *then_expr = exprptr(expr->ternary_expr.then_expr);
|
||||
@@ -5877,9 +5883,7 @@ INLINE void llvm_emit_varargs_expr(GenContext *c, BEValue *value_ref, Expr **var
|
||||
BEValue array_ref = llvm_emit_alloca_b(c, array, varargslots_name);
|
||||
FOREACH_IDX(foreach_index, Expr *, val, varargs)
|
||||
{
|
||||
llvm_emit_expr(c, &inner_temp, val);
|
||||
RETURN_ON_EMPTY_BLOCK(value_ref);
|
||||
llvm_value_fold_optional(c, &inner_temp);
|
||||
if (!llvm_emit_folded_in_block(c, &inner_temp, val)) RETURN_EMPTY_BLOCK(value_ref);
|
||||
BEValue slot = llvm_emit_array_gep(c, &array_ref, foreach_index);
|
||||
llvm_store(c, &slot, &inner_temp);
|
||||
}
|
||||
@@ -6001,9 +6005,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
Expr *arg = args[i];
|
||||
if (arg)
|
||||
{
|
||||
llvm_emit_expr(c, value_ref, arg);
|
||||
llvm_value_fold_optional(c, value_ref);
|
||||
RETURN_ON_EMPTY_BLOCK(result_value);
|
||||
if (!llvm_emit_folded_in_block(c, value_ref, arg)) RETURN_EMPTY_BLOCK(result_value);
|
||||
continue;
|
||||
}
|
||||
Decl *decl = sig->params[i];
|
||||
@@ -6029,9 +6031,7 @@ static void llvm_emit_call_expr(GenContext *c, BEValue *result_value, Expr *expr
|
||||
FOREACH_IDX(i, Expr *, vararg, varargs)
|
||||
{
|
||||
BEValue *value_ref = &values[arg_count + i];
|
||||
llvm_emit_expr(c, value_ref, vararg);
|
||||
llvm_value_fold_optional(c, value_ref);
|
||||
RETURN_ON_EMPTY_BLOCK(result_value);
|
||||
if (!llvm_emit_folded_in_block(c, value_ref, vararg)) RETURN_EMPTY_BLOCK(result_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6777,9 +6777,7 @@ static inline void llvm_emit_type_from_any(GenContext *c, BEValue *be_value)
|
||||
static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Expr *inner = exprptr(expr->builtin_access_expr.inner);
|
||||
llvm_emit_expr(c, be_value, inner);
|
||||
llvm_value_fold_optional(c, be_value);
|
||||
RETURN_ON_EMPTY_BLOCK(be_value);
|
||||
if (!llvm_emit_folded_in_block(c, be_value, inner)) RETURN_EMPTY_BLOCK(be_value);
|
||||
switch (expr->builtin_access_expr.kind)
|
||||
{
|
||||
case ACCESS_FAULTNAME:
|
||||
@@ -7028,22 +7026,16 @@ static void llvm_emit_ptr_access(GenContext *c, BEValue *value, Expr *expr)
|
||||
|
||||
static void llvm_emit_make_any(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
|
||||
llvm_emit_expr(c, value, expr->make_any_expr.inner);
|
||||
llvm_value_rvalue(c, value);
|
||||
RETURN_ON_EMPTY_BLOCK(value);
|
||||
if (!llvm_emit_rvalue_in_block(c, value, expr->make_any_expr.inner)) RETURN_EMPTY_BLOCK(value);
|
||||
BEValue typeid_val;
|
||||
Expr *typeid = expr->make_any_expr.typeid;
|
||||
llvm_emit_expr(c, &typeid_val, typeid);
|
||||
llvm_value_rvalue(c, &typeid_val);
|
||||
RETURN_ON_EMPTY_BLOCK(value);
|
||||
if (!llvm_emit_rvalue_in_block(c, &typeid_val, typeid)) RETURN_EMPTY_BLOCK(value);
|
||||
llvm_value_aggregate_two(c, value, expr->type, value->value, typeid_val.value);
|
||||
}
|
||||
|
||||
static void llvm_emit_ext_trunc(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_emit_expr(c, value, expr->ext_trunc_expr.inner);
|
||||
llvm_value_rvalue(c, value);
|
||||
if (!llvm_emit_rvalue_in_block(c, value, expr->ext_trunc_expr.inner)) RETURN_EMPTY_BLOCK(value);
|
||||
Type *to_type = type_lowering(expr->type);
|
||||
LLVMTypeRef to = llvm_get_type(c, to_type);
|
||||
LLVMValueRef val;
|
||||
@@ -7131,9 +7123,7 @@ static inline void llvm_emit_vector_to_array(GenContext *c, BEValue *value, Expr
|
||||
|
||||
void llvm_emit_slice_to_vec_array(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
llvm_emit_expr(c, value, expr->inner_expr);
|
||||
RETURN_ON_EMPTY_BLOCK(value);
|
||||
llvm_value_rvalue(c, value);
|
||||
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
|
||||
BEValue pointer;
|
||||
Type *base = value->type->array.base;
|
||||
AlignSize element_alignment = type_abi_alignment(base);
|
||||
@@ -7164,6 +7154,36 @@ static inline void llvm_emit_make_slice(GenContext *c, BEValue *value, Expr *exp
|
||||
llvm_value_aggregate_two(c, value, expr->type, pointer, llvm_const_int(c, type_usz, size));
|
||||
}
|
||||
|
||||
bool llvm_emit_folded_in_block(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
if (llvm_is_global_eval(c))
|
||||
{
|
||||
llvm_emit_expr(c, value, expr);
|
||||
llvm_value_fold_optional(c, value);
|
||||
return true;
|
||||
}
|
||||
llvm_emit_expr(c, value, expr);
|
||||
if (!c->current_block) return false;
|
||||
llvm_value_fold_optional(c, value);
|
||||
if (!c->current_block) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool llvm_emit_rvalue_in_block(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
if (llvm_is_global_eval(c))
|
||||
{
|
||||
llvm_emit_expr(c, value, expr);
|
||||
llvm_value_rvalue(c, value);
|
||||
return true;
|
||||
}
|
||||
llvm_emit_expr(c, value, expr);
|
||||
if (!c->current_block) return false;
|
||||
llvm_value_rvalue(c, value);
|
||||
if (!c->current_block) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
EMIT_EXPR_LOC(c, expr);
|
||||
|
||||
@@ -529,6 +529,8 @@ LLVMValueRef llvm_get_selector(GenContext *c, const char *name);
|
||||
// -- C3 Lowering --
|
||||
void llvm_emit_expr_global_value(GenContext *c, BEValue *value, Expr *expr);
|
||||
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr);
|
||||
bool llvm_emit_rvalue_in_block(GenContext *c, BEValue *value, Expr *expr);
|
||||
bool llvm_emit_folded_in_block(GenContext *c, BEValue *value, Expr *expr);
|
||||
LLVMValueRef llvm_emit_expr_to_rvalue(GenContext *c, Expr *expr);
|
||||
LLVMValueRef llvm_emit_exprid_to_rvalue(GenContext *c, ExprId expr_id);
|
||||
void llvm_emit_ignored_expr(GenContext *c, Expr *expr);
|
||||
@@ -596,6 +598,7 @@ void llvm_emit_debug_local_var(GenContext *c, Decl *var);
|
||||
#define POP_DEFER_ERROR() c->defer_error_var = def_err__
|
||||
#define RETURN_ON_EMPTY_BLOCK(value__) do { if (!llvm_is_global_eval(c) && !c->current_block) { llvm_value_set_empty(value__); return; }} while(0)
|
||||
#define RETURN_ON_EMPTY_BLOCK_VOID() do { if (!llvm_is_global_eval(c) && !c->current_block) { return; }} while(0)
|
||||
#define RETURN_EMPTY_BLOCK(value__) do { llvm_value_set_empty(value__); return; } while(0)
|
||||
|
||||
LLVMAtomicOrdering llvm_atomic_ordering(Atomicity atomicity);
|
||||
|
||||
|
||||
@@ -699,16 +699,14 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
if (case_stmt == default_case) continue;
|
||||
BEValue be_value;
|
||||
Expr *expr = exprptr(case_stmt->case_stmt.expr);
|
||||
llvm_emit_expr(c, &be_value, expr);
|
||||
llvm_value_rvalue(c, &be_value);
|
||||
if (!llvm_emit_rvalue_in_block(c, &be_value, expr)) goto DONE;
|
||||
BEValue equals;
|
||||
Expr *to_expr = exprptrzero(case_stmt->case_stmt.to_expr);
|
||||
if (to_expr)
|
||||
{
|
||||
ASSERT(!is_type_switch);
|
||||
BEValue to_value;
|
||||
llvm_emit_expr(c, &to_value, to_expr);
|
||||
llvm_value_rvalue(c, &to_value);
|
||||
if (!llvm_emit_rvalue_in_block(c, &to_value, to_expr)) goto DONE;
|
||||
BEValue le;
|
||||
llvm_emit_comp(c, &le, &be_value, switch_value, BINARYOP_LE);
|
||||
BEValue ge;
|
||||
@@ -748,6 +746,7 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
||||
{
|
||||
llvm_emit_br(c, exit_block);
|
||||
}
|
||||
DONE:
|
||||
llvm_emit_block(c, exit_block);
|
||||
}
|
||||
|
||||
|
||||
73
test/test_suite/expressions/optional_in_init_2.c3t
Normal file
73
test/test_suite/expressions/optional_in_init_2.c3t
Normal file
@@ -0,0 +1,73 @@
|
||||
module abc_faults;
|
||||
module abc <Type>;
|
||||
import std::io, abc_faults, std::collections::list;
|
||||
struct TextTemplate
|
||||
{
|
||||
Allocator allocator;
|
||||
String template;
|
||||
}
|
||||
fn void? TextTemplate.init(&self, String , String tag_start = "", String tag_end = "", Allocator using )
|
||||
{
|
||||
*self = { .allocator = io::EOF~!, .template = io::EOF~!, };
|
||||
}
|
||||
module text_test;
|
||||
import abc;
|
||||
alias FooTmpl = TextTemplate{Foo};
|
||||
alias BarTmpl = TextTemplate{Bar};
|
||||
struct Foo
|
||||
{
|
||||
BarTmpl bar;
|
||||
}
|
||||
struct Bar
|
||||
{
|
||||
String bar;
|
||||
}
|
||||
fn void main()
|
||||
{
|
||||
String foo_tmpl = "";
|
||||
FooTmpl ft;
|
||||
ft.init(foo_tmpl, using: tmem)!!;
|
||||
}
|
||||
|
||||
/* #expect: abc.ll
|
||||
|
||||
define weak i64 @"abc.TextTemplate$text_test.Foo$.init"(ptr %0, [2 x i64] %1, [2 x i64] %2, [2 x i64] %3, [2 x i64] %4) #0 {
|
||||
entry:
|
||||
%.anon = alloca %"char[]", align 8
|
||||
%tag_start = alloca %"char[]", align 8
|
||||
%tag_end = alloca %"char[]", align 8
|
||||
%using = alloca %any, align 8
|
||||
%.assign_list = alloca %"TextTemplate{Foo}", align 8
|
||||
%error_var = alloca i64, align 8
|
||||
store [2 x i64] %1, ptr %.anon, align 8
|
||||
store [2 x i64] %2, ptr %tag_start, align 8
|
||||
store [2 x i64] %3, ptr %tag_end, align 8
|
||||
store [2 x i64] %4, ptr %using, align 8
|
||||
call void @llvm.memset.p0.i64(ptr align 8 %.assign_list, i8 0, i64 32, i1 false)
|
||||
store i64 ptrtoint (ptr @std.io.EOF to i64), ptr %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
guard_block: ; preds = %entry
|
||||
%5 = load i64, ptr %error_var, align 8
|
||||
ret i64 %5
|
||||
}
|
||||
define weak i64 @"abc.TextTemplate$text_test.Bar$.init"(ptr %0, [2 x i64] %1, [2 x i64] %2, [2 x i64] %3, [2 x i64] %4) #0 {
|
||||
entry:
|
||||
%.anon = alloca %"char[]", align 8
|
||||
%tag_start = alloca %"char[]", align 8
|
||||
%tag_end = alloca %"char[]", align 8
|
||||
%using = alloca %any, align 8
|
||||
%.assign_list = alloca %"TextTemplate{Bar}", align 8
|
||||
%error_var = alloca i64, align 8
|
||||
store [2 x i64] %1, ptr %.anon, align 8
|
||||
store [2 x i64] %2, ptr %tag_start, align 8
|
||||
store [2 x i64] %3, ptr %tag_end, align 8
|
||||
store [2 x i64] %4, ptr %using, align 8
|
||||
call void @llvm.memset.p0.i64(ptr align 8 %.assign_list, i8 0, i64 32, i1 false)
|
||||
store i64 ptrtoint (ptr @std.io.EOF to i64), ptr %error_var, align 8
|
||||
br label %guard_block
|
||||
|
||||
guard_block: ; preds = %entry
|
||||
%5 = load i64, ptr %error_var, align 8
|
||||
ret i64 %5
|
||||
}
|
||||
20
test/test_suite/expressions/optional_panic_in_switch.c3t
Normal file
20
test/test_suite/expressions/optional_panic_in_switch.c3t
Normal file
@@ -0,0 +1,20 @@
|
||||
faultdef BAD_STUFF, WORSE_STUFF, THE_WORST_STUFF;
|
||||
fn int exitcode(fault )
|
||||
{
|
||||
switch
|
||||
{
|
||||
case THE_WORST_STUFF~!!:
|
||||
default: return 70;
|
||||
}
|
||||
}
|
||||
fn void? canFail()
|
||||
{
|
||||
}
|
||||
fn int main()
|
||||
{
|
||||
if (catch err = canFail())
|
||||
{
|
||||
return exitcode(err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user