diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 0b4c7d5f37..53e34bd0c2 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1022,11 +1022,11 @@ pub mut: pub struct SizeOf { pub: - is_type bool - typ table.Type - type_name string - expr Expr - pos token.Position + is_type bool + expr Expr // checker uses this to set typ + pos token.Position +pub mut: + typ table.Type } pub struct Likely { diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e23c72f563..7fd8130cb2 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3357,6 +3357,9 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { return c.selector_expr(mut node) } ast.SizeOf { + if !node.is_type { + node.typ = c.expr(node.expr) + } return table.u32_type } ast.SqlExpr { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 49e5d094f2..eb3c5a1b82 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1122,23 +1122,22 @@ pub fn (mut f Fmt) expr(node ast.Expr) { f.write(node.field_name) } ast.SizeOf { + f.write('sizeof(') if node.is_type { - f.write('sizeof(') - if node.type_name != '' { - if f.is_external_name(node.type_name) { - f.write(node.type_name) + sym := f.table.get_type_symbol(node.typ) + if sym.name != '' { + if f.is_external_name(sym.name) { + f.write(sym.name) } else { - f.write(f.short_module(node.type_name)) + f.write(f.short_module(sym.name)) } } else { f.write(f.table.type_to_str(node.typ)) } - f.write(')') } else { - f.write('sizeof(') f.expr(node.expr) - f.write(')') } + f.write(')') } ast.SqlExpr { // sql app.db { select from Contributor where repo == id && user == 0 } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index b0f345062e..58034b8c85 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2719,29 +2719,9 @@ fn (mut g Gen) expr(node ast.Expr) { g.select_expr(node) } ast.SizeOf { - if node.is_type { - node_typ := g.unwrap_generic(node.typ) - mut styp := node.type_name - if styp.starts_with('C.') { - styp = styp[2..] - } - if node.type_name == '' || node.typ.has_flag(.generic) { - styp = g.typ(node_typ) - } else { - sym := g.table.get_type_symbol(node_typ) - if sym.kind == .struct_ { - info := sym.info as table.Struct - if !info.is_typedef { - styp = 'struct ' + styp - } - } - } - g.write('/*SizeOfType*/ sizeof(${util.no_dots(styp)})') - } else { - g.write('/*SizeOfVar*/ sizeof(') - g.expr(node.expr) - g.write(')') - } + node_typ := g.unwrap_generic(node.typ) + styp := g.typ(node_typ) + g.write('/*SizeOf*/ sizeof(${util.no_dots(styp)})') } ast.SqlExpr { g.sql_select_expr(node) diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 56873f8901..02069735e9 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -158,10 +158,9 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { pos := p.tok.position() p.next() // sizeof p.check(.lpar) - if !p.tok.can_start_type(table.builtin_type_names) { - if p.tok.kind == .name { - p.mark_var_as_used(p.tok.lit) - } + is_known_var := p.mark_var_as_used(p.tok.lit) + // assume mod. prefix leads to a type + if is_known_var || !(p.known_import(p.tok.lit) || p.tok.kind.is_start_of_type()) { expr := p.expr(0) node = ast.SizeOf{ is_type: false @@ -169,6 +168,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { pos: pos } } else { + p.register_used_import(p.tok.lit) save_expr_mod := p.expr_mod p.expr_mod = '' sizeof_type := p.parse_type() @@ -176,7 +176,6 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { node = ast.SizeOf{ is_type: true typ: sizeof_type - type_name: p.table.get_type_symbol(sizeof_type).name pos: pos } } diff --git a/vlib/v/tests/sizeof_test.v b/vlib/v/tests/sizeof_test.v index 372f13250b..df17734036 100644 --- a/vlib/v/tests/sizeof_test.v +++ b/vlib/v/tests/sizeof_test.v @@ -1,7 +1,11 @@ import math +import flag struct S1 { - i voidptr + p voidptr +} +struct S2 { + i int } fn test_math_sizeof() { @@ -10,8 +14,12 @@ fn test_math_sizeof() { } fn test_sizeof() { - // depends on compiler - assert sizeof(`€`) in [u32(2), 4] + assert sizeof(rune) == 4 + assert sizeof([44]byte) == 44 + assert sizeof(`€`) == 4 // depends on -m32/64 assert sizeof(S1) in [u32(4), 8] + s := S2{} + assert sizeof(s.i) == 4 + assert sizeof(flag.Flag) > 4 }