diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2022-07-28 16:01:18 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-28 16:01:18 +0200 |
| commit | 674ebe395f1feba70becaac75c4fb9451f74f84c (patch) | |
| tree | 78589612bd458269904d53de46d0accf4f58a7af /src/check_stmt.cpp | |
| parent | 9746e25784c208cf8a7883bcb2e1ac2317117aeb (diff) | |
| parent | 96eecaab54cea02499e9cf418aa39eb5a9c9ec75 (diff) | |
Merge branch 'master' into master
Diffstat (limited to 'src/check_stmt.cpp')
| -rw-r--r-- | src/check_stmt.cpp | 190 |
1 files changed, 80 insertions, 110 deletions
diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 94b7561c7..a6f6f1a7d 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -490,6 +490,14 @@ void check_stmt(CheckerContext *ctx, Ast *node, u32 flags) { out &= ~StateFlag_no_bounds_check; } + if (in & StateFlag_no_type_assert) { + out |= StateFlag_no_type_assert; + out &= ~StateFlag_type_assert; + } else if (in & StateFlag_type_assert) { + out |= StateFlag_type_assert; + out &= ~StateFlag_no_type_assert; + } + ctx->state_flags = out; } @@ -689,54 +697,6 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, b return true; } - -struct TypeAndToken { - Type *type; - Token token; -}; - - -void add_constant_switch_case(CheckerContext *ctx, PtrMap<uintptr, TypeAndToken> *seen, Operand operand, bool use_expr = true) { - if (operand.mode != Addressing_Constant) { - return; - } - if (operand.value.kind == ExactValue_Invalid) { - return; - } - - uintptr key = hash_exact_value(operand.value); - TypeAndToken *found = map_get(seen, key); - if (found != nullptr) { - isize count = multi_map_count(seen, key); - TypeAndToken *taps = gb_alloc_array(temporary_allocator(), TypeAndToken, count); - - multi_map_get_all(seen, key, taps); - for (isize i = 0; i < count; i++) { - TypeAndToken tap = taps[i]; - if (!are_types_identical(operand.type, tap.type)) { - continue; - } - - TokenPos pos = tap.token.pos; - if (use_expr) { - gbString expr_str = expr_to_string(operand.expr); - error(operand.expr, - "Duplicate case '%s'\n" - "\tprevious case at %s", - expr_str, - token_pos_to_string(pos)); - gb_string_free(expr_str); - } else { - error(operand.expr, "Duplicate case found with previous case at %s", token_pos_to_string(pos)); - } - return; - } - } - - TypeAndToken tap = {operand.type, ast_token(operand.expr)}; - multi_map_insert(seen, key, tap); -} - void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { ast_node(irs, UnrollRangeStmt, node); check_open_scope(ctx, node); @@ -961,7 +921,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { } } - PtrMap<uintptr, TypeAndToken> seen = {}; // NOTE(bill): Multimap, Key: ExactValue + SeenMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); @@ -1001,9 +961,9 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { TokenKind upper_op = Token_Invalid; switch (be->op.kind) { - case Token_Ellipsis: upper_op = Token_GtEq; break; - case Token_RangeFull: upper_op = Token_GtEq; break; - case Token_RangeHalf: upper_op = Token_Gt; break; + case Token_Ellipsis: upper_op = Token_LtEq; break; + case Token_RangeFull: upper_op = Token_LtEq; break; + case Token_RangeHalf: upper_op = Token_Lt; break; default: GB_PANIC("Invalid range operator"); break; } @@ -1024,45 +984,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { Operand b1 = rhs; check_comparison(ctx, &a1, &b1, Token_LtEq); - 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); - } - } + add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs); if (is_type_string(x.type)) { // NOTE(bill): Force dependency for strings here @@ -1107,7 +1029,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { continue; } update_untyped_expr_type(ctx, z.expr, x.type, !is_type_untyped(x.type)); - add_constant_switch_case(ctx, &seen, y); + add_to_seen_map(ctx, &seen, y); } } } @@ -1143,7 +1065,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { if (unhandled.count == 1) { error_no_newline(node, "Unhandled switch case: %.*s", LIT(unhandled[0]->token.string)); } else { - error_no_newline(node, "Unhandled switch cases: "); + error(node, "Unhandled switch cases:"); for_array(i, unhandled) { Entity *f = unhandled[i]; error_line("\t%.*s\n", LIT(f->token.string)); @@ -1459,6 +1381,18 @@ bool all_operands_valid(Array<Operand> const &operands) { return true; } +bool check_stmt_internal_builtin_proc_id(Ast *expr, BuiltinProcId *id_) { + BuiltinProcId id = BuiltinProc_Invalid; + Entity *e = entity_of_node(expr); + if (e != nullptr && e->kind == Entity_Builtin) { + if (e->Builtin.id && e->Builtin.id != BuiltinProc_DIRECTIVE) { + id = cast(BuiltinProcId)e->Builtin.id; + } + } + if (id_) *id_ = id; + return id != BuiltinProc_Invalid; +} + void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { u32 mod_flags = flags & (~Stmt_FallthroughAllowed); switch (node->kind) { @@ -1483,29 +1417,43 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { if (kind == Expr_Stmt) { return; } - Ast *expr = strip_or_return_expr(operand.expr); + Ast *expr = strip_or_return_expr(operand.expr); if (expr->kind == Ast_CallExpr) { + BuiltinProcId builtin_id = BuiltinProc_Invalid; + bool do_require = false; + AstCallExpr *ce = &expr->CallExpr; - Type *t = type_of_expr(ce->proc); - if (is_type_proc(t)) { - if (t->Proc.require_results) { - gbString expr_str = expr_to_string(ce->proc); - error(node, "'%s' requires that its results must be handled", expr_str); - gb_string_free(expr_str); - } + Type *t = base_type(type_of_expr(ce->proc)); + if (t->kind == Type_Proc) { + do_require = t->Proc.require_results; + } else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) { + auto const &bp = builtin_procs[builtin_id]; + do_require = bp.kind == Expr_Expr && !bp.ignore_results; + } + if (do_require) { + gbString expr_str = expr_to_string(ce->proc); + error(node, "'%s' requires that its results must be handled", expr_str); + gb_string_free(expr_str); } return; } else if (expr->kind == Ast_SelectorCallExpr) { + BuiltinProcId builtin_id = BuiltinProc_Invalid; + bool do_require = false; + AstSelectorCallExpr *se = &expr->SelectorCallExpr; ast_node(ce, CallExpr, se->call); - Type *t = type_of_expr(ce->proc); - if (is_type_proc(t)) { - if (t->Proc.require_results) { - gbString expr_str = expr_to_string(ce->proc); - error(node, "'%s' requires that its results must be handled", expr_str); - gb_string_free(expr_str); - } + Type *t = base_type(type_of_expr(ce->proc)); + if (t->kind == Type_Proc) { + do_require = t->Proc.require_results; + } else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) { + auto const &bp = builtin_procs[builtin_id]; + do_require = bp.kind == Expr_Expr && !bp.ignore_results; + } + if (do_require) { + gbString expr_str = expr_to_string(ce->proc); + error(node, "'%s' requires that its results must be handled", expr_str); + gb_string_free(expr_str); } return; } @@ -2194,7 +2142,26 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } if (new_name_count == 0) { - error(node, "No new declarations on the lhs"); + begin_error_block(); + error(node, "No new declarations on the left hand side"); + bool all_underscore = true; + for_array(i, vd->names) { + Ast *name = vd->names[i]; + if (name->kind == Ast_Ident) { + if (!is_blank_ident(name)) { + all_underscore = false; + break; + } + } else { + all_underscore = false; + break; + } + } + if (all_underscore) { + error_line("\tSuggestion: Try changing the declaration (:=) to an assignment (=)\n"); + } + + end_error_block(); } Type *init_type = nullptr; @@ -2230,7 +2197,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { e->state = EntityState_Resolved; } ac.link_name = handle_link_name(ctx, e->token, ac.link_name, ac.link_prefix); - e->Variable.thread_local_model = ac.thread_local_model; if (ac.link_name.len > 0) { e->Variable.link_name = ac.link_name; @@ -2260,6 +2226,10 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } e->Variable.thread_local_model = ac.thread_local_model; } + + if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) { + error(e->token, "@(thread_local) is not supported for this target platform"); + } if (ac.is_static && ac.thread_local_model != "") { |