From 150d4e343ddd99eef1d921cdd494c108ac2e9a12 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 23 Aug 2019 10:24:18 +0100 Subject: [PATCH] Fix `~(1 << x)` type inference bug --- src/check_expr.cpp | 17 ++++++++++------- src/check_stmt.cpp | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8da6816ac..6c252b9b6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1767,7 +1767,7 @@ void check_comparison(CheckerContext *c, Operand *x, Operand *y, TokenKind op) { } -void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *node) { +void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *node, Type *type_hint) { GB_ASSERT(node->kind == Ast_BinaryExpr); ast_node(be, BinaryExpr, node); @@ -1845,6 +1845,9 @@ void check_shift(CheckerContext *c, Operand *x, Operand *y, Ast *node) { info->is_lhs = true; } x->mode = Addressing_Value; + if (type_hint && is_type_integer(type_hint)) { + x->type = type_hint; + } // x->value = x_val; return; } @@ -2167,7 +2170,7 @@ bool check_binary_array_expr(CheckerContext *c, Token op, Operand *x, Operand *y } -void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as_type_hint=false) { +void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint, bool use_lhs_as_type_hint=false) { GB_ASSERT(node->kind == Ast_BinaryExpr); Operand y_ = {}, *y = &y_; @@ -2178,7 +2181,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as case Token_CmpEq: case Token_NotEq: { // NOTE(bill): Allow comparisons between types - check_expr_or_type(c, x, be->left); + check_expr_or_type(c, x, be->left, type_hint); check_expr_or_type(c, y, be->right, x->type); bool xt = x->mode == Addressing_Type; bool yt = y->mode == Addressing_Type; @@ -2278,11 +2281,11 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as return; default: - check_expr(c, x, be->left); + check_expr_with_type_hint(c, x, be->left, type_hint); if (use_lhs_as_type_hint) { check_expr_with_type_hint(c, y, be->right, x->type); } else { - check_expr(c, y, be->right); + check_expr_with_type_hint(c, y, be->right, type_hint); } break; } @@ -2307,7 +2310,7 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, bool use_lhs_as } if (token_is_shift(op.kind)) { - check_shift(c, x, y, node); + check_shift(c, x, y, node, type_hint); return; } @@ -7000,7 +7003,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type case_ast_node(be, BinaryExpr, node); - check_binary_expr(c, o, node, true); + check_binary_expr(c, o, node, type_hint, true); if (o->mode == Addressing_Invalid) { o->expr = node; return kind; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index e2090688f..2787aa436 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1168,7 +1168,7 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { be->right = as->rhs[0]; check_expr(ctx, &lhs, as->lhs[0]); - check_binary_expr(ctx, &rhs, &binary_expr, true); + check_binary_expr(ctx, &rhs, &binary_expr, nullptr, true); if (rhs.mode == Addressing_Invalid) { return; }