aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-11-24 16:31:37 +0000
committergingerBill <bill@gingerbill.org>2021-11-24 16:31:37 +0000
commit504ea7deeb8645c441047b5a986c4eae6d8fdf93 (patch)
tree3a510e26af12e887cd44daffc6611a952c72a2a4 /src/check_expr.cpp
parent5e2280a78704fff62d4445015af3558babe74870 (diff)
Fix `update_untyped_expr_type` for ternary if expressions with an untyped type
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp29
1 files changed, 25 insertions, 4 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 3c884d117..560e5e607 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -1837,11 +1837,12 @@ void check_cast_error_suggestion(CheckerContext *c, Operand *o, Type *type) {
}
-void check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
+bool check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
GB_ASSERT(o->mode == Addressing_Constant);
ExactValue out_value = o->value;
if (is_type_constant_type(type) && check_representable_as_constant(ctx, o->value, type, &out_value)) {
o->value = out_value;
+ return true;
} else {
o->value = out_value;
@@ -1866,6 +1867,7 @@ void check_is_expressible(CheckerContext *ctx, Operand *o, Type *type) {
error(o->expr, "Cannot convert '%s' to '%s' from '%s", a, b, c);
check_assignment_error_suggestion(ctx, o, type);
}
+ return false;
}
}
@@ -3204,6 +3206,16 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Type *type_hint
x->mode = Addressing_Value;
}
+Operand make_operand_from_node(Ast *node) {
+ GB_ASSERT(node != nullptr);
+ Operand x = {};
+ x.expr = node;
+ x.mode = node->tav.mode;
+ x.type = node->tav.type;
+ x.value = node->tav.value;
+ return x;
+}
+
void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final) {
GB_ASSERT(e != nullptr);
@@ -3252,9 +3264,18 @@ void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final)
// See above note in UnaryExpr case
break;
}
-
- update_untyped_expr_type(c, te->x, type, final);
- update_untyped_expr_type(c, te->y, type, final);
+
+ // NOTE(bill): This is a bit of a hack to get around the edge cases of ternary if expressions
+ // having an untyped value
+ Operand x = make_operand_from_node(te->x);
+ Operand y = make_operand_from_node(te->y);
+ if (x.mode != Addressing_Constant || check_is_expressible(c, &x, type)) {
+ update_untyped_expr_type(c, te->x, type, final);
+ }
+ if (y.mode != Addressing_Constant || check_is_expressible(c, &y, type)) {
+ update_untyped_expr_type(c, te->y, type, final);
+ }
+
case_end;
case_ast_node(te, TernaryWhenExpr, e);