diff options
| author | gingerBill <bill@gingerbill.org> | 2024-06-29 12:02:31 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2024-06-29 12:02:31 +0100 |
| commit | 4b71c47fd5e70f0f96e139e17637cf5de1beb2fc (patch) | |
| tree | 8540dd126a0e18b12c40864433c23dcd2a980f45 /src/check_expr.cpp | |
| parent | 704530497b166dfa6fcee8f2c95a9e492a78a024 (diff) | |
Check for unneeded `transmute` with `-vet-cast`
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2fa491417..45500e79a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3396,7 +3396,7 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forb ) { gbString oper_str = expr_to_string(x->expr); gbString to_type = type_to_string(dst_exact); - error(x->expr, "Unneeded cast of `%s` to identical type `%s`", oper_str, to_type); + error(x->expr, "Unneeded cast of '%s' to identical type '%s'", oper_str, to_type); gb_string_free(oper_str); gb_string_free(to_type); } @@ -3406,22 +3406,13 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forb x->type = type; } -gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) { +gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t, bool forbid_identical = false) { if (!is_operand_value(*o)) { error(o->expr, "'transmute' can only be applied to values"); o->mode = Addressing_Invalid; return false; } - // if (o->mode == Addressing_Constant) { - // gbString expr_str = expr_to_string(o->expr); - // error(o->expr, "Cannot transmute a constant expression: '%s'", expr_str); - // gb_string_free(expr_str); - // o->mode = Addressing_Invalid; - // o->expr = node; - // return false; - // } - Type *src_t = o->type; Type *dst_t = t; Type *src_bt = base_type(src_t); @@ -3504,6 +3495,29 @@ gb_internal bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type return true; } } + } else { + // If we check polymorphic procedures, we risk erring on + // identical casts that cannot be foreseen or otherwise + // forbidden, so just skip them. + if (forbid_identical && check_vet_flags(c) & VetFlag_Cast && + (c->curr_proc_sig == nullptr || !is_type_polymorphic(c->curr_proc_sig))) { + bool is_runtime = false; + if (c->pkg && (c->pkg->kind == Package_Runtime || c->pkg->kind == Package_Builtin)) { + is_runtime = true; + } + if (are_types_identical(src_t, dst_t) && !is_runtime) { + gbString oper_str = expr_to_string(o->expr); + gbString to_type = type_to_string(dst_t); + error(o->expr, "Unneeded transmute of '%s' to identical type '%s'", oper_str, to_type); + gb_string_free(oper_str); + gb_string_free(to_type); + } else if (is_type_internally_pointer_like(src_t) && + is_type_internally_pointer_like(dst_t)) { + gbString to_type = type_to_string(dst_t); + error(o->expr, "Use of 'transmute' where 'cast' would be preferred since the types are pointer-like", to_type); + gb_string_free(to_type); + } + } } o->mode = Addressing_Value; @@ -10734,7 +10748,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast if (o->mode != Addressing_Invalid) { switch (tc->token.kind) { case Token_transmute: - check_transmute(c, node, o, type); + check_transmute(c, node, o, type, true); break; case Token_cast: check_cast(c, o, type, true); |