unsigned ints implicitly cast to signed ints when they fit

also fix #135
This commit is contained in:
Andrew Kelley 2016-04-11 22:57:32 -07:00
parent 4a3bce4b63
commit 954a451c51
2 changed files with 29 additions and 11 deletions

View File

@ -1855,6 +1855,14 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
return true;
}
// small enough unsigned ints can get casted to large enough signed ints
if (expected_type->id == TypeTableEntryIdInt && expected_type->data.integral.is_signed &&
actual_type->id == TypeTableEntryIdInt && !actual_type->data.integral.is_signed &&
expected_type->data.integral.bit_count > actual_type->data.integral.bit_count)
{
return true;
}
// implicit float widening conversion
if (expected_type->id == TypeTableEntryIdFloat &&
actual_type->id == TypeTableEntryIdFloat &&
@ -1889,27 +1897,30 @@ static bool types_match_with_implicit_cast(CodeGen *g, TypeTableEntry *expected_
return false;
}
static AstNode *create_ast_node(CodeGen *g, ImportTableEntry *import, NodeType kind) {
static AstNode *create_ast_node(CodeGen *g, ImportTableEntry *import, NodeType kind, AstNode *source_node) {
AstNode *node = allocate<AstNode>(1);
node->type = kind;
node->owner = import;
node->create_index = g->next_node_index;
g->next_node_index += 1;
node->line = source_node->line;
node->column = source_node->column;
return node;
}
static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeTableEntry *type_entry) {
AstNode *node = create_ast_node(g, import, NodeTypeSymbol);
static AstNode *create_ast_type_node(CodeGen *g, ImportTableEntry *import, TypeTableEntry *type_entry,
AstNode *source_node)
{
AstNode *node = create_ast_node(g, import, NodeTypeSymbol, source_node);
node->data.symbol_expr.override_type_entry = type_entry;
return node;
}
static AstNode *create_ast_void_node(CodeGen *g, ImportTableEntry *import, AstNode *source_node) {
AstNode *node = create_ast_node(g, import, NodeTypeContainerInitExpr);
AstNode *node = create_ast_node(g, import, NodeTypeContainerInitExpr, source_node);
node->data.container_init_expr.kind = ContainerInitKindArray;
node->data.container_init_expr.type = create_ast_type_node(g, import, g->builtin_types.entry_void);
node->line = source_node->line;
node->column = source_node->column;
node->data.container_init_expr.type = create_ast_type_node(g, import, g->builtin_types.entry_void,
source_node);
normalize_parent_ptrs(node);
return node;
}
@ -1917,13 +1928,11 @@ static AstNode *create_ast_void_node(CodeGen *g, ImportTableEntry *import, AstNo
static TypeTableEntry *create_and_analyze_cast_node(CodeGen *g, ImportTableEntry *import,
BlockContext *context, TypeTableEntry *cast_to_type, AstNode *node)
{
AstNode *new_parent_node = create_ast_node(g, import, NodeTypeFnCallExpr);
new_parent_node->line = node->line;
new_parent_node->column = node->column;
AstNode *new_parent_node = create_ast_node(g, import, NodeTypeFnCallExpr, node);
*node->parent_field = new_parent_node;
new_parent_node->parent_field = node->parent_field;
new_parent_node->data.fn_call_expr.fn_ref_expr = create_ast_type_node(g, import, cast_to_type);
new_parent_node->data.fn_call_expr.fn_ref_expr = create_ast_type_node(g, import, cast_to_type, node);
new_parent_node->data.fn_call_expr.params.append(node);
normalize_parent_ptrs(new_parent_node);

View File

@ -811,3 +811,12 @@ fn cast_undefined() {
test_cast_undefined(slice);
}
fn test_cast_undefined(x: []u8) {}
#attribute("test")
fn cast_small_unsigned_to_larger_signed() {
assert(cast_small_unsigned_to_larger_signed_1(200) == i16(200));
assert(cast_small_unsigned_to_larger_signed_2(9999) == isize(9999));
}
fn cast_small_unsigned_to_larger_signed_1(x: u8) -> i16 { x }
fn cast_small_unsigned_to_larger_signed_2(x: u16) -> isize { x }