From 0ab323012e4fd0303a7e41587a5919c9be028561 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 20 Feb 2025 11:12:59 +0000 Subject: Use `TypeSet` instead of `PtrSet` --- src/check_stmt.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1708f7c81..e81996566 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1446,8 +1446,8 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ Ast *nil_seen = nullptr; - PtrSet seen = {}; - defer (ptr_set_destroy(&seen)); + TypeSet seen = {}; + defer (type_set_destroy(&seen)); for (Ast *stmt : bs->stmts) { if (stmt->kind != Ast_CaseClause) { @@ -1515,7 +1515,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ GB_PANIC("Unknown type to type switch statement"); } - if (type_ptr_set_update(&seen, y.type)) { + if (type_set_update(&seen, y.type)) { TokenPos pos = cc->token.pos; gbString expr_str = expr_to_string(y.expr); error(y.expr, @@ -1569,7 +1569,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ auto unhandled = array_make(temporary_allocator(), 0, variants.count); for (Type *t : variants) { - if (!type_ptr_set_exists(&seen, t)) { + if (!type_set_exists(&seen, t)) { array_add(&unhandled, t); } } -- cgit v1.2.3 From 77b5eebf8ce090839713fc59fe0f60045524043f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 7 Apr 2025 11:57:55 +0100 Subject: Add trivial sanity check for assigning to return values within `defer` #5011 --- src/check_stmt.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index e81996566..1b44ff4d7 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2755,6 +2755,47 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) if (ctx->decl) { ctx->decl->defer_used += 1; } + + // NOTE(bill): Handling errors/warnings + + Ast *stmt = ds->stmt; + Ast *original_stmt = stmt; + + bool is_singular = true; + while (is_singular && stmt->kind == Ast_BlockStmt) { + Ast *inner_stmt = nullptr; + for (Ast *s : stmt->BlockStmt.stmts) { + if (s->kind == Ast_EmptyStmt) { + continue; + } + if (inner_stmt != nullptr) { + is_singular = false; + break; + } + inner_stmt = s; + } + + if (inner_stmt != nullptr) { + stmt = inner_stmt; + } + } + if (!is_singular) { + stmt = original_stmt; + } + + switch (stmt->kind) { + case_ast_node(as, AssignStmt, stmt); + if (as->op.kind != Token_Eq) { + break; + } + for (Ast *lhs : as->lhs) { + Entity *e = entity_of_node(lhs); + if (e && e->flags & EntityFlag_Result) { + error(lhs, "Assignments to named return values within 'defer' will not affect the value that is returned"); + } + } + case_end; + } } case_end; -- cgit v1.2.3 From 3c0ba5bb55fe59ed1644c3e61fd2a81fb856624e Mon Sep 17 00:00:00 2001 From: bogwi Date: Mon, 5 May 2025 22:39:03 +0900 Subject: CHECK 4 done The original errors: 1. `5024.odin(127:15) Error: Invalid use of a polymorphic type 'List($T)' in variable declaration` 2. `5024.odin(129:17) Error: Cannot determine polymorphic type from parameter: 'invalid type' to 'List($T)'` Are gone. We now have a single, different error: `5024.odin(124:28) Error: Unspecialized polymorphic types are not allowed in procedure parameters, got List($T)` This error points directly to the `list : List($T)` parameter within the `List_Filter` procedure definition. This seems much more relevant to the actual problem (the interaction between the generic `List_Filter` and the concrete `default_filter`) than the original error about the variable declaration. While this new error message might not be exactly pinpointing the default parameter issue, it correctly identifies the problematic procedure definition (`List_Filter`) as the source of the error, rather than the variable declaration (`my_list`). This seems like a step in the right direction for improving the error reporting for this kind of scenario. --- src/check_stmt.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1b44ff4d7..0460f5bec 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2108,10 +2108,12 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f if (init_type == nullptr) { init_type = t_invalid; } else if (is_type_polymorphic(base_type(init_type))) { + /* DISABLED: This error seems too aggressive for instantiated generic types. gbString str = type_to_string(init_type); error(vd->type, "Invalid use of a polymorphic type '%s' in variable declaration", str); gb_string_free(str); init_type = t_invalid; + */ } if (init_type == t_invalid && entity_count == 1 && (mod_flags & (Stmt_BreakAllowed|Stmt_FallthroughAllowed))) { Entity *e = entities[0]; -- cgit v1.2.3 From 7853a1db1c1ab3662767d14da055e59a7434ebcd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 29 May 2025 16:35:28 +0100 Subject: Fix #5228 --- src/check_stmt.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 0460f5bec..6cacef3ee 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2855,6 +2855,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) case Ast_BlockStmt: case Ast_IfStmt: case Ast_SwitchStmt: + case Ast_TypeSwitchStmt: if (token.kind != Token_break) { error(bs->label, "Label '%.*s' can only be used with 'break'", LIT(e->token.string)); } -- cgit v1.2.3 From d046214f67baf9c580605fa4294818e7a12fc434 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:00:33 -0400 Subject: Be strict with type switch case column alignment too This copies the same block used for regular switch cases. Fixes #4673 --- src/check_stmt.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 6cacef3ee..d92edf41d 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1593,6 +1593,20 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ error_line("\tSuggestion: Was '#partial switch' wanted?\n"); } } + + if (build_context.strict_style) { + Token stok = ss->token; + for_array(i, bs->stmts) { + Ast *stmt = bs->stmts[i]; + if (stmt->kind != Ast_CaseClause) { + continue; + } + Token ctok = stmt->CaseClause.token; + if (ctok.pos.column > stok.pos.column) { + error(ctok, "With '-strict-style', 'case' statements must share the same column as the 'switch' token"); + } + } + } } gb_internal void check_block_stmt_for_errors(CheckerContext *ctx, Ast *body) { -- cgit v1.2.3 From 2259db9a5396f598cb1c38d5f0ad73b02fce1403 Mon Sep 17 00:00:00 2001 From: Airtz Date: Tue, 24 Jun 2025 02:54:14 +0200 Subject: Better error messages --- src/check_expr.cpp | 14 +++++++------- src/check_stmt.cpp | 20 +++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3f947b6a7..fa1b4cd92 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2424,27 +2424,27 @@ gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o Type *s = src->Array.elem; Type *d = dst->Slice.elem; if (are_types_identical(s, d)) { - error_line("\tSuggestion: the array expression may be sliced with %s[:]\n", a); + error_line("\tSuggestion: The array expression may be sliced with %s[:]\n", a); } } else if (is_type_dynamic_array(src) && is_type_slice(dst)) { Type *s = src->DynamicArray.elem; Type *d = dst->Slice.elem; if (are_types_identical(s, d)) { - error_line("\tSuggestion: the dynamic array expression may be sliced with %s[:]\n", a); + error_line("\tSuggestion: The dynamic array expression may be sliced with %s[:]\n", a); } }else if (are_types_identical(src, dst) && !are_types_identical(o->type, type)) { - error_line("\tSuggestion: the expression may be directly casted to type %s\n", b); + error_line("\tSuggestion: The expression may be directly casted to type %s\n", b); } else if (are_types_identical(src, t_string) && is_type_u8_slice(dst)) { - error_line("\tSuggestion: a string may be transmuted to %s\n", b); - error_line("\t This is an UNSAFE operation as string data is assumed to be immutable, \n"); + error_line("\tSuggestion: A string may be transmuted to %s\n", b); + error_line("\t This is an UNSAFE operation as string data is assumed to be immutable,\n"); error_line("\t whereas slices in general are assumed to be mutable.\n"); } else if (is_type_u8_slice(src) && are_types_identical(dst, t_string) && o->mode != Addressing_Constant) { - error_line("\tSuggestion: the expression may be casted to %s\n", b); + error_line("\tSuggestion: The expression may be casted to %s\n", b); } else if (check_integer_exceed_suggestion(c, o, type, max_bit_size)) { return; } else if (is_expr_inferred_fixed_array(c->type_hint_expr) && is_type_array_like(type) && is_type_array_like(o->type)) { gbString s = expr_to_string(c->type_hint_expr); - error_line("\tSuggestion: make sure that `%s` is attached to the compound literal directly\n", s); + error_line("\tSuggestion: Make sure that `%s` is attached to the compound literal directly\n", s); gb_string_free(s); } else if (is_type_pointer(type) && o->mode == Addressing_Variable && diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index d92edf41d..620e9fb74 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -418,7 +418,7 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) { -gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) { +gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs, String context_name) { if (rhs->mode == Addressing_Invalid) { return nullptr; } @@ -430,7 +430,7 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O Ast *node = unparen_expr(lhs->expr); - check_no_copy_assignment(*rhs, str_lit("assignment")); + check_no_copy_assignment(*rhs, context_name); // NOTE(bill): Ignore assignments to '_' if (is_blank_ident(node)) { @@ -630,7 +630,7 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O ctx->bit_field_bit_size = lhs_e->Variable.bit_field_bit_size; } - check_assignment(ctx, rhs, assignment_type, str_lit("assignment")); + check_assignment(ctx, rhs, assignment_type, context_name); ctx->bit_field_bit_size = prev_bit_field_bit_size; @@ -2418,7 +2418,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { isize lhs_count = as->lhs.count; if (lhs_count == 0) { - error(as->op, "Missing lhs in assignment statement"); + error(as->op, "Missing LHS in assignment statement"); return; } @@ -2451,7 +2451,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { if (lhs_to_ignore[i]) { continue; } - check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i]); + check_assignment_variable(ctx, &lhs_operands[i], &rhs_operands[i], str_lit("assignment")); } if (lhs_count != rhs_count) { error(as->lhs[0], "Assignment count mismatch '%td' = '%td'", lhs_count, rhs_count); @@ -2461,11 +2461,11 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { // a += 1; // Single-sided Token op = as->op; if (as->lhs.count != 1 || as->rhs.count != 1) { - error(op, "Assignment operation '%.*s' requires single-valued expressions", LIT(op.string)); + error(op, "Assignment operator '%.*s' requires single-valued operands", LIT(op.string)); return; } if (!gb_is_between(op.kind, Token__AssignOpBegin+1, Token__AssignOpEnd-1)) { - error(op, "Unknown Assignment operation '%.*s'", LIT(op.string)); + error(op, "Unknown assignment operator '%.*s'", LIT(op.string)); return; } Operand lhs = {Addressing_Invalid}; @@ -2474,7 +2474,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { ast_node(be, BinaryExpr, binary_expr); be->op = op; be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add)); - // NOTE(bill): Only use the first one will be used + // NOTE(bill): Only use the first one will be used be->left = as->lhs[0]; be->right = as->rhs[0]; @@ -2482,7 +2482,9 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { check_binary_expr(ctx, &rhs, binary_expr, nullptr, true); if (rhs.mode != Addressing_Invalid) { // NOTE(bill): Only use the first one will be used - check_assignment_variable(ctx, &lhs, &rhs); + be->op.string = substring(be->op.string, 0, 1); + rhs.expr = binary_expr; + check_assignment_variable(ctx, &lhs, &rhs, str_lit("assignment operation")); } } } -- cgit v1.2.3 From fb3bccdd3e31c8c237721f6658722e0bfb54e71c Mon Sep 17 00:00:00 2001 From: Airtz Date: Tue, 24 Jun 2025 16:09:42 +0200 Subject: Fix an oversight for operators with more than 2 chars --- src/check_stmt.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/check_stmt.cpp') diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 620e9fb74..07801b477 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2481,8 +2481,7 @@ gb_internal void check_assign_stmt(CheckerContext *ctx, Ast *node) { check_expr(ctx, &lhs, as->lhs[0]); check_binary_expr(ctx, &rhs, binary_expr, nullptr, true); if (rhs.mode != Addressing_Invalid) { - // NOTE(bill): Only use the first one will be used - be->op.string = substring(be->op.string, 0, 1); + be->op.string = substring(be->op.string, 0, be->op.string.len - 1); rhs.expr = binary_expr; check_assignment_variable(ctx, &lhs, &rhs, str_lit("assignment operation")); } -- cgit v1.2.3