mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 03:03:09 +00:00
parent
38b47d8aca
commit
2234788fa8
@ -150,3 +150,7 @@ Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
|
||||
return CmpEQ;
|
||||
}
|
||||
}
|
||||
|
||||
bool bigfloat_has_fraction(const BigFloat *bigfloat) {
|
||||
return floorl(bigfloat->value) != bigfloat->value;
|
||||
}
|
||||
|
||||
@ -43,5 +43,6 @@ void bigfloat_read_ieee597(BigFloat *dest, const uint8_t *buf, size_t bit_count,
|
||||
|
||||
// convenience functions
|
||||
Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
|
||||
bool bigfloat_has_fraction(const BigFloat *bigfloat);
|
||||
|
||||
#endif
|
||||
|
||||
46
src/ir.cpp
46
src/ir.cpp
@ -6206,7 +6206,9 @@ static bool const_val_fits_in_num_lit(ConstExprValue *const_val, TypeTableEntry
|
||||
(const_val->type->id == TypeTableEntryIdInt || const_val->type->id == TypeTableEntryIdNumLitInt)));
|
||||
}
|
||||
|
||||
static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type) {
|
||||
static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruction, TypeTableEntry *other_type,
|
||||
bool explicit_cast)
|
||||
{
|
||||
if (type_is_invalid(other_type)) {
|
||||
return false;
|
||||
}
|
||||
@ -6243,6 +6245,32 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (explicit_cast && (other_type->id == TypeTableEntryIdInt || other_type->id == TypeTableEntryIdNumLitInt) &&
|
||||
const_val_is_float)
|
||||
{
|
||||
if (bigfloat_has_fraction(&const_val->data.x_bigfloat)) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigfloat_write_buf(val_buf, &const_val->data.x_bigfloat);
|
||||
|
||||
ir_add_error(ira, instruction,
|
||||
buf_sprintf("fractional component prevents float value %s from being casted to type '%s'",
|
||||
buf_ptr(val_buf),
|
||||
buf_ptr(&other_type->name)));
|
||||
return false;
|
||||
} else {
|
||||
BigInt bigint;
|
||||
bigint_init_bigfloat(&bigint, &const_val->data.x_bigfloat);
|
||||
if (other_type->id == TypeTableEntryIdNumLitInt) {
|
||||
return true;
|
||||
} else {
|
||||
if (bigint_fits_in_bits(&bigint, other_type->data.integral.bit_count,
|
||||
other_type->data.integral.is_signed))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *num_lit_str;
|
||||
Buf *val_buf = buf_alloc();
|
||||
@ -6425,12 +6453,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
||||
if (expected_type->id == TypeTableEntryIdPointer &&
|
||||
expected_type->data.pointer.is_const)
|
||||
{
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, expected_type->data.pointer.child_type)) {
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, expected_type->data.pointer.child_type, false)) {
|
||||
return ImplicitCastMatchResultYes;
|
||||
} else {
|
||||
return ImplicitCastMatchResultReportedError;
|
||||
}
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, expected_type)) {
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, expected_type, false)) {
|
||||
return ImplicitCastMatchResultYes;
|
||||
} else {
|
||||
return ImplicitCastMatchResultReportedError;
|
||||
@ -6542,7 +6570,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
||||
} else if (prev_type->id == TypeTableEntryIdNumLitInt ||
|
||||
prev_type->id == TypeTableEntryIdNumLitFloat)
|
||||
{
|
||||
if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type)) {
|
||||
if (ir_num_lit_fits_in_other_type(ira, prev_inst, cur_type, false)) {
|
||||
prev_inst = cur_inst;
|
||||
continue;
|
||||
} else {
|
||||
@ -6551,7 +6579,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
||||
} else if (cur_type->id == TypeTableEntryIdNumLitInt ||
|
||||
cur_type->id == TypeTableEntryIdNumLitFloat)
|
||||
{
|
||||
if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) {
|
||||
if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type, false)) {
|
||||
continue;
|
||||
} else {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
@ -7636,7 +7664,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
||||
actual_type->id == TypeTableEntryIdNumLitFloat)
|
||||
{
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type)) {
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.maybe.child_type, true)) {
|
||||
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
|
||||
} else {
|
||||
return ira->codegen->invalid_instruction;
|
||||
@ -7658,7 +7686,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
||||
actual_type->id == TypeTableEntryIdNumLitFloat)
|
||||
{
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type)) {
|
||||
if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error.child_type, true)) {
|
||||
return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
|
||||
} else {
|
||||
return ira->codegen->invalid_instruction;
|
||||
@ -7736,7 +7764,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
return cast2;
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type)) {
|
||||
} else if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
|
||||
CastOp op;
|
||||
if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
|
||||
wanted_type->id == TypeTableEntryIdFloat) ||
|
||||
@ -8630,7 +8658,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type);
|
||||
ir_num_lit_fits_in_other_type(ira, &bin_op_instruction->base, resolved_type, false);
|
||||
return resolved_type;
|
||||
}
|
||||
|
||||
|
||||
@ -43,8 +43,7 @@ fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
|
||||
|
||||
// normalize the midpoint
|
||||
|
||||
var e: i32 = undefined;
|
||||
_ = math.frexp(val, &e);
|
||||
const e = math.frexp(val).exponent;
|
||||
var exp = i16(math.floor(307 + f64(e) * 0.30103));
|
||||
if (exp < 20) {
|
||||
exp = 20;
|
||||
|
||||
@ -95,7 +95,7 @@ pub const isSignalNan = @import("isnan.zig").isSignalNan;
|
||||
pub const fabs = @import("fabs.zig").fabs;
|
||||
pub const ceil = @import("ceil.zig").ceil;
|
||||
pub const floor = @import("floor.zig").floor;
|
||||
pub const trunc = @import("floor.zig").trunc;
|
||||
pub const trunc = @import("trunc.zig").trunc;
|
||||
pub const round = @import("round.zig").round;
|
||||
pub const frexp = @import("frexp.zig").frexp;
|
||||
pub const frexp32_result = @import("frexp.zig").frexp32_result;
|
||||
|
||||
@ -251,3 +251,10 @@ fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {
|
||||
else => error.BadValue,
|
||||
}
|
||||
}
|
||||
|
||||
test "explicit cast float number literal to integer if no fraction component" {
|
||||
const x = i32(1e4);
|
||||
assert(x == 10000);
|
||||
const y = i32(f32(1e4));
|
||||
assert(y == 10000);
|
||||
}
|
||||
|
||||
@ -1945,4 +1945,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:15: error: float literal out of range of any type");
|
||||
|
||||
cases.add("explicit cast float literal to integer when there is a fraction component",
|
||||
\\export fn entry() -> i32 {
|
||||
\\ i32(12.34)
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:9: error: fractional component prevents float value 12.340000 from being casted to type 'i32'");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user