From 1d2de44e196b003b06caab3b70766ee288f6a668 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 3 Apr 2020 20:17:53 +0200 Subject: [PATCH] cgen: fix print(ptr); checker: uninitialized reference error/warning --- vlib/v/checker/checker.v | 39 ++++++++++++++++++++++++++++++++++----- vlib/v/gen/cgen.v | 10 +++++++--- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 1e9a725536..c812473e9d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -102,10 +102,12 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { if struct_init.exprs.len > info.fields.len { c.error('too many fields', struct_init.pos) } + mut inited_fields := []string for i, expr in struct_init.exprs { // struct_field info. field_name := if is_short_syntax { info.fields[i].name } else { struct_init.fields[i] } mut field := info.fields[i] + inited_fields << field_name mut found_field := false for f in info.fields { if f.name == field_name { @@ -127,6 +129,15 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { struct_init.expr_types << expr_type struct_init.expected_types << field.typ } + // Check uninitialized refs + for field in info.fields { + if field.name in inited_fields { + continue + } + if table.type_is_ptr(field.typ) { + c.warn('reference field `Reference.value` must be initialized', struct_init.pos) + } + } } else {} } @@ -1166,23 +1177,41 @@ pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type { return map_type } +pub fn (c mut Checker) warn(s string, pos token.Position) { + allow_warnings := !c.pref.is_prod // allow warnings only in dev builds + c.warn_or_error(s, pos, allow_warnings) // allow warnings only in dev builds +} + pub fn (c mut Checker) error(s string, pos token.Position) { - c.nr_errors++ + c.warn_or_error(s, pos, false) +} + +fn (c mut Checker) warn_or_error(s string, pos token.Position, warn bool) { + if !warn { + c.nr_errors++ + } //if c.pref.is_verbose { if c.pref.verbosity.is_higher_or_equal(.level_one) { print_backtrace() } + typ := if warn { 'warning' } else { 'error' } kind := if c.pref.verbosity.is_higher_or_equal(.level_one) { - 'checker error #$c.nr_errors:' + 'checker $typ #$c.nr_errors:' } else { - 'error:' + '$typ:' } ferror := util.formated_error(kind, s, c.file.path, pos) c.errors << ferror if !(pos.line_nr in c.error_lines) { - eprintln(ferror) + if warn { + println(ferror) + } else { + eprintln(ferror) + } + } + if !warn { + c.error_lines << pos.line_nr } - c.error_lines << pos.line_nr if c.pref.verbosity.is_higher_or_equal(.level_one) { println('\n\n') } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index d63baf476a..d4569a85fa 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1884,7 +1884,7 @@ fn (g mut Gen) struct_init(it ast.StructInit) { g.writeln('($styp){') } mut fields := []string - mut inited_fields := []string + mut inited_fields := []string // TODO this is done in checker, move to ast node if it.fields.len == 0 && it.exprs.len > 0 { // Get fields for {a,b} short syntax. Fields array wasn't set in the parser. for f in info.fields { @@ -2447,10 +2447,14 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { else { // `println(int_str(10))` // sym := g.table.get_type_symbol(node.args[0].typ) + if table.type_is_ptr(typ) { + // ptr_str() for pointers + styp = 'ptr' + } g.write('${print_method}(${styp}_str(') if table.type_is_ptr(typ) { // dereference - g.write('*') + //g.write('*') } g.expr(node.args[0].expr) g.write('))') @@ -2883,7 +2887,7 @@ fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) { fmt := type_to_fmt(field.typ) g.definitions.write('\t$field.name: $fmt\\n') } - g.definitions.write('\\n}"') + g.definitions.write('}"') if info.fields.len > 0 { g.definitions.write(', ') }