Browse Source

Fix Duplicate integer switch case values incorrectly consider its absolute value #502

(Hashing proc was wrong for big ints)
gingerBill 5 years ago
parent
commit
8bec324779
2 changed files with 25 additions and 17 deletions
  1. 19 16
      src/check_stmt.cpp
  2. 6 1
      src/exact_value.cpp

+ 19 - 16
src/check_stmt.cpp

@@ -550,6 +550,7 @@ struct TypeAndToken {
 	Token token;
 };
 
+
 void add_constant_switch_case(CheckerContext *ctx, Map<TypeAndToken> *seen, Operand operand, bool use_expr = true) {
 	if (operand.mode != Addressing_Constant) {
 		return;
@@ -567,23 +568,25 @@ void add_constant_switch_case(CheckerContext *ctx, Map<TypeAndToken> *seen, Oper
 		multi_map_get_all(seen, key, taps);
 		for (isize i = 0; i < count; i++) {
 			TypeAndToken tap = taps[i];
-			if (are_types_identical(operand.type, tap.type)) {
-				TokenPos pos = tap.token.pos;
-				if (use_expr) {
-					gbString expr_str = expr_to_string(operand.expr);
-					error(operand.expr,
-					      "Duplicate case '%s'\n"
-					      "\tprevious case at %.*s(%td:%td)",
-					      expr_str,
-					      LIT(pos.file), pos.line, pos.column);
-					gb_string_free(expr_str);
-				} else {
-					error(operand.expr,
-					      "Duplicate case found with previous case at %.*s(%td:%td)",
-					      LIT(pos.file), pos.line, pos.column);
-				}
-				return;
+			if (!are_types_identical(operand.type, tap.type)) {
+				continue;
 			}
+
+			TokenPos pos = tap.token.pos;
+			if (use_expr) {
+				gbString expr_str = expr_to_string(operand.expr);
+				error(operand.expr,
+				      "Duplicate case '%s'\n"
+				      "\tprevious case at %.*s(%td:%td)",
+				      expr_str,
+				      LIT(pos.file), pos.line, pos.column);
+				gb_string_free(expr_str);
+			} else {
+				error(operand.expr,
+				      "Duplicate case found with previous case at %.*s(%td:%td)",
+				      LIT(pos.file), pos.line, pos.column);
+			}
+			return;
 		}
 	}
 

+ 6 - 1
src/exact_value.cpp

@@ -71,7 +71,12 @@ HashKey hash_exact_value(ExactValue v) {
 	case ExactValue_String:
 		return hash_string(v.value_string);
 	case ExactValue_Integer:
-		return hashing_proc(big_int_ptr(&v.value_integer), v.value_integer.len * gb_size_of(u64));
+		{
+			HashKey key = hashing_proc(big_int_ptr(&v.value_integer), v.value_integer.len * gb_size_of(u64));
+			u8 last = (u8)v.value_integer.neg;
+			key.key = (key.key ^ last) * 0x100000001b3ll;
+			return key;
+		}
 	case ExactValue_Float:
 		return hash_f64(v.value_float);
 	case ExactValue_Pointer: