summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorClyybber <darkmine956@gmail.com>2020-07-01 11:41:03 +0200
committerGitHub <noreply@github.com>2020-07-01 11:41:03 +0200
commit1440e70c62e7dc2e2a2062c1291f65c12055818a (patch)
treed7ba6ef283ac73af016fb404e62fe801a2959de5 /compiler
parent1edb9a6178d868e34e76faf9e2a05afbc1431cb0 (diff)
downloadNim-1440e70c62e7dc2e2a2062c1291f65c12055818a.tar.gz
allow packed union (#14868)
Co-authored-by: Arne Döring <arne.doering@gmx.net>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/sizealignoffsetimpl.nim16
1 files changed, 7 insertions, 9 deletions
diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim
index 4d73923db..baa2c40f9 100644
--- a/compiler/sizealignoffsetimpl.nim
+++ b/compiler/sizealignoffsetimpl.nim
@@ -164,7 +164,7 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, a
     accum.maxAlign = szUnknownSize
     accum.offset = szUnknownSize
 
-proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var OffsetAccum) =
+proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; packed: bool; accum: var OffsetAccum) =
   ## ``accum.offset`` will the offset from the larget member of the union.
   case n.kind
   of nkRecCase:
@@ -175,7 +175,7 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
     let accumRoot = accum # copy, because each branch should start af the same offset
     for i, child in n.sons:
       var branchAccum = accumRoot
-      computeUnionObjectOffsetsFoldFunction(conf, child, branchAccum)
+      computeUnionObjectOffsetsFoldFunction(conf, child, packed, branchAccum)
       accum.mergeBranch(branchAccum)
   of nkSym:
     var size = szUnknownSize
@@ -183,7 +183,7 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
     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
+      align = if packed: 1 else: n.sym.typ.align.int
     accum.align(align)
     if n.sym.alignment > 0:
       accum.align(n.sym.alignment)
@@ -365,16 +365,14 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
         else:
           OffsetAccum(maxAlign: 1)
       if tfUnion in typ.flags:
-        if tfPacked in typ.flags:
-          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
-          localError(conf, info, "union type may not be packed.")
-          accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
-        elif accum.offset != 0:
+        if accum.offset != 0:
           let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
           localError(conf, info, "union type may not have an object header")
           accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
+        elif tfPacked in typ.flags:
+          computeUnionObjectOffsetsFoldFunction(conf, typ.n, true, accum)
         else:
-          computeUnionObjectOffsetsFoldFunction(conf, typ.n, accum)
+          computeUnionObjectOffsetsFoldFunction(conf, typ.n, false, accum)
       elif tfPacked in typ.flags:
         accum.maxAlign = 1
         computeObjectOffsetsFoldFunction(conf, typ.n, true, accum)