checker: prompt error on implicit int overflow by literal (#6410)
							parent
							
								
									34884c1631
								
							
						
					
					
						commit
						5086fd537c
					
				|  | @ -182,10 +182,7 @@ fn test_int_decl() { | |||
| 	assert typeof(x3) == 'int' | ||||
| 	assert typeof(x4) == 'int' | ||||
| 	assert typeof(x5) == 'int' | ||||
| 	// integers are always 'int' by default
 | ||||
| 	x6 := 989898932113111 | ||||
| 	x7 := u64(-321314588900011) | ||||
| 	assert typeof(x6) == 'int' | ||||
| 	assert typeof(x7) == 'u64' | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -178,8 +178,8 @@ fn test_mt19937_u64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_mt19937_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		mut rng := mt19937.MT19937RNG{} | ||||
| 		rng.seed(seed) | ||||
|  |  | |||
|  | @ -168,8 +168,8 @@ fn test_musl_u64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_musl_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		mut rng := musl.MuslRNG{} | ||||
| 		rng.seed(seed) | ||||
|  |  | |||
|  | @ -169,8 +169,8 @@ fn test_pcg32_u64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_pcg32_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		mut rng := pcg32.PCG32RNG{} | ||||
| 		rng.seed(seed) | ||||
|  |  | |||
|  | @ -100,8 +100,8 @@ fn test_rand_i64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_rand_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for _ in 0 .. rnd_count { | ||||
| 		value := rand.int31() | ||||
| 		assert value >= 0 | ||||
|  |  | |||
|  | @ -168,8 +168,8 @@ fn test_splitmix64_u64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_splitmix64_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		mut rng := splitmix64.SplitMix64RNG{} | ||||
| 		rng.seed(seed) | ||||
|  |  | |||
|  | @ -237,8 +237,8 @@ fn test_sys_rng_i64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_sys_rng_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		seed_data := [seed] | ||||
| 		mut rng := sys.SysRNG{} | ||||
|  |  | |||
|  | @ -168,8 +168,8 @@ fn test_wyrand_u64_in_range() { | |||
| } | ||||
| 
 | ||||
| fn test_wyrand_int31() { | ||||
| 	max_u31 := 0x7FFFFFFF | ||||
| 	sign_mask := 0x80000000 | ||||
| 	max_u31 := int(0x7FFFFFFF) | ||||
| 	sign_mask := int(0x80000000) | ||||
| 	for seed in seeds { | ||||
| 		mut rng := wyrand.WyRandRNG{} | ||||
| 		rng.seed(seed) | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ import v.errors | |||
| const ( | ||||
| 	max_nr_errors                 = 300 | ||||
| 	match_exhaustive_cutoff_limit = 10 | ||||
| 	enum_min                      = int(0x80000000) | ||||
| 	enum_max                      = 0x7FFFFFFF | ||||
| 	int_min                       = int(0x80000000) | ||||
| 	int_max                       = 0x7FFFFFFF | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
|  | @ -1682,7 +1682,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) { | |||
| 			match field.expr as field_expr { | ||||
| 				ast.IntegerLiteral { | ||||
| 					val := field_expr.val.i64() | ||||
| 					if val < enum_min || val > enum_max { | ||||
| 					if val < int_min || val > int_max { | ||||
| 						c.error('enum value `$val` overflows int', field_expr.pos) | ||||
| 					} else if !decl.is_multi_allowed && int(val) in seen { | ||||
| 						c.error('enum value `$val` already exists', field_expr.pos) | ||||
|  | @ -1707,7 +1707,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) { | |||
| 		} else { | ||||
| 			if seen.len > 0 { | ||||
| 				last := seen[seen.len - 1] | ||||
| 				if last == enum_max { | ||||
| 				if last == int_max { | ||||
| 					c.error('enum value overflows', field.pos) | ||||
| 				} | ||||
| 				seen << last + 1 | ||||
|  | @ -1805,6 +1805,29 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { | |||
| 		right_type := assign_stmt.right_types[i] | ||||
| 		if is_decl { | ||||
| 			left_type = c.table.mktyp(right_type) | ||||
| 			if left_type == table.int_type { | ||||
| 				mut expr := right | ||||
| 				mut negative := false | ||||
| 				if right is ast.PrefixExpr { | ||||
| 					expr = right.right | ||||
| 					if right.op == .minus { | ||||
| 						negative = true | ||||
| 					} | ||||
| 				} | ||||
| 				if expr is ast.IntegerLiteral { | ||||
| 					mut is_large := false | ||||
| 					if expr.val.len > 8 { | ||||
| 						val := expr.val.i64() | ||||
| 						if (!negative && val > int_max) || (negative && -val < int_min) { | ||||
| 							is_large = true | ||||
| 						} | ||||
| 					} | ||||
| 					if is_large { | ||||
| 						c.error('overflow in implicit type `int`, use explicit type casting instead', | ||||
| 							expr.pos) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			// we are unwrapping here instead if check_expr_opt_call currently
 | ||||
| 			if left_type.has_flag(.optional) { | ||||
| 				left_type = left_type.clear_flag(.optional) | ||||
|  |  | |||
|  | @ -0,0 +1,14 @@ | |||
| vlib/v/checker/tests/overflow_int_err.vv:4:8: error: overflow in implicit type `int`, use explicit type casting instead | ||||
|     2 |     a := -2147483648 | ||||
|     3 |     b := 2147483647 | ||||
|     4 |     c := -2147483649 | ||||
|       |           ~~~~~~~~~~ | ||||
|     5 |     d := 2147483648 | ||||
|     6 |     println(a) | ||||
| vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead | ||||
|     3 |     b := 2147483647 | ||||
|     4 |     c := -2147483649 | ||||
|     5 |     d := 2147483648 | ||||
|       |          ~~~~~~~~~~ | ||||
|     6 |     println(a) | ||||
|     7 |     println(b) | ||||
|  | @ -0,0 +1,10 @@ | |||
| fn main() { | ||||
| 	a := -2147483648 | ||||
| 	b := 2147483647 | ||||
| 	c := -2147483649 | ||||
| 	d := 2147483648 | ||||
| 	println(a) | ||||
| 	println(b) | ||||
| 	println(c) | ||||
| 	println(d) | ||||
| } | ||||
		Loading…
	
		Reference in New Issue