diff options
| author | gingerBill <bill@gingerbill.org> | 2021-05-13 00:57:10 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-05-13 00:57:10 +0100 |
| commit | be12f12c3c2872fd89021af16c2ab838277c4c4a (patch) | |
| tree | c383925cf5bdd8a16e5836ab12fe2fb8dcc10e06 /src/check_stmt.cpp | |
| parent | 2e5f57d8a18352c02da72f2f2385116a099d7942 (diff) | |
Fix #814
Diffstat (limited to 'src/check_stmt.cpp')
| -rw-r--r-- | src/check_stmt.cpp | 41 |
1 files changed, 38 insertions, 3 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a3c9a529c..9ca53c4fc 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -960,9 +960,44 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { Operand b1 = rhs; check_comparison(ctx, &a1, &b1, Token_LtEq); - add_constant_switch_case(ctx, &seen, lhs); - if (upper_op == Token_GtEq) { - add_constant_switch_case(ctx, &seen, rhs); + if (is_type_enum(x.type)) { + // TODO(bill): Fix this logic so it's fast!!! + + i64 v0 = exact_value_to_i64(lhs.value); + i64 v1 = exact_value_to_i64(rhs.value); + Operand v = {}; + v.mode = Addressing_Constant; + v.type = x.type; + v.expr = x.expr; + + Type *bt = base_type(x.type); + GB_ASSERT(bt->kind == Type_Enum); + for (i64 vi = v0; vi <= v1; vi++) { + if (upper_op != Token_GtEq && vi == v1) { + break; + } + + bool found = false; + for_array(j, bt->Enum.fields) { + Entity *f = bt->Enum.fields[j]; + GB_ASSERT(f->kind == Entity_Constant); + + i64 fv = exact_value_to_i64(f->Constant.value); + if (fv == vi) { + found = true; + break; + } + } + if (found) { + v.value = exact_value_i64(vi); + add_constant_switch_case(ctx, &seen, v); + } + } + } else { + add_constant_switch_case(ctx, &seen, lhs); + if (upper_op == Token_GtEq) { + add_constant_switch_case(ctx, &seen, rhs); + } } if (is_type_string(x.type)) { |