From 6496432b8056eeecd9ba396148f7c458a5cc02ac Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 28 Jun 2024 22:49:24 -0400 Subject: [PATCH 1/2] Add `-vet-identical-cast` --- src/build_settings.cpp | 5 ++++- src/check_expr.cpp | 23 +++++++++++++++++++++-- src/main.cpp | 7 +++++++ 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 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 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) { From b3caae6db4da4b604d5812d587b773674d72ccf3 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 28 Jun 2024 22:49:48 -0400 Subject: [PATCH 2/2] Keep `-vet` happy --- core/encoding/uuid/generation.odin | 4 ++-- core/flags/internal_rtti.odin | 2 +- core/os/os_darwin.odin | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/encoding/uuid/generation.odin b/core/encoding/uuid/generation.odin index cf29df378..7c9d4b80c 100644 --- a/core/encoding/uuid/generation.odin +++ b/core/encoding/uuid/generation.odin @@ -106,8 +106,8 @@ generate_v6 :: proc(clock_seq: Maybe(u16) = nil, node: Maybe([6]u8) = nil, times temporary: [2]u8 bytes_generated := rand.read(temporary[:]) assert(bytes_generated == 2, "RNG failed to generate 2 bytes for UUID v1.") - result[8] |= cast(u8)temporary[0] & 0x3F - result[9] = cast(u8)temporary[1] + result[8] |= temporary[0] & 0x3F + result[9] = temporary[1] } if realized_node, ok := node.?; ok { diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin index c9b1f59fd..f19f52ba5 100644 --- a/core/flags/internal_rtti.odin +++ b/core/flags/internal_rtti.odin @@ -184,7 +184,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: case 16: (cast(^u16) ptr)^ = cast(u16) value case 32: (cast(^u32) ptr)^ = cast(u32) value case 64: (cast(^u64) ptr)^ = cast(u64) value - case 128: (cast(^u128) ptr)^ = cast(u128) value + case 128: (cast(^u128) ptr)^ = value } } diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 877a90bf1..b1fde77b3 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -555,7 +555,7 @@ open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno err := fchmod(handle, cast(u16)mode) if err != 0 { _unix_close(handle) - return INVALID_HANDLE, cast(Errno)err + return INVALID_HANDLE, err } }