mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +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
|
- Converting static "make_slice" to array failed to be handled #2866
|
||||||
- Narrowing a not expression was incorrectly handled #2867
|
- Narrowing a not expression was incorrectly handled #2867
|
||||||
- Vector shift by optional scalar failed #2868
|
- 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
|
### Stdlib changes
|
||||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
- 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;
|
return;
|
||||||
}
|
}
|
||||||
BEValue val;
|
BEValue val;
|
||||||
|
RETURN_ON_EMPTY_BLOCK(ref);
|
||||||
llvm_emit_expr(c, &val, expr);
|
llvm_emit_expr(c, &val, expr);
|
||||||
|
RETURN_ON_EMPTY_BLOCK(ref);
|
||||||
llvm_store(c, ref, &val);
|
llvm_store(c, ref, &val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1884,6 +1886,7 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa
|
|||||||
{
|
{
|
||||||
BEValue splat_value;
|
BEValue splat_value;
|
||||||
llvm_emit_expr(c, &splat_value, splat);
|
llvm_emit_expr(c, &splat_value, splat);
|
||||||
|
RETURN_ON_EMPTY_BLOCK(ref);
|
||||||
llvm_store(c, ref, &splat_value);
|
llvm_store(c, ref, &splat_value);
|
||||||
}
|
}
|
||||||
else
|
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;
|
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,
|
llvm_emit_initialize_designated_element(c, ref, 0, designator->designator_expr.path, last_element,
|
||||||
designator->designator_expr.value, NULL);
|
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
|
// Generate condition and conditional branch
|
||||||
Expr *cond = exprptr(expr->ternary_expr.cond);
|
Expr *cond = exprptr(expr->ternary_expr.cond);
|
||||||
llvm_emit_expr(c, value, cond);
|
if (!llvm_emit_rvalue_in_block(c, value, cond))
|
||||||
llvm_value_rvalue(c, value);
|
{
|
||||||
RETURN_ON_EMPTY_BLOCK(value);
|
llvm_value_set_empty(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Expr *else_expr = exprptr(expr->ternary_expr.else_expr);
|
Expr *else_expr = exprptr(expr->ternary_expr.else_expr);
|
||||||
Expr *then_expr = exprptr(expr->ternary_expr.then_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);
|
BEValue array_ref = llvm_emit_alloca_b(c, array, varargslots_name);
|
||||||
FOREACH_IDX(foreach_index, Expr *, val, varargs)
|
FOREACH_IDX(foreach_index, Expr *, val, varargs)
|
||||||
{
|
{
|
||||||
llvm_emit_expr(c, &inner_temp, val);
|
if (!llvm_emit_folded_in_block(c, &inner_temp, val)) RETURN_EMPTY_BLOCK(value_ref);
|
||||||
RETURN_ON_EMPTY_BLOCK(value_ref);
|
|
||||||
llvm_value_fold_optional(c, &inner_temp);
|
|
||||||
BEValue slot = llvm_emit_array_gep(c, &array_ref, foreach_index);
|
BEValue slot = llvm_emit_array_gep(c, &array_ref, foreach_index);
|
||||||
llvm_store(c, &slot, &inner_temp);
|
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];
|
Expr *arg = args[i];
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
llvm_emit_expr(c, value_ref, arg);
|
if (!llvm_emit_folded_in_block(c, value_ref, arg)) RETURN_EMPTY_BLOCK(result_value);
|
||||||
llvm_value_fold_optional(c, value_ref);
|
|
||||||
RETURN_ON_EMPTY_BLOCK(result_value);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Decl *decl = sig->params[i];
|
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)
|
FOREACH_IDX(i, Expr *, vararg, varargs)
|
||||||
{
|
{
|
||||||
BEValue *value_ref = &values[arg_count + i];
|
BEValue *value_ref = &values[arg_count + i];
|
||||||
llvm_emit_expr(c, value_ref, vararg);
|
if (!llvm_emit_folded_in_block(c, value_ref, vararg)) RETURN_EMPTY_BLOCK(result_value);
|
||||||
llvm_value_fold_optional(c, value_ref);
|
|
||||||
RETURN_ON_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)
|
static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Expr *expr)
|
||||||
{
|
{
|
||||||
Expr *inner = exprptr(expr->builtin_access_expr.inner);
|
Expr *inner = exprptr(expr->builtin_access_expr.inner);
|
||||||
llvm_emit_expr(c, be_value, inner);
|
if (!llvm_emit_folded_in_block(c, be_value, inner)) RETURN_EMPTY_BLOCK(be_value);
|
||||||
llvm_value_fold_optional(c, be_value);
|
|
||||||
RETURN_ON_EMPTY_BLOCK(be_value);
|
|
||||||
switch (expr->builtin_access_expr.kind)
|
switch (expr->builtin_access_expr.kind)
|
||||||
{
|
{
|
||||||
case ACCESS_FAULTNAME:
|
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)
|
static void llvm_emit_make_any(GenContext *c, BEValue *value, Expr *expr)
|
||||||
{
|
{
|
||||||
|
if (!llvm_emit_rvalue_in_block(c, value, expr->make_any_expr.inner)) RETURN_EMPTY_BLOCK(value);
|
||||||
llvm_emit_expr(c, value, expr->make_any_expr.inner);
|
|
||||||
llvm_value_rvalue(c, value);
|
|
||||||
RETURN_ON_EMPTY_BLOCK(value);
|
|
||||||
BEValue typeid_val;
|
BEValue typeid_val;
|
||||||
Expr *typeid = expr->make_any_expr.typeid;
|
Expr *typeid = expr->make_any_expr.typeid;
|
||||||
llvm_emit_expr(c, &typeid_val, typeid);
|
if (!llvm_emit_rvalue_in_block(c, &typeid_val, typeid)) RETURN_EMPTY_BLOCK(value);
|
||||||
llvm_value_rvalue(c, &typeid_val);
|
|
||||||
RETURN_ON_EMPTY_BLOCK(value);
|
|
||||||
llvm_value_aggregate_two(c, value, expr->type, value->value, typeid_val.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)
|
static void llvm_emit_ext_trunc(GenContext *c, BEValue *value, Expr *expr)
|
||||||
{
|
{
|
||||||
llvm_emit_expr(c, value, expr->ext_trunc_expr.inner);
|
if (!llvm_emit_rvalue_in_block(c, value, expr->ext_trunc_expr.inner)) RETURN_EMPTY_BLOCK(value);
|
||||||
llvm_value_rvalue(c, value);
|
|
||||||
Type *to_type = type_lowering(expr->type);
|
Type *to_type = type_lowering(expr->type);
|
||||||
LLVMTypeRef to = llvm_get_type(c, to_type);
|
LLVMTypeRef to = llvm_get_type(c, to_type);
|
||||||
LLVMValueRef val;
|
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)
|
void llvm_emit_slice_to_vec_array(GenContext *c, BEValue *value, Expr *expr)
|
||||||
{
|
{
|
||||||
llvm_emit_expr(c, value, expr->inner_expr);
|
if (!llvm_emit_rvalue_in_block(c, value, expr->inner_expr)) RETURN_EMPTY_BLOCK(value);
|
||||||
RETURN_ON_EMPTY_BLOCK(value);
|
|
||||||
llvm_value_rvalue(c, value);
|
|
||||||
BEValue pointer;
|
BEValue pointer;
|
||||||
Type *base = value->type->array.base;
|
Type *base = value->type->array.base;
|
||||||
AlignSize element_alignment = type_abi_alignment(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));
|
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)
|
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||||
{
|
{
|
||||||
EMIT_EXPR_LOC(c, expr);
|
EMIT_EXPR_LOC(c, expr);
|
||||||
|
|||||||
@@ -529,6 +529,8 @@ LLVMValueRef llvm_get_selector(GenContext *c, const char *name);
|
|||||||
// -- C3 Lowering --
|
// -- C3 Lowering --
|
||||||
void llvm_emit_expr_global_value(GenContext *c, BEValue *value, Expr *expr);
|
void llvm_emit_expr_global_value(GenContext *c, BEValue *value, Expr *expr);
|
||||||
void llvm_emit_expr(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_expr_to_rvalue(GenContext *c, Expr *expr);
|
||||||
LLVMValueRef llvm_emit_exprid_to_rvalue(GenContext *c, ExprId expr_id);
|
LLVMValueRef llvm_emit_exprid_to_rvalue(GenContext *c, ExprId expr_id);
|
||||||
void llvm_emit_ignored_expr(GenContext *c, Expr *expr);
|
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 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(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_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);
|
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;
|
if (case_stmt == default_case) continue;
|
||||||
BEValue be_value;
|
BEValue be_value;
|
||||||
Expr *expr = exprptr(case_stmt->case_stmt.expr);
|
Expr *expr = exprptr(case_stmt->case_stmt.expr);
|
||||||
llvm_emit_expr(c, &be_value, expr);
|
if (!llvm_emit_rvalue_in_block(c, &be_value, expr)) goto DONE;
|
||||||
llvm_value_rvalue(c, &be_value);
|
|
||||||
BEValue equals;
|
BEValue equals;
|
||||||
Expr *to_expr = exprptrzero(case_stmt->case_stmt.to_expr);
|
Expr *to_expr = exprptrzero(case_stmt->case_stmt.to_expr);
|
||||||
if (to_expr)
|
if (to_expr)
|
||||||
{
|
{
|
||||||
ASSERT(!is_type_switch);
|
ASSERT(!is_type_switch);
|
||||||
BEValue to_value;
|
BEValue to_value;
|
||||||
llvm_emit_expr(c, &to_value, to_expr);
|
if (!llvm_emit_rvalue_in_block(c, &to_value, to_expr)) goto DONE;
|
||||||
llvm_value_rvalue(c, &to_value);
|
|
||||||
BEValue le;
|
BEValue le;
|
||||||
llvm_emit_comp(c, &le, &be_value, switch_value, BINARYOP_LE);
|
llvm_emit_comp(c, &le, &be_value, switch_value, BINARYOP_LE);
|
||||||
BEValue ge;
|
BEValue ge;
|
||||||
@@ -748,6 +746,7 @@ static void llvm_emit_switch_body_if_chain(GenContext *c,
|
|||||||
{
|
{
|
||||||
llvm_emit_br(c, exit_block);
|
llvm_emit_br(c, exit_block);
|
||||||
}
|
}
|
||||||
|
DONE:
|
||||||
llvm_emit_block(c, exit_block);
|
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