mirror of
https://github.com/ziglang/zig.git
synced 2025-12-20 21:23:06 +00:00
parent
38b47d8aca
commit
2234788fa8
@ -150,3 +150,7 @@ Cmp bigfloat_cmp_zero(const BigFloat *bigfloat) {
|
|||||||
return CmpEQ;
|
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
|
// convenience functions
|
||||||
Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
|
Cmp bigfloat_cmp_zero(const BigFloat *bigfloat);
|
||||||
|
bool bigfloat_has_fraction(const BigFloat *bigfloat);
|
||||||
|
|
||||||
#endif
|
#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)));
|
(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)) {
|
if (type_is_invalid(other_type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -6243,6 +6245,32 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
|||||||
return true;
|
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;
|
const char *num_lit_str;
|
||||||
Buf *val_buf = buf_alloc();
|
Buf *val_buf = buf_alloc();
|
||||||
@ -6425,12 +6453,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
|
|||||||
if (expected_type->id == TypeTableEntryIdPointer &&
|
if (expected_type->id == TypeTableEntryIdPointer &&
|
||||||
expected_type->data.pointer.is_const)
|
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;
|
return ImplicitCastMatchResultYes;
|
||||||
} else {
|
} else {
|
||||||
return ImplicitCastMatchResultReportedError;
|
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;
|
return ImplicitCastMatchResultYes;
|
||||||
} else {
|
} else {
|
||||||
return ImplicitCastMatchResultReportedError;
|
return ImplicitCastMatchResultReportedError;
|
||||||
@ -6542,7 +6570,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
|||||||
} else if (prev_type->id == TypeTableEntryIdNumLitInt ||
|
} else if (prev_type->id == TypeTableEntryIdNumLitInt ||
|
||||||
prev_type->id == TypeTableEntryIdNumLitFloat)
|
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;
|
prev_inst = cur_inst;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@ -6551,7 +6579,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
|
|||||||
} else if (cur_type->id == TypeTableEntryIdNumLitInt ||
|
} else if (cur_type->id == TypeTableEntryIdNumLitInt ||
|
||||||
cur_type->id == TypeTableEntryIdNumLitFloat)
|
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;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return ira->codegen->builtin_types.entry_invalid;
|
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 ||
|
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
||||||
actual_type->id == TypeTableEntryIdNumLitFloat)
|
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);
|
return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
|
||||||
} else {
|
} else {
|
||||||
return ira->codegen->invalid_instruction;
|
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 ||
|
} else if (actual_type->id == TypeTableEntryIdNumLitInt ||
|
||||||
actual_type->id == TypeTableEntryIdNumLitFloat)
|
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);
|
return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
|
||||||
} else {
|
} else {
|
||||||
return ira->codegen->invalid_instruction;
|
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 ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
return cast2;
|
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;
|
CastOp op;
|
||||||
if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
|
if ((actual_type->id == TypeTableEntryIdNumLitFloat &&
|
||||||
wanted_type->id == TypeTableEntryIdFloat) ||
|
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;
|
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;
|
return resolved_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,8 +43,7 @@ fn errol3u(val: f64, buffer: []u8) -> FloatDecimal {
|
|||||||
|
|
||||||
// normalize the midpoint
|
// normalize the midpoint
|
||||||
|
|
||||||
var e: i32 = undefined;
|
const e = math.frexp(val).exponent;
|
||||||
_ = math.frexp(val, &e);
|
|
||||||
var exp = i16(math.floor(307 + f64(e) * 0.30103));
|
var exp = i16(math.floor(307 + f64(e) * 0.30103));
|
||||||
if (exp < 20) {
|
if (exp < 20) {
|
||||||
exp = 20;
|
exp = 20;
|
||||||
|
|||||||
@ -95,7 +95,7 @@ pub const isSignalNan = @import("isnan.zig").isSignalNan;
|
|||||||
pub const fabs = @import("fabs.zig").fabs;
|
pub const fabs = @import("fabs.zig").fabs;
|
||||||
pub const ceil = @import("ceil.zig").ceil;
|
pub const ceil = @import("ceil.zig").ceil;
|
||||||
pub const floor = @import("floor.zig").floor;
|
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 round = @import("round.zig").round;
|
||||||
pub const frexp = @import("frexp.zig").frexp;
|
pub const frexp = @import("frexp.zig").frexp;
|
||||||
pub const frexp32_result = @import("frexp.zig").frexp32_result;
|
pub const frexp32_result = @import("frexp.zig").frexp32_result;
|
||||||
|
|||||||
@ -251,3 +251,10 @@ fn testPeerErrorAndArray2(x: u8) -> %[]const u8 {
|
|||||||
else => error.BadValue,
|
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");
|
".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