mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
Add checks on enum conversion in safe mode. Bump to 0.3.38.
This commit is contained in:
@@ -97,6 +97,7 @@ typedef enum
|
||||
CAST_BOOLBOOL,
|
||||
CAST_FPBOOL,
|
||||
CAST_INTBOOL,
|
||||
CAST_INTENUM,
|
||||
CAST_FPFP,
|
||||
CAST_FPSI,
|
||||
CAST_FPUI,
|
||||
|
||||
@@ -1106,8 +1106,9 @@ void llvm_emit_array_to_vector_cast(GenContext *c, BEValue *value, Type *to_type
|
||||
llvm_value_set(value, vector, to_type);
|
||||
}
|
||||
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type)
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
Type *to_type_original = to_type;
|
||||
to_type = type_flatten(to_type);
|
||||
from_type = type_flatten(from_type);
|
||||
|
||||
@@ -1288,6 +1289,27 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_
|
||||
value->value = LLVMBuildBitCast(c->builder, value->value, llvm_get_ptr_type(c, to_type), "");
|
||||
value->type = to_type;
|
||||
return;
|
||||
case CAST_INTENUM:
|
||||
if (active_target.feature.safe_mode && c->builder != c->global_builder)
|
||||
{
|
||||
llvm_value_rvalue(c, value);
|
||||
BEValue check;
|
||||
Decl *decl = to_type_original->canonical->decl;
|
||||
unsigned max = vec_size(decl->enums.values);
|
||||
if (type_is_signed(value->type))
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf("Conversion to enum '%s' failed - tried to convert a negative value.", decl->name);
|
||||
llvm_emit_int_comp_zero(c, &check, value, BINARYOP_LT);
|
||||
llvm_emit_panic_on_true(c, check.value, scratch_buffer_to_string(), expr->span);
|
||||
}
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf("Conversion to enum '%s' failed - the value was greater than %u.", decl->name, max - 1);
|
||||
LLVMValueRef val = llvm_const_int(c, value->type, max);
|
||||
llvm_emit_int_comp_raw(c, &check, value->type, value->type, value->value, val, BINARYOP_GE);
|
||||
llvm_emit_panic_on_true(c, check.value,scratch_buffer_to_string(), expr->span);
|
||||
}
|
||||
return;
|
||||
case CAST_SABOOL:
|
||||
llvm_value_fold_optional(c, value);
|
||||
if (llvm_value_is_addr(value))
|
||||
@@ -1316,6 +1338,7 @@ static inline void gencontext_emit_cast_expr(GenContext *context, BEValue *be_va
|
||||
llvm_emit_exprid(context, be_value, expr->cast_expr.expr);
|
||||
llvm_emit_cast(context,
|
||||
expr->cast_expr.kind,
|
||||
expr,
|
||||
be_value,
|
||||
expr->type,
|
||||
exprtype(expr->cast_expr.expr));
|
||||
@@ -3620,7 +3643,7 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
if (value->kind != BE_BOOLEAN)
|
||||
{
|
||||
CastKind cast = cast_to_bool_kind(cond_type);
|
||||
llvm_emit_cast(c, cast, value, type_bool, cond_type);
|
||||
llvm_emit_cast(c, cast, cond, value, type_bool, cond_type);
|
||||
assert(value->kind == BE_BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref,
|
||||
void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len);
|
||||
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl);
|
||||
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);
|
||||
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type);
|
||||
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl);
|
||||
void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value);
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ void llvm_emit_decl_expr_list(GenContext *context, BEValue *be_value, Expr *expr
|
||||
if (type->type_kind != TYPE_BOOL)
|
||||
{
|
||||
CastKind cast = cast_to_bool_kind(type);
|
||||
llvm_emit_cast(context, cast, be_value, type, type_bool);
|
||||
llvm_emit_cast(context, cast, last, be_value, type, type_bool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,11 +214,9 @@ bool integer_to_enum(Expr *expr, Type *canonical, Type *type)
|
||||
Decl *enum_decl = canonical->decl;
|
||||
if (expr->expr_kind != EXPR_CONST)
|
||||
{
|
||||
REMINDER("Add check for runtime enum conversions");
|
||||
Type *underlying_type = enum_decl->enums.type_info->type->canonical;
|
||||
if (!cast(expr, underlying_type)) return false;
|
||||
expr->type = type;
|
||||
return true;
|
||||
return insert_cast(expr, CAST_INTENUM, type);
|
||||
}
|
||||
unsigned max_enums = vec_size(enum_decl->enums.values);
|
||||
Int to_convert = expr->const_expr.ixx;
|
||||
|
||||
@@ -263,6 +263,7 @@ bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
|
||||
case CAST_BSINT:
|
||||
case CAST_BSARRY:
|
||||
return true;
|
||||
case CAST_INTENUM:
|
||||
case CAST_ANYPTR:
|
||||
case CAST_ERBOOL:
|
||||
case CAST_EUBOOL:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.37"
|
||||
#define COMPILER_VERSION "0.3.38"
|
||||
Reference in New Issue
Block a user