Skip to content

Commit 7604960

Browse files
committed
v3: preserve signed fastc integer literals
1 parent ac8b2d5 commit 7604960

2 files changed

Lines changed: 94 additions & 5 deletions

File tree

vlib/v3/gen/fastc/fastc.v

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,7 +4452,7 @@ fn (mut g Parser) parse_declaration_after_name(name string, is_mut bool) ! {
44524452

44534453
fn fastc_normalize_inferred_type(typ string) string {
44544454
return match typ {
4455-
'integer literal' { 'int' }
4455+
'integer literal', 'negative integer literal' { 'int' }
44564456
'float literal' { 'f64' }
44574457
'nil' { 'voidptr' }
44584458
else { typ }
@@ -9311,6 +9311,9 @@ fn (g &Parser) infer_expression_type(tokens []FastcExpressionToken) !string {
93119311
if !fastc_is_numeric_expression_type(operand_type) {
93129312
return g.unsupported('arithmetic `${tokens[start].tok.str()}` on non-numeric type `${operand_type}`')
93139313
}
9314+
if tokens[start].tok == .minus && operand_type == 'integer literal' {
9315+
return 'negative integer literal'
9316+
}
93149317
return operand_type
93159318
}
93169319
if tokens[start].tok in [.amp, .and] {
@@ -9583,19 +9586,36 @@ fn fastc_number_expression_type(literal string) string {
95839586
&& clean.contains_any('eE')) {
95849587
return 'float literal'
95859588
}
9589+
if clean.starts_with('-') {
9590+
return 'negative integer literal'
9591+
}
95869592
return 'integer literal'
95879593
}
95889594

95899595
fn fastc_common_arithmetic_type(left string, right string) string {
95909596
if left == right && fastc_is_numeric_expression_type(left) {
95919597
return left
95929598
}
9593-
if left == 'integer literal' && fastc_is_integer_type(right) {
9599+
if left == 'negative integer literal' && fastc_is_unsigned_integer_type(right) {
9600+
return ''
9601+
}
9602+
if right == 'negative integer literal' && fastc_is_unsigned_integer_type(left) {
9603+
return ''
9604+
}
9605+
if fastc_is_integer_literal_expression_type(left) && fastc_is_integer_type(right) {
95949606
return right
95959607
}
9596-
if right == 'integer literal' && fastc_is_integer_type(left) {
9608+
if fastc_is_integer_literal_expression_type(right) && fastc_is_integer_type(left) {
95979609
return left
95989610
}
9611+
if fastc_is_integer_literal_expression_type(left)
9612+
&& fastc_is_integer_literal_expression_type(right) {
9613+
return if left == 'negative integer literal' || right == 'negative integer literal' {
9614+
'negative integer literal'
9615+
} else {
9616+
'integer literal'
9617+
}
9618+
}
95999619
if left == 'float literal' && right in ['f32', 'f64'] {
96009620
return right
96019621
}
@@ -9606,11 +9626,16 @@ fn fastc_common_arithmetic_type(left string, right string) string {
96069626
}
96079627

96089628
fn fastc_is_numeric_expression_type(typ string) bool {
9609-
return typ in ['integer literal', 'float literal', 'f32', 'f64'] || fastc_is_integer_type(typ)
9629+
return fastc_is_integer_literal_expression_type(typ) || typ in ['float literal', 'f32', 'f64']
9630+
|| fastc_is_integer_type(typ)
96109631
}
96119632

96129633
fn fastc_is_integer_expression_type(typ string) bool {
9613-
return typ == 'integer literal' || fastc_is_integer_type(typ)
9634+
return fastc_is_integer_literal_expression_type(typ) || fastc_is_integer_type(typ)
9635+
}
9636+
9637+
fn fastc_is_integer_literal_expression_type(typ string) bool {
9638+
return typ in ['integer literal', 'negative integer literal']
96149639
}
96159640

96169641
fn fastc_call_types_are_compatible(actual string, expected string) bool {
@@ -9620,6 +9645,9 @@ fn fastc_call_types_are_compatible(actual string, expected string) bool {
96209645
if actual == 'integer literal' {
96219646
return fastc_is_integer_type(expected)
96229647
}
9648+
if actual == 'negative integer literal' {
9649+
return fastc_is_integer_type(expected) && !fastc_is_unsigned_integer_type(expected)
9650+
}
96239651
if actual == 'float literal' {
96249652
return expected in ['f32', 'f64']
96259653
}
@@ -9647,6 +9675,9 @@ fn fastc_selfhost_types_are_compatible(actual string, expected string) bool {
96479675
|| (expected_base == 'map' && actual_base.starts_with('Map_')) {
96489676
return true
96499677
}
9678+
if actual == 'negative integer literal' && fastc_is_unsigned_integer_type(expected) {
9679+
return false
9680+
}
96509681
if fastc_is_integer_expression_type(actual) && fastc_is_integer_type(expected) {
96519682
return true
96529683
}
@@ -9711,6 +9742,10 @@ fn fastc_is_integer_type(typ string) bool {
97119742
'u32', 'u64', 'unsigned int', 'usize']
97129743
}
97139744

9745+
fn fastc_is_unsigned_integer_type(typ string) bool {
9746+
return typ in ['byte', 'u8', 'u16', 'u32', 'u64', 'unsigned int', 'usize']
9747+
}
9748+
97149749
fn fastc_nondecimal_literal_is_type_sensitive(literal string) bool {
97159750
clean := literal.replace('_', '')
97169751
if clean.len <= 2 || clean[0] != `0` {

vlib/v3/gen/fastc/fastc_test.v

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,60 @@ fn main() {
353353
assert c_source.contains('count+=3;')
354354
}
355355

356+
fn test_negative_integer_literals_are_rejected_for_unsigned_targets() {
357+
prefs := pref.new_preferences()
358+
for source in [
359+
'module main\nfn take(x u32) { println(x) }\nfn main() { take(-1) }\n',
360+
'module main\nfn main() { mut value := u32(0); value = -1; println(value) }\n',
361+
'module main\nfn value() u32 { return -1 }\nfn main() { println(value()) }\n',
362+
] {
363+
mut message := ''
364+
_ := generate(source, 'negative_unsigned_literal.v', prefs) or {
365+
message = err.msg()
366+
''
367+
}
368+
assert message.contains('negative integer literal'), message
369+
assert message.contains('u32'), message
370+
}
371+
372+
c_source := generate('module main
373+
374+
fn take(x u32) {
375+
println(x)
376+
}
377+
378+
fn value() u32 {
379+
return 1
380+
}
381+
382+
fn take_signed(x int) {
383+
println(x)
384+
}
385+
386+
fn signed_value() int {
387+
return -1
388+
}
389+
390+
fn main() {
391+
mut number := u32(0)
392+
number = 1
393+
take(1)
394+
println(value())
395+
mut signed := 0
396+
signed = -1
397+
take_signed(-1)
398+
println(signed_value())
399+
}
400+
',
401+
'positive_unsigned_literals.v', prefs) or { panic(err) }
402+
assert c_source.contains('number=1;')
403+
assert c_source.contains('take(1);')
404+
assert c_source.contains('return 1;')
405+
assert c_source.contains('signed=-1;')
406+
assert c_source.contains('take_signed(-1);')
407+
assert c_source.contains('return -1;')
408+
}
409+
356410
fn test_main_must_not_return_a_value() {
357411
prefs := pref.new_preferences()
358412
mut message := ''

0 commit comments

Comments
 (0)