cgen: fix print(ptr); checker: uninitialized reference error/warning

pull/4220/head
Alexander Medvednikov 2020-04-03 20:17:53 +02:00
parent 436ef12730
commit 1d2de44e19
2 changed files with 41 additions and 8 deletions

View File

@ -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 { if struct_init.exprs.len > info.fields.len {
c.error('too many fields', struct_init.pos) c.error('too many fields', struct_init.pos)
} }
mut inited_fields := []string
for i, expr in struct_init.exprs { for i, expr in struct_init.exprs {
// struct_field info. // struct_field info.
field_name := if is_short_syntax { info.fields[i].name } else { struct_init.fields[i] } field_name := if is_short_syntax { info.fields[i].name } else { struct_init.fields[i] }
mut field := info.fields[i] mut field := info.fields[i]
inited_fields << field_name
mut found_field := false mut found_field := false
for f in info.fields { for f in info.fields {
if f.name == field_name { 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.expr_types << expr_type
struct_init.expected_types << field.typ 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 {} else {}
} }
@ -1166,23 +1177,41 @@ pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type {
return map_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) { 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.is_verbose {
if c.pref.verbosity.is_higher_or_equal(.level_one) { if c.pref.verbosity.is_higher_or_equal(.level_one) {
print_backtrace() print_backtrace()
} }
typ := if warn { 'warning' } else { 'error' }
kind := if c.pref.verbosity.is_higher_or_equal(.level_one) { kind := if c.pref.verbosity.is_higher_or_equal(.level_one) {
'checker error #$c.nr_errors:' 'checker $typ #$c.nr_errors:'
} else { } else {
'error:' '$typ:'
} }
ferror := util.formated_error(kind, s, c.file.path, pos) ferror := util.formated_error(kind, s, c.file.path, pos)
c.errors << ferror c.errors << ferror
if !(pos.line_nr in c.error_lines) { 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) { if c.pref.verbosity.is_higher_or_equal(.level_one) {
println('\n\n') println('\n\n')
} }

View File

@ -1884,7 +1884,7 @@ fn (g mut Gen) struct_init(it ast.StructInit) {
g.writeln('($styp){') g.writeln('($styp){')
} }
mut fields := []string 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 { if it.fields.len == 0 && it.exprs.len > 0 {
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser. // Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
for f in info.fields { for f in info.fields {
@ -2447,10 +2447,14 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
else { else {
// `println(int_str(10))` // `println(int_str(10))`
// sym := g.table.get_type_symbol(node.args[0].typ) // 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(') g.write('${print_method}(${styp}_str(')
if table.type_is_ptr(typ) { if table.type_is_ptr(typ) {
// dereference // dereference
g.write('*') //g.write('*')
} }
g.expr(node.args[0].expr) g.expr(node.args[0].expr)
g.write('))') 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) fmt := type_to_fmt(field.typ)
g.definitions.write('\t$field.name: $fmt\\n') g.definitions.write('\t$field.name: $fmt\\n')
} }
g.definitions.write('\\n}"') g.definitions.write('}"')
if info.fields.len > 0 { if info.fields.len > 0 {
g.definitions.write(', ') g.definitions.write(', ')
} }