Skip to content

Commit

Permalink
Warn on suffix-less integer literals outside Int64's range (#12427)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored Sep 5, 2022
1 parent a9ce021 commit 8b801a5
Show file tree
Hide file tree
Showing 34 changed files with 302 additions and 216 deletions.
4 changes: 2 additions & 2 deletions spec/compiler/interpreter/primitives_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ describe Crystal::Repl::Interpreter do
assert_overflows 1_i16 + 32767
assert_overflows 1_u32 + 4294967295
assert_overflows 1_i32 + 2147483647
assert_overflows 1_u64 + 18446744073709551615
assert_overflows 1_u64 + 18446744073709551615u64
assert_overflows 1_i64 + 9223372036854775807
end

Expand All @@ -328,7 +328,7 @@ describe Crystal::Repl::Interpreter do
assert_overflows 1_u32 - 2
assert_overflows 1_i32 - 2147483650
assert_overflows 1_u64 - 2
assert_overflows 1_i64 - 9223372036854775810
assert_overflows 1_i64 - 9223372036854775810u64
end

context "*" do
Expand Down
4 changes: 4 additions & 0 deletions spec/compiler/macro/macro_methods_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,10 @@ module Crystal
assert_macro %({{parse_type :Foo }}), %(nil)
end
end

it "exposes syntax warnings" do
assert_warning %({% parse_type "Foo(0x8000_0000_0000_0000)" %}), "Warning: 0x8000_0000_0000_0000 doesn't fit in an Int64, try using the suffix u64 or i128"
end
end

describe "printing" do
Expand Down
30 changes: 30 additions & 0 deletions spec/compiler/parser/warnings_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require "../../support/syntax"

private def assert_parser_warning(source, message, *, file = __FILE__, line = __LINE__)
parser = Parser.new(source)
parser.filename = "/foo/bar/baz.cr"
node = parser.parse

warnings = parser.warnings.infos
warnings.size.should eq(1), file: file, line: line
warnings[0].should contain(message), file: file, line: line
end

describe "Parser warnings" do
it "warns on suffix-less UInt64 literals > Int64::MAX" do
values = [
"9223372036854775808", # Int64::MAX + 1
"9999999999999999999",
"10000000000000000000",
"18446744073709551615", # UInt64::MAX
"0x8000_0000_0000_0000",
"0xFFFF_FFFF_FFFF_FFFF",
]

values.each do |value|
assert_parser_warning value, "Warning: #{value} doesn't fit in an Int64, try using the suffix u64 or i128"
assert_parser_warning "Foo(#{value})", "Warning: #{value} doesn't fit in an Int64, try using the suffix u64 or i128"
assert_parser_warning "{{ #{value} }}", "Warning: #{value} doesn't fit in an Int64, try using the suffix u64 or i128"
end
end
end
8 changes: 8 additions & 0 deletions spec/compiler/semantic/warnings_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -761,4 +761,12 @@ describe "Semantic: warnings" do
CR
end
end

it "exposes syntax warnings" do
assert_warning UInt64::MAX.to_s, "Warning: #{UInt64::MAX} doesn't fit in an Int64, try using the suffix u64 or i128"
end

it "exposes syntax warnings after macro interpolation" do
assert_warning "{% begin %}0x8000_0000_0000_000{{ 0 }}{% end %}", "Warning: 0x8000_0000_0000_0000 doesn't fit in an Int64, try using the suffix u64 or i128"
end
end
10 changes: 6 additions & 4 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ def assert_type(str, *, inject_primitives = false, flags = nil, file = __FILE__,
end

def semantic(code : String, wants_doc = false, inject_primitives = false, flags = nil, filename = nil)
node = parse(code, wants_doc: wants_doc, filename: filename)
warnings = WarningCollection.new
node = parse(code, wants_doc: wants_doc, filename: filename, warnings: warnings)
node = inject_primitives(node) if inject_primitives
semantic node, wants_doc: wants_doc, flags: flags
semantic node, warnings: warnings, wants_doc: wants_doc, flags: flags
end

private def inject_primitives(node : ASTNode)
Expand All @@ -66,8 +67,9 @@ private def inject_primitives(node : ASTNode)
end
end

def semantic(node : ASTNode, wants_doc = false, flags = nil)
def semantic(node : ASTNode, *, warnings = nil, wants_doc = false, flags = nil)
program = new_program
program.warnings = warnings if warnings
program.flags.concat(flags.split) if flags
program.wants_doc = wants_doc
node = program.normalize node
Expand Down Expand Up @@ -139,7 +141,7 @@ end
def assert_warning(code, message, *, file = __FILE__, line = __LINE__)
warning_failures = warnings_result(code)
warning_failures.size.should eq(1), file: file, line: line
warning_failures[0].should start_with(message), file: file, line: line
warning_failures[0].should contain(message), file: file, line: line
end

def assert_macro(macro_body, expected, args = nil, *, expected_pragmas = nil, flags = nil, file = __FILE__, line = __LINE__)
Expand Down
14 changes: 7 additions & 7 deletions spec/std/big/big_int_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -504,12 +504,12 @@ describe "BigInt" do
big = BigInt.new("9" * 32)
expect_raises(OverflowError) { big.to_i64 }
expect_raises(OverflowError) { big.to_u64 }
big.to_i64!.should eq(-8814407033341083649) # 99999999999999999999999999999999 - 5421010862428*(2**64)
big.to_u64!.should eq(9632337040368467967) # 99999999999999999999999999999999 - 5421010862427*(2**64)
big.to_i64!.should eq(-8814407033341083649) # 99999999999999999999999999999999 - 5421010862428*(2**64)
big.to_u64!.should eq(9632337040368467967u64) # 99999999999999999999999999999999 - 5421010862427*(2**64)
end

it "between 63 and 64 bits" do
big = BigInt.new(i = 9999999999999999999)
big = BigInt.new(i = 9999999999999999999u64)
expect_raises(OverflowError) { big.to_i64 }
big.to_u64.should eq(i)
big.to_i64!.should eq(-8446744073709551617) # 9999999999999999999 - 2**64
Expand All @@ -529,15 +529,15 @@ describe "BigInt" do
big.to_i64.should eq(i)
expect_raises(OverflowError) { big.to_u64 }
big.to_i64!.should eq(i)
big.to_u64!.should eq(18446744073709541617) # -9999 + 2**64
big.to_u64!.should eq(18446744073709541617u64) # -9999 + 2**64
end

it "negative between 32 and 63 bits" do
big = BigInt.new(i = -9999999999999)
big.to_i64.should eq(i)
expect_raises(OverflowError) { big.to_u64 }
big.to_i64!.should eq(i)
big.to_u64!.should eq(18446734073709551617) # -9999999999999 + 2**64
big.to_u64!.should eq(18446734073709551617u64) # -9999999999999 + 2**64
end

it "negative between 63 and 64 bits" do
Expand All @@ -552,8 +552,8 @@ describe "BigInt" do
big = BigInt.new("-" + "9" * 20)
expect_raises(OverflowError) { big.to_i64 }
expect_raises(OverflowError) { big.to_u64 }
big.to_i64!.should eq(-7766279631452241919) # -9999999999999999999 + 5*(2**64)
big.to_u64!.should eq(10680464442257309697) # -9999999999999999999 + 6*(2**64)
big.to_i64!.should eq(-7766279631452241919) # -9999999999999999999 + 5*(2**64)
big.to_u64!.should eq(10680464442257309697u64) # -9999999999999999999 + 6*(2**64)

big = BigInt.new("-" + "9" * 32)
expect_raises(OverflowError) { big.to_i64 }
Expand Down
72 changes: 36 additions & 36 deletions spec/std/crystal/compiler_rt/ashlti3_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,40 @@ require "./spec_helper"
# Ported from https://github.com/llvm/llvm-project/blob/ce59ccd04023cab3a837da14079ca2dcbfebb70c/compiler-rt/test/builtins/Unit/ashlti3_test.c

it ".__ashlti3" do
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 0).should eq make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 1).should eq make_ti(0xFDB97530ECA8642B, 0xFDB97530ECA8642A)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 2).should eq make_ti(0xFB72EA61D950C857, 0xFB72EA61D950C854)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 3).should eq make_ti(0xF6E5D4C3B2A190AF, 0xF6E5D4C3B2A190A8)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 4).should eq make_ti(0xEDCBA9876543215F, 0xEDCBA98765432150)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 28).should eq make_ti(0x876543215FEDCBA9, 0x8765432150000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 29).should eq make_ti(0x0ECA8642BFDB9753, 0x0ECA8642A0000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 30).should eq make_ti(0x1D950C857FB72EA6, 0x1D950C8540000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 31).should eq make_ti(0x3B2A190AFF6E5D4C, 0x3B2A190A80000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 32).should eq make_ti(0x76543215FEDCBA98, 0x7654321500000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 33).should eq make_ti(0xECA8642BFDB97530, 0xECA8642A00000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 34).should eq make_ti(0xD950C857FB72EA61, 0xD950C85400000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 35).should eq make_ti(0xB2A190AFF6E5D4C3, 0xB2A190A800000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 36).should eq make_ti(0x6543215FEDCBA987, 0x6543215000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 60).should eq make_ti(0x5FEDCBA987654321, 0x5000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 61).should eq make_ti(0xBFDB97530ECA8642, 0xA000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 62).should eq make_ti(0x7FB72EA61D950C85, 0x4000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 63).should eq make_ti(0xFF6E5D4C3B2A190A, 0x8000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 64).should eq make_ti(0xFEDCBA9876543215, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 65).should eq make_ti(0xFDB97530ECA8642A, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 66).should eq make_ti(0xFB72EA61D950C854, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 67).should eq make_ti(0xF6E5D4C3B2A190A8, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 68).should eq make_ti(0xEDCBA98765432150, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 92).should eq make_ti(0x8765432150000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 93).should eq make_ti(0x0ECA8642A0000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 94).should eq make_ti(0x1D950C8540000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 95).should eq make_ti(0x3B2A190A80000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 96).should eq make_ti(0x7654321500000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 97).should eq make_ti(0xECA8642A00000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 98).should eq make_ti(0xD950C85400000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 99).should eq make_ti(0xB2A190A800000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 100).should eq make_ti(0x6543215000000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 124).should eq make_ti(0x5000000000000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 125).should eq make_ti(0xA000000000000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 126).should eq make_ti(0x4000000000000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215, 0xFEDCBA9876543215), 127).should eq make_ti(0x8000000000000000, 0x0000000000000000)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 0).should eq make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 1).should eq make_ti(0xFDB97530ECA8642Bu64, 0xFDB97530ECA8642Au64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 2).should eq make_ti(0xFB72EA61D950C857u64, 0xFB72EA61D950C854u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 3).should eq make_ti(0xF6E5D4C3B2A190AFu64, 0xF6E5D4C3B2A190A8u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 4).should eq make_ti(0xEDCBA9876543215Fu64, 0xEDCBA98765432150u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 28).should eq make_ti(0x876543215FEDCBA9u64, 0x8765432150000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 29).should eq make_ti(0x0ECA8642BFDB9753u64, 0x0ECA8642A0000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 30).should eq make_ti(0x1D950C857FB72EA6u64, 0x1D950C8540000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 31).should eq make_ti(0x3B2A190AFF6E5D4Cu64, 0x3B2A190A80000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 32).should eq make_ti(0x76543215FEDCBA98u64, 0x7654321500000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 33).should eq make_ti(0xECA8642BFDB97530u64, 0xECA8642A00000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 34).should eq make_ti(0xD950C857FB72EA61u64, 0xD950C85400000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 35).should eq make_ti(0xB2A190AFF6E5D4C3u64, 0xB2A190A800000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 36).should eq make_ti(0x6543215FEDCBA987u64, 0x6543215000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 60).should eq make_ti(0x5FEDCBA987654321u64, 0x5000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 61).should eq make_ti(0xBFDB97530ECA8642u64, 0xA000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 62).should eq make_ti(0x7FB72EA61D950C85u64, 0x4000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 63).should eq make_ti(0xFF6E5D4C3B2A190Au64, 0x8000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 64).should eq make_ti(0xFEDCBA9876543215u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 65).should eq make_ti(0xFDB97530ECA8642Au64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 66).should eq make_ti(0xFB72EA61D950C854u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 67).should eq make_ti(0xF6E5D4C3B2A190A8u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 68).should eq make_ti(0xEDCBA98765432150u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 92).should eq make_ti(0x8765432150000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 93).should eq make_ti(0x0ECA8642A0000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 94).should eq make_ti(0x1D950C8540000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 95).should eq make_ti(0x3B2A190A80000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 96).should eq make_ti(0x7654321500000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 97).should eq make_ti(0xECA8642A00000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 98).should eq make_ti(0xD950C85400000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 99).should eq make_ti(0xB2A190A800000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 100).should eq make_ti(0x6543215000000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 124).should eq make_ti(0x5000000000000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 125).should eq make_ti(0xA000000000000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 126).should eq make_ti(0x4000000000000000u64, 0x0000000000000000u64)
__ashlti3(make_ti(0xFEDCBA9876543215u64, 0xFEDCBA9876543215u64), 127).should eq make_ti(0x8000000000000000u64, 0x0000000000000000u64)
end
Loading

0 comments on commit 8b801a5

Please sign in to comment.