From aaf3ced7501049308448ff99727df84f100c38e2 Mon Sep 17 00:00:00 2001 From: SleepyRoy <47302112+SleepyRoy@users.noreply.github.com> Date: Wed, 19 Feb 2020 05:14:52 +0800 Subject: [PATCH] parser: add type check for +=, -=, *=, /= --- vlib/compiler/aparser.v | 15 +++++++++++++++ vlib/compiler/table.v | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/vlib/compiler/aparser.v b/vlib/compiler/aparser.v index 446b47328f..2c74b2a314 100644 --- a/vlib/compiler/aparser.v +++ b/vlib/compiler/aparser.v @@ -1674,6 +1674,21 @@ fn ($v.name mut $v.typ) ${p.cur_fn.name}(...) { } p.cgen.resetln('memcpy( (& $left), ($etype{$expr}), sizeof( $left ) );') } + // check type for +=, -=, *=, /=. + else if tok in [.plus_assign, .minus_assign, .mult_assign, .div_assign] { + // special 1. ptrs with += or -= are acceptable. + if !(tok in [.plus_assign, .minus_assign] && (is_integer_type(p.assigned_type) || is_pointer_type(p.assigned_type)) && (is_integer_type(expr_type) || is_pointer_type(expr_type))) { + // special 2. `str += str` is acceptable + if !(tok == .plus_assign && p.assigned_type == expr_type && expr_type == 'string' ) { + if !is_number_type(p.assigned_type) { + p.error_with_token_index('cannot use assignment operator ${tok.str()} on non-numeric type `$p.assigned_type`', errtok) + } + if !is_number_type(expr_type) { + p.error_with_token_index('cannot use non-numeric type `$expr_type` as assignment operator ${tok.str()} argument', errtok) + } + } + } + } // check type for <<= >>= %= ^= &= |= else if tok in [.left_shift_assign, .righ_shift_assign, .mod_assign, .xor_assign, .and_assign, .or_assign] { if !is_integer_type(p.assigned_type) { diff --git a/vlib/compiler/table.v b/vlib/compiler/table.v index e4ca5e1eb9..52ed2419d7 100644 --- a/vlib/compiler/table.v +++ b/vlib/compiler/table.v @@ -189,6 +189,7 @@ const ( integer_types = ['int', 'i8', 'char', 'byte', 'i16', 'u16', 'u32', 'i64', 'u64'] float_types = ['f32', 'f64'] reserved_type_param_names = ['R', 'S', 'T', 'U', 'W'] + pointer_types = ['byte*', 'byteptr', 'char*', 'charptr', 'void*', 'voidptr', 'voidptr*', 'intptr'] ) fn is_number_type(typ string) bool { @@ -207,6 +208,10 @@ fn is_primitive_type(typ string) bool { return is_number_type(typ) || typ == 'string' } +fn is_pointer_type(typ string) bool { + return typ in pointer_types +} + /* fn (t mut Table) register_enum_val(typ, val string) { if t.enum_vals.len == 0 {