aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-28 22:49:24 -0400
committerFeoramund <161657516+Feoramund@users.noreply.github.com>2024-06-28 23:14:03 -0400
commit6496432b8056eeecd9ba396148f7c458a5cc02ac (patch)
tree256ec29a6a658615d9532d520a6504388f89ae46 /src
parent06652bebce111640930a513c825e59f7b37bbd4f (diff)
Add `-vet-identical-cast`
Diffstat (limited to 'src')
-rw-r--r--src/build_settings.cpp5
-rw-r--r--src/check_expr.cpp23
-rw-r--r--src/main.cpp7
3 files changed, 32 insertions, 3 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp
index 4b348256b..f44179da0 100644
--- a/src/build_settings.cpp
+++ b/src/build_settings.cpp
@@ -742,10 +742,11 @@ enum VetFlags : u64 {
VetFlag_UnusedVariables = 1u<<5,
VetFlag_UnusedImports = 1u<<6,
VetFlag_Deprecated = 1u<<7,
+ VetFlag_IdenticalCast = 1u<<8,
VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports,
- VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated,
+ VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated|VetFlag_IdenticalCast,
VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam,
};
@@ -769,6 +770,8 @@ u64 get_vet_flag_from_name(String const &name) {
return VetFlag_Semicolon;
} else if (name == "deprecated") {
return VetFlag_Deprecated;
+ } else if (name == "identical-cast") {
+ return VetFlag_IdenticalCast;
}
return VetFlag_NONE;
}
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");
diff --git a/src/main.cpp b/src/main.cpp
index b24796559..aa701b61b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -300,6 +300,7 @@ enum BuildFlagKind {
BuildFlag_VetUsingParam,
BuildFlag_VetStyle,
BuildFlag_VetSemicolon,
+ BuildFlag_VetIdenticalCast,
BuildFlag_CustomAttribute,
BuildFlag_IgnoreUnknownAttributes,
@@ -499,6 +500,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_VetUsingParam, str_lit("vet-using-param"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_VetStyle, str_lit("vet-style"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check);
+ add_flag(&build_flags, BuildFlag_VetIdenticalCast, str_lit("vet-identical-cast"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true);
add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check);
@@ -1152,6 +1154,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break;
case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break;
case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break;
+ case BuildFlag_VetIdenticalCast: build_context.vet_flags |= VetFlag_IdenticalCast; break;
case BuildFlag_CustomAttribute:
{
@@ -2243,6 +2246,10 @@ gb_internal void print_show_help(String const arg0, String const &command) {
print_usage_line(1, "-vet-semicolon");
print_usage_line(2, "Errs on unneeded semicolons.");
print_usage_line(0, "");
+
+ print_usage_line(1, "-vet-identical-cast");
+ print_usage_line(2, "Errs on casting a value to its own type.");
+ print_usage_line(0, "");
}
if (check) {