diff options
-rw-r--r-- | compiler/pragmas.nim | 2 | ||||
-rw-r--r-- | compiler/sizealignoffsetimpl.nim | 11 | ||||
-rw-r--r-- | tests/misc/tsizeof.nim | 36 |
3 files changed, 42 insertions, 7 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1c07a3309..ef5223559 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 dd7c117be..4791788fa 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 dddb7dd58..f60c7fa00 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" |