aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 891378b99..7d2f10c95 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3310,7 +3310,7 @@ gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type)
}
-gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
+gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forbid_identical = false) {
if (!is_operand_value(*x)) {
error(x->expr, "Only values can be casted");
x->mode = Addressing_Invalid;
@@ -3382,6 +3382,25 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) {
add_package_dependency(c, "runtime", "gnu_f2h_ieee", REQUIRE);
}
}
+ if (forbid_identical && check_vet_flags(c) & VetFlag_IdenticalCast) {
+ Type *src_exact = x->type;
+ Type *dst_exact = type;
+
+ if (src_exact != nullptr &&
+ dst_exact != nullptr &&
+ // If we check polymorphic procedures, we risk erring on
+ // identical casts that cannot be foreseen or otherwise
+ // forbidden, so just skip them.
+ (c->curr_proc_sig == nullptr || !is_type_polymorphic(c->curr_proc_sig)) &&
+ src_exact == dst_exact)
+ {
+ 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);
+ gb_string_free(oper_str);
+ gb_string_free(to_type);
+ }
+ }
}
x->type = type;
@@ -10718,7 +10737,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
check_transmute(c, node, o, type);
break;
case Token_cast:
- check_cast(c, o, type);
+ check_cast(c, o, type, true);
break;
default:
error(node, "Invalid AST: Invalid casting expression");