From 1e08fff2d525e4c2db68a92819fb910739252764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Mon, 19 Nov 2018 13:48:40 +0100 Subject: [PATCH] bitsize respected in size calculation. (#9756) --- compiler/pragmas.nim | 2 ++ compiler/sizealignoffsetimpl.nim | 11 +++++++--- tests/misc/tsizeof.nim | 36 ++++++++++++++++++++++++++++---- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1c07a33095..ef52235593 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1062,6 +1062,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, invalidPragma(c, it) else: sym.bitsize = expectIntLit(c, it) + if sym.bitsize <= 0: + localError(c.config, it.info, "bitsize needs to be positive") of wGuard: if sym == nil or sym.kind notin {skVar, skLet, skField}: invalidPragma(c, it) diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim index dd7c117be2..4791788fa1 100644 --- a/compiler/sizealignoffsetimpl.nim +++ b/compiler/sizealignoffsetimpl.nim @@ -127,9 +127,14 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: result.offset = align(offset, result.align) of nkSym: - computeSizeAlign(conf, n.sym.typ) - let size = n.sym.typ.size - let align = n.sym.typ.align + var size = szUnknownSize + var align = szUnknownSize + + if n.sym.bitsize == 0: # 0 represents bitsize not set + computeSizeAlign(conf, n.sym.typ) + size = n.sym.typ.size.int + align = n.sym.typ.align.int + result.align = align if initialOffset == szUnknownSize or size == szUnknownSize: n.sym.offset = szUnknownSize diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim index dddb7dd585..f60c7fa004 100644 --- a/tests/misc/tsizeof.nim +++ b/tests/misc/tsizeof.nim @@ -10,14 +10,16 @@ type TMyArray2 = array[1..3, int32] TMyArray3 = array[TMyEnum, float64] +var failed = false + const mysize1 = sizeof(TMyArray1) mysize2 = sizeof(TMyArray2) mysize3 = sizeof(TMyArray3) -assert mysize1 == 3 -assert mysize2 == 12 -assert mysize3 == 32 +doAssert mysize1 == 3 +doAssert mysize2 == 12 +doAssert mysize3 == 32 import macros, typetraits @@ -38,6 +40,7 @@ macro testSizeAlignOf(args: varargs[untyped]): untyped = if nim_align != c_align: msg.add " align(get, expected): " & $nim_align & " != " & $c_align echo msg + failed = true macro testOffsetOf(a,b1,b2: untyped): untyped = @@ -49,6 +52,7 @@ macro testOffsetOf(a,b1,b2: untyped): untyped = nim_offset = offsetof(`a`,`b2`) if c_offset != nim_offset: echo `typeName`, ".", `member`, " offsetError, C: ", c_offset, " nim: ", nim_offset + failed = true template testOffsetOf(a,b: untyped): untyped = testOffsetOf(a,b,b) @@ -100,6 +104,16 @@ macro testAlign(arg:untyped):untyped = let nimAlign = alignof(`arg`) if cAlign != nimAlign: echo `prefix`, cAlign, " != ", nimAlign + failed = true + +macro testSize(arg:untyped):untyped = + let prefix = newLit(arg.lineinfo & " sizeof " & arg.repr & " ") + result = quote do: + let cSize = c_sizeof(`arg`) + let nimSize = sizeof(`arg`) + if cSize != nimSize: + echo `prefix`, cSize, " != ", nimSize + failed = true type MyEnum {.pure.} = enum @@ -297,10 +311,20 @@ testinstance: eoa: EnumObjectA eob: EnumObjectB + testAlign(SimpleAlignment) testSizeAlignOf(t,a,b,c,d,e,f,g,ro, e1, e2, e4, e8, eoa, eob) + when not defined(cpp): + type + WithBitsize {.objectconfig.} = object + bitfieldA {.bitsize: 16.}: uint32 + bitfieldB {.bitsize: 16.}: uint32 + + var wbs: WithBitsize + testSize(wbs) + testOffsetOf(TrivialType, x) testOffsetOf(TrivialType, y) testOffsetOf(TrivialType, z) @@ -308,6 +332,7 @@ testinstance: testOffsetOf(SimpleAlignment, a) testOffsetOf(SimpleAlignment, b) testOffsetOf(SimpleAlignment, c) + testOffsetOf(AlignAtEnd, a) testOffsetOf(AlignAtEnd, b) testOffsetOf(AlignAtEnd, c) @@ -369,4 +394,7 @@ type assert sizeof(Bar) == 12 -echo "OK" +if failed: + quit("FAIL") +else: + echo "OK"