Browse Source

Add `-vet-identical-cast`

Feoramund 1 year ago
parent
commit
6496432b80
3 changed files with 32 additions and 3 deletions
  1. 4 1
      src/build_settings.cpp
  2. 21 2
      src/check_expr.cpp
  3. 7 0
      src/main.cpp

+ 4 - 1
src/build_settings.cpp

@@ -742,10 +742,11 @@ enum VetFlags : u64 {
 	VetFlag_UnusedVariables = 1u<<5,
 	VetFlag_UnusedVariables = 1u<<5,
 	VetFlag_UnusedImports   = 1u<<6,
 	VetFlag_UnusedImports   = 1u<<6,
 	VetFlag_Deprecated      = 1u<<7,
 	VetFlag_Deprecated      = 1u<<7,
+	VetFlag_IdenticalCast   = 1u<<8,
 
 
 	VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports,
 	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,
 	VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam,
 };
 };
@@ -769,6 +770,8 @@ u64 get_vet_flag_from_name(String const &name) {
 		return VetFlag_Semicolon;
 		return VetFlag_Semicolon;
 	} else if (name == "deprecated") {
 	} else if (name == "deprecated") {
 		return VetFlag_Deprecated;
 		return VetFlag_Deprecated;
+	} else if (name == "identical-cast") {
+		return VetFlag_IdenticalCast;
 	}
 	}
 	return VetFlag_NONE;
 	return VetFlag_NONE;
 }
 }

+ 21 - 2
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)) {
 	if (!is_operand_value(*x)) {
 		error(x->expr, "Only values can be casted");
 		error(x->expr, "Only values can be casted");
 		x->mode = Addressing_Invalid;
 		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);
 				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;
 	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);
 				check_transmute(c, node, o, type);
 				break;
 				break;
 			case Token_cast:
 			case Token_cast:
-				check_cast(c, o, type);
+				check_cast(c, o, type, true);
 				break;
 				break;
 			default:
 			default:
 				error(node, "Invalid AST: Invalid casting expression");
 				error(node, "Invalid AST: Invalid casting expression");

+ 7 - 0
src/main.cpp

@@ -300,6 +300,7 @@ enum BuildFlagKind {
 	BuildFlag_VetUsingParam,
 	BuildFlag_VetUsingParam,
 	BuildFlag_VetStyle,
 	BuildFlag_VetStyle,
 	BuildFlag_VetSemicolon,
 	BuildFlag_VetSemicolon,
+	BuildFlag_VetIdenticalCast,
 
 
 	BuildFlag_CustomAttribute,
 	BuildFlag_CustomAttribute,
 	BuildFlag_IgnoreUnknownAttributes,
 	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_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_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_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_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);
 	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_VetUsingParam:      build_context.vet_flags |= VetFlag_UsingParam;      break;
 						case BuildFlag_VetStyle:           build_context.vet_flags |= VetFlag_Style;           break;
 						case BuildFlag_VetStyle:           build_context.vet_flags |= VetFlag_Style;           break;
 						case BuildFlag_VetSemicolon:       build_context.vet_flags |= VetFlag_Semicolon;       break;
 						case BuildFlag_VetSemicolon:       build_context.vet_flags |= VetFlag_Semicolon;       break;
+						case BuildFlag_VetIdenticalCast:   build_context.vet_flags |= VetFlag_IdenticalCast;   break;
 
 
 						case BuildFlag_CustomAttribute:
 						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(1, "-vet-semicolon");
 		print_usage_line(2, "Errs on unneeded semicolons.");
 		print_usage_line(2, "Errs on unneeded semicolons.");
 		print_usage_line(0, "");
 		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) {
 	if (check) {