mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
parent
1543043bf5
commit
a922d5d42a
@ -310,6 +310,7 @@ enum CastOp {
|
||||
CastOpToUnknownSizeArray,
|
||||
CastOpMaybeWrap,
|
||||
CastOpPointerReinterpret,
|
||||
CastOpErrToInt,
|
||||
};
|
||||
|
||||
struct AstNodeFnCallExpr {
|
||||
@ -999,6 +1000,7 @@ struct CodeGen {
|
||||
bool error_during_imports;
|
||||
uint32_t next_node_index;
|
||||
uint32_t next_error_index;
|
||||
TypeTableEntry *err_tag_type;
|
||||
};
|
||||
|
||||
struct VariableTableEntry {
|
||||
|
@ -233,11 +233,10 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
|
||||
entry->data.error.child_type = child_type;
|
||||
|
||||
if (child_type->size_in_bits == 0) {
|
||||
TypeTableEntry *tag_type = get_smallest_unsigned_int_type(g, g->next_error_index);
|
||||
entry->type_ref = tag_type->type_ref;
|
||||
entry->size_in_bits = tag_type->size_in_bits;
|
||||
entry->align_in_bits = tag_type->align_in_bits;
|
||||
entry->di_type = tag_type->di_type;
|
||||
entry->type_ref = g->err_tag_type->type_ref;
|
||||
entry->size_in_bits = g->err_tag_type->size_in_bits;
|
||||
entry->align_in_bits = g->err_tag_type->align_in_bits;
|
||||
entry->di_type = g->err_tag_type->di_type;
|
||||
|
||||
} else {
|
||||
zig_panic("TODO get_error_type non-void");
|
||||
@ -2869,6 +2868,10 @@ static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *ex
|
||||
const_val->data.x_maybe = other_val;
|
||||
const_val->ok = true;
|
||||
break;
|
||||
case CastOpErrToInt:
|
||||
bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_err->value);
|
||||
const_val->ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2975,6 +2978,24 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
|
||||
}
|
||||
}
|
||||
|
||||
// explicit cast from %void to integer type which can fit it
|
||||
if (actual_type->id == TypeTableEntryIdError &&
|
||||
actual_type->data.error.child_type->size_in_bits == 0 &&
|
||||
wanted_type->id == TypeTableEntryIdInt)
|
||||
{
|
||||
BigNum bn;
|
||||
bignum_init_unsigned(&bn, g->next_error_index);
|
||||
if (bignum_fits_in_bits(&bn, wanted_type->size_in_bits, wanted_type->data.integral.is_signed)) {
|
||||
node->data.fn_call_expr.cast_op = CastOpErrToInt;
|
||||
eval_const_expr_implicit_cast(g, node, expr_node);
|
||||
return wanted_type;
|
||||
} else {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("too many error values to fit in '%s'", buf_ptr(&wanted_type->name)));
|
||||
return g->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("invalid cast from type '%s' to '%s'",
|
||||
buf_ptr(&actual_type->name),
|
||||
@ -4353,6 +4374,9 @@ void semantic_analyze(CodeGen *g) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g->err_tag_type = get_smallest_unsigned_int_type(g, g->next_error_index);
|
||||
|
||||
{
|
||||
auto it = g->import_table.entry_iterator();
|
||||
for (;;) {
|
||||
|
@ -284,6 +284,13 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) {
|
||||
zig_unreachable();
|
||||
case CastOpNoop:
|
||||
return expr_val;
|
||||
case CastOpErrToInt:
|
||||
assert(actual_type->id == TypeTableEntryIdError);
|
||||
if (actual_type->data.error.child_type->size_in_bits == 0) {
|
||||
return expr_val;
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
case CastOpMaybeWrap:
|
||||
{
|
||||
assert(cast_expr->tmp_ptr);
|
||||
@ -2122,6 +2129,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
} else {
|
||||
return global_value;
|
||||
}
|
||||
} else if (type_entry->id == TypeTableEntryIdError) {
|
||||
if (type_entry->data.error.child_type->size_in_bits == 0) {
|
||||
return LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err->value, false);
|
||||
} else {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -1258,6 +1258,22 @@ pub fn main(args: [][]u8) i32 => {
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
add_simple_case("error values", R"SOURCE(
|
||||
import "std.zig";
|
||||
%.err1;
|
||||
%.err2;
|
||||
pub fn main(args: [][]u8) i32 => {
|
||||
const a = i32(%.err1);
|
||||
const b = i32(%.err2);
|
||||
if (a == b) {
|
||||
print_str("BAD\n");
|
||||
}
|
||||
|
||||
print_str("OK\n");
|
||||
return 0;
|
||||
}
|
||||
)SOURCE", "OK\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user