Fix case of very long literal int type values. Fix to bigint compile time truncation. Check decl enum implicit overflow.

This commit is contained in:
Christoffer Lerno
2021-11-19 09:11:58 +01:00
parent a4a6ea16ce
commit 0af448ee71
6 changed files with 46 additions and 23 deletions

View File

@@ -767,16 +767,18 @@ Int int_conv(Int op, TypeKind to_type)
}
// Extending from a signed to unsigned
int shift = 128 - to_bitsize;
// Cut off the top.
// Cut off the top of the signed bits
// 11101 -> 11010 -> 01101
return (Int){ i128_lshr64(i128_shl64(op.i, shift), shift), to_type };
}
// The other case is cutting down bits.
int shift = 128 - to_bitsize;
// Cut off the top.
if (from_signed)
Int128 without_top_bits = i128_lshr64(i128_shl64(op.i, shift), shift);
if (to_signed)
{
return (Int){ i128_ashr64(i128_shl64(op.i, shift), shift), to_type };
return (Int){ i128_ashr64(i128_shl64(without_top_bits, shift), shift), to_type };
}
return (Int){ i128_lshr64(i128_shl64(op.i, shift), shift), to_type };
return (Int) { without_top_bits, to_type };
}
Int int_div(Int op1, Int op2)

View File

@@ -1781,7 +1781,6 @@ static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *
}
if (initializer->kind == CONST_INIT_ZERO)
{
REMINDER("Optimize this for few elements");
// In case of a zero, optimize.
llvm_emit_memclear(c, ref);
return;
@@ -4738,27 +4737,31 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue
static inline void gencontext_emit_failable(GenContext *context, BEValue *be_value, Expr *expr)
static inline void llvm_emit_failable(GenContext *c, BEValue *be_value, Expr *expr)
{
Expr *fail = expr->inner_expr;
if (context->error_var)
// If there is an error value, assign to it.
if (c->error_var)
{
assert(context->error_var);
llvm_emit_expr(context, be_value, fail);
REMINDER("fix failable");
LLVMBuildStore(context->builder, llvm_value_rvalue_store(context, be_value),
llvm_emit_bitcast(context, context->error_var, type_get_ptr(fail->type)));
assert(c->error_var);
llvm_emit_expr(c, be_value, fail);
llvm_store_bevalue_dest_aligned(c, c->error_var, be_value);
}
llvm_emit_br(context, context->catch_block);
LLVMBasicBlockRef ignored_block = llvm_basic_block_new(context, "postfailed");
llvm_emit_block(context, ignored_block);
// Branch to the catch
llvm_emit_br(c, c->catch_block);
// Create an empty block
LLVMBasicBlockRef ignored_block = llvm_basic_block_new(c, "postfailed");
llvm_emit_block(c, ignored_block);
// Finally we need to replace the result with something undefined here.
// It will be optimized away.
Type *type = type_no_fail(expr->type);
if (type->canonical == type_void)
{
llvm_value_set(be_value, NULL, type_void);
return;
}
llvm_value_set(be_value, LLVMGetUndef(llvm_get_type(context, type)), type);
llvm_value_set(be_value, LLVMGetUndef(llvm_get_type(c, type)), type);
}
static inline LLVMValueRef llvm_update_vector(GenContext *c, LLVMValueRef vector, LLVMValueRef value, ArrayIndex index, bool *is_const)
@@ -5027,7 +5030,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_len(c, value, expr);
return;
case EXPR_FAILABLE:
gencontext_emit_failable(c, value, expr);
llvm_emit_failable(c, value, expr);
return;
case EXPR_TRY:
llvm_emit_try_expr(c, value, expr);

View File

@@ -952,11 +952,12 @@ static Expr *parse_placeholder(Context *context, Expr *left)
static int read_num_type(const char *string, const char *end)
{
REMINDER("Limit num type reader");
int i = 0;
if (string[0] == '0') return -1;
while (string < end)
{
i *= 10;
if (i > 1024) return i;
i += *(string++) - '0';
}
return i;
@@ -1079,7 +1080,7 @@ static Expr *parse_integer(Context *context, Expr *left)
{
if (!is_power_of_two(type_bits) || type_bits > 128)
{
SEMA_TOKEN_ERROR(context->tok, "Integer width should be 8, 16, 32, 64 or 128.");
SEMA_TOKEN_ERROR(context->tok, "Integer type suffix should be i8, i16, i32, i64 or i128.");
return poisoned_expr;
}
}

View File

@@ -741,9 +741,10 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
unsigned enums = vec_size(decl->enums.values);
Int128 value = { 0, 0 };
Decl **enum_values = decl->enums.values;
for (unsigned i = 0; i < enums; i++)
{
Decl *enum_value = decl->enums.values[i];
Decl *enum_value = enum_values[i];
enum_value->type = decl->type;
DEBUG_LOG("* Checking enum constant %s.", enum_value->name);
enum_value->enum_constant.ordinal = i;
@@ -762,8 +763,15 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
expr = expr_new(EXPR_CONST, source_span_from_token_id(enum_value->name_token));
expr->type = type;
expr->resolve_status = RESOLVE_NOT_DONE;
REMINDER("Do range check");
expr->const_expr.ixx = (Int) { value, canonical->type_kind };
if (expr_const_will_overflow(&expr->const_expr, canonical->type_kind))
{
SEMA_ERROR(enum_value,
"The enum value would implicitly be %s which does not fit in %s.",
i128_to_string(value, 10, type_is_signed(canonical)),
type_quoted_error_string(type));
return false;
}
expr->const_expr.const_kind = CONST_INTEGER;
expr->const_expr.narrowable = true;
expr->type = canonical;
@@ -794,7 +802,7 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
}
// Update the value
value = i128_add64(value, 1);
value = i128_add64(expr->const_expr.ixx.i, 1);
DEBUG_LOG("* Value: %s", expr_const_to_error_string(&expr->const_expr));
enum_value->resolve_status = RESOLVE_DONE;
}

View File

@@ -0,0 +1,4 @@
int i = 4i15; // #error: Integer type suffix should be i8, i16, i32, i64 or i128
int j = 4i1024; // #error: Integer type suffix should be i8, i16, i32, i64 or i128
int k = 4i65536; // #error: Integer type suffix should be i8, i16, i32, i64 or i128
int l = 4i016; // #error: Integer type suffix should be i8, i16, i32, i64 or i128

View File

@@ -0,0 +1,5 @@
enum Foo : char
{
MY_VAL1 = 255,
MY_VAL2, // #error: The enum value would implicitly be 256 which does not fit in 'char'
}