summary refs log tree commit diff stats
path: root/tests/misc/tsizeof.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/misc/tsizeof.nim')
-rw-r--r--tests/misc/tsizeof.nim252
1 files changed, 228 insertions, 24 deletions
diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim
index 50d1c645a..ce5334664 100644
--- a/tests/misc/tsizeof.nim
+++ b/tests/misc/tsizeof.nim
@@ -1,4 +1,5 @@
 discard """
+  targets: "c cpp"
   output: '''
 body executed
 body executed
@@ -7,6 +8,14 @@ macros api OK
 '''
 """
 
+# This is for Azure. The keyword ``alignof`` only exists in ``c++11``
+# and newer. On Azure gcc does not default to c++11 yet.
+when defined(cpp) and not defined(windows):
+  {.passC: "-std=c++11".}
+
+# Object offsets are different for inheritance objects when compiling
+# to c++.
+
 type
   TMyEnum = enum
     tmOne, tmTwo, tmThree, tmFour
@@ -65,22 +74,25 @@ proc strAlign(arg: string): string =
   for i in 0 ..< minLen - arg.len:
     result &= ' '
 
-macro c_offsetof(a: typed, b: untyped): int32 =
-  ## Buffet proof implementation that works on actual offsetof operator
+macro c_offsetof(fieldAccess: typed): int32 =
+  ## Bullet proof implementation that works on actual offsetof operator
   ## in the c backend. Assuming of course this implementation is
   ## correct.
-  let bliteral =
-    if b.kind == nnkStrLit:
-      b
-    else:
-      newLit(repr(b))
+  let s = if fieldAccess.kind == nnkCheckedFieldExpr: fieldAccess[0]
+          else: fieldAccess
+  let a = s[0].getTypeInst
+  let b = s[1]
   result = quote do:
     var res: int32
-    {.emit: [res, " = offsetof(", `a`, ", ", `bliteral`, ");"] .}
+    {.emit: [res, " = offsetof(", `a`, ", ", `b`, ");"] .}
     res
 
+template c_offsetof(t: typedesc, a: untyped): int32 =
+  var x: ptr t
+  c_offsetof(x[].a)
+
 macro c_sizeof(a: typed): int32 =
-  ## Buffet proof implementation that works using the sizeof operator
+  ## Bullet proof implementation that works using the sizeof operator
   ## in the c backend. Assuming of course this implementation is
   ## correct.
   result = quote do:
@@ -89,7 +101,7 @@ macro c_sizeof(a: typed): int32 =
     res
 
 macro c_alignof(arg: untyped): untyped =
-  ## Buffet proof implementation that works on actual alignment
+  ## Bullet proof implementation that works on actual alignment
   ## behavior measured at runtime.
   let typeSym = genSym(nskType, "AlignTestType"&arg.repr)
   result = quote do:
@@ -143,6 +155,14 @@ type
     ValueA
     ValueB
 
+  # Must have more than 32 elements so that set[MyEnum33] will become compile to an int64.
+  MyEnum33 {.pure.} = enum
+    Value1, Value2, Value3, Value4, Value5, Value6,
+    Value7, Value8, Value9, Value10, Value11, Value12,
+    Value13, Value14, Value15, Value16, Value17, Value18,
+    Value19, Value20, Value21, Value22, Value23, Value24,
+    Value25, Value26, Value27, Value28, Value29, Value30,
+    Value31, Value32, Value33
 
 proc transformObjectconfigPacked(arg: NimNode): NimNode =
   let debug = arg.kind == nnkPragmaExpr
@@ -296,6 +316,10 @@ testinstance:
         b: int8
       c: int8
 
+    PaddingOfSetEnum33 {.objectconfig.} = object
+      cause: int8
+      theSet: set[MyEnum33]
+
     Bazing {.objectconfig.} = object of RootObj
       a: int64
       # TODO test on 32 bit system
@@ -311,10 +335,42 @@ testinstance:
       c: char
 
     # from issue 4763
-    GenericObject[T] = object
+    GenericObject[T] {.objectconfig.} = object
       a: int32
       b: T
 
+    # this type mixes `packed` with `align`.
+    MyCustomAlignPackedObject {.objectconfig.} = object
+      a: char
+      b {.align: 32.}: int32 # align overrides `packed` for this field.
+      c: char
+      d: int32  # unaligned
+
+    Kind = enum
+      K1, K2
+  
+    AnotherEnum = enum
+      X1, X2, X3
+
+    MyObject = object
+      s: string
+      case k: Kind
+      of K1: nil
+      of K2:
+          x: float
+          y: int32
+      z: AnotherEnum
+
+    Stack[N: static int, T: object] = object
+      pad: array[128 - sizeof(array[N, ptr T]) - sizeof(int) - sizeof(pointer), byte]
+      stack: array[N, ptr T]
+      len*: int
+      rawMem: ptr array[N, T]
+
+    Stack2[T: object] = object
+      pad: array[128 - sizeof(array[sizeof(T), ptr T]), byte]
+    
+
   const trivialSize = sizeof(TrivialType) # needs to be able to evaluate at compile time
 
   proc main(): void =
@@ -328,6 +384,11 @@ testinstance:
     var g : RecursiveStuff
     var ro : RootObj
     var go : GenericObject[int64]
+    var po : PaddingOfSetEnum33
+    var capo: MyCustomAlignPackedObject
+    var issue15516: MyObject
+    var issue12636_1: Stack[5, MyObject]
+    var issue12636_2: Stack2[MyObject]
 
     var
       e1: Enum1
@@ -346,16 +407,15 @@ testinstance:
     else:
       doAssert sizeof(SimpleAlignment) > 10
 
-    testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go, e1, e2, e4, e8, eoa, eob)
+    testSizeAlignOf(t,a,b,c,d,e,f,g,ro,go,po, e1, e2, e4, e8, eoa, eob, capo, issue15516, issue12636_1, issue12636_2)
 
-    when not defined(cpp):
-      type
-        WithBitsize {.objectconfig.} = object
-          bitfieldA {.bitsize: 16.}: uint32
-          bitfieldB {.bitsize: 16.}: uint32
+    type
+      WithBitsize {.objectconfig.} = object
+        bitfieldA {.bitsize: 16.}: uint32
+        bitfieldB {.bitsize: 16.}: uint32
 
-      var wbs: WithBitsize
-      testSize(wbs)
+    var wbs: WithBitsize
+    testSize(wbs)
 
     testOffsetOf(TrivialType, x)
     testOffsetOf(TrivialType, y)
@@ -383,11 +443,13 @@ testinstance:
 
     testOffsetOf(Foobar, c)
 
-    when not defined(cpp):
-      testOffsetOf(Bazing, a)
-      testOffsetOf(InheritanceA, a)
-      testOffsetOf(InheritanceB, b)
-      testOffsetOf(InheritanceC, c)
+    testOffsetOf(PaddingOfSetEnum33, cause)
+    testOffsetOf(PaddingOfSetEnum33, theSet)
+
+    testOffsetOf(Bazing, a)
+    testOffsetOf(InheritanceA, a)
+    testOffsetOf(InheritanceB, b)
+    testOffsetOf(InheritanceC, c)
 
     testOffsetOf(EnumObjectA, a)
     testOffsetOf(EnumObjectA, b)
@@ -409,6 +471,11 @@ testinstance:
     testOffsetOf(RecursiveStuff, d1)
     testOffsetOf(RecursiveStuff, d2)
 
+    testOffsetOf(MyCustomAlignPackedObject, a)
+    testOffsetOf(MyCustomAlignPackedObject, b)
+    testOffsetOf(MyCustomAlignPackedObject, c)
+    testOffsetOf(MyCustomAlignPackedObject, d)
+
     echo "body executed" # sanity check to ensure this logic isn't skipped entirely
 
 
@@ -458,7 +525,24 @@ type
     a: int32
     b: float32
 
+  MyCustomAlignUnion {.union.} = object
+    c: char
+    a {.align: 32.}: int
+
+  MyCustomAlignObject = object
+    c: char
+    a {.align: 32.}: int
+
 doAssert sizeof(MyUnionType) == 4
+doAssert sizeof(MyCustomAlignUnion) == 32
+doAssert alignof(MyCustomAlignUnion) == 32
+doAssert sizeof(MyCustomAlignObject) == 64
+doAssert alignof(MyCustomAlignObject) == 32
+
+
+
+
+
 
 ##########################################
 # bug #9794
@@ -536,3 +620,123 @@ proc main() =
   typeProcessing(mylocal)
 
 main()
+
+# issue #11320 use UncheckedArray
+
+type
+  Payload = object
+    something: int8
+    vals: UncheckedArray[int32]
+
+proc payloadCheck() =
+  doAssert offsetOf(Payload, vals) == 4
+  doAssert sizeof(Payload) == 4
+
+payloadCheck()
+
+# offsetof tuple types
+
+type
+  MyTupleType = tuple
+    a: float64
+    b: float64
+    c: float64
+
+  MyOtherTupleType = tuple
+    a: float64
+    b: imported_double
+    c: float64
+
+  MyCaseObject = object
+    val1: imported_double
+    case kind: bool
+    of true:
+      val2,val3: float32
+    else:
+      val4,val5: int32
+
+doAssert offsetof(MyTupleType, a) == 0
+doAssert offsetof(MyTupleType, b) == 8
+doAssert offsetof(MyTupleType, c) == 16
+
+doAssert offsetof(MyOtherTupleType, a) == 0
+doAssert offsetof(MyOtherTupleType, b) == 8
+
+# The following expression can only work if the offsetof expression is
+# properly forwarded for the C code generator.
+doAssert offsetof(MyOtherTupleType, c) == 16
+doAssert offsetof(Bar, foo) == 4
+doAssert offsetof(MyCaseObject, val1) == 0
+doAssert offsetof(MyCaseObject, kind) == 8
+doAssert offsetof(MyCaseObject, val2) == 12
+doAssert offsetof(MyCaseObject, val3) == 16
+doAssert offsetof(MyCaseObject, val4) == 12
+doAssert offsetof(MyCaseObject, val5) == 16
+
+template reject(e) =
+  static: assert(not compiles(e))
+
+reject:
+  const off1 = offsetof(MyOtherTupleType, c)
+
+reject:
+  const off2 = offsetof(MyOtherTupleType, b)
+
+reject:
+  const off3 = offsetof(MyCaseObject, kind)
+
+
+type
+  MyPackedCaseObject {.packed.} = object
+    val1: imported_double
+    case kind: bool
+    of true:
+      val2,val3: float32
+    else:
+      val4,val5: int32
+
+# packed case object
+
+doAssert offsetof(MyPackedCaseObject, val1) == 0
+doAssert offsetof(MyPackedCaseObject, val2) == 9
+doAssert offsetof(MyPackedCaseObject, val3) == 13
+doAssert offsetof(MyPackedCaseObject, val4) == 9
+doAssert offsetof(MyPackedCaseObject, val5) == 13
+
+reject:
+  const off5 = offsetof(MyPackedCaseObject, val2)
+
+reject:
+  const off6 = offsetof(MyPackedCaseObject, val3)
+
+reject:
+  const off7 = offsetof(MyPackedCaseObject, val4)
+
+reject:
+  const off8 = offsetof(MyPackedCaseObject, val5)
+
+
+type
+  O0 = object
+  T0 = tuple[]
+
+doAssert sizeof(O0) == 1
+doAssert sizeof(T0) == 1
+
+
+type
+  # this thing may not have padding bytes at the end
+  PackedUnion* {.union, packed.} = object
+    a*: array[11, byte]
+    b*: int64
+
+doAssert sizeof(PackedUnion) == 11
+doAssert alignof(PackedUnion) == 1
+
+# bug #22553
+type
+  ChunkObj = object
+    data: UncheckedArray[byte]
+
+doAssert sizeof(ChunkObj) == 1
+doAssert offsetOf(ChunkObj, data) == 1