summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJuan M Gómez <info@jmgomez.me>2023-05-02 09:10:51 +0100
committerGitHub <noreply@github.com>2023-05-02 10:10:51 +0200
commit3e82a315fce0c0b11be5094092d8cf4b12b49299 (patch)
treedb1e4e779ece482c1017b660ce422c0f05a3efe7
parentaec5a4c4744a81e19954daf330bafac948098835 (diff)
downloadNim-3e82a315fce0c0b11be5094092d8cf4b12b49299.tar.gz
implements #21747 (#21748)
-rw-r--r--compiler/ccgtypes.nim60
-rw-r--r--compiler/pragmas.nim2
2 files changed, 34 insertions, 28 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 9757f6aa9..adefffc8b 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -576,22 +576,11 @@ proc fillObjectFields*(m: BModule; typ: PType) =
 
 proc mangleDynLibProc(sym: PSym): Rope
 
-proc getRecordDesc(m: BModule; typ: PType, name: Rope,
-                   check: var IntSet): Rope =
-  # declare the record:
-  var hasField = false
-
-  if tfPacked in typ.flags:
-    if hasAttribute in CC[m.config.cCompiler].props:
-      result = structOrUnion(typ) & " __attribute__((__packed__))"
-    else:
-      result = "#pragma pack(push, 1)\L" & structOrUnion(typ)
-  else:
-    result = structOrUnion(typ)
-
-  result.add " "
-  result.add name
-
+template cgDeclFrmt*(s: PSym): string =
+  s.constraint.strVal
+  
+proc getRecordDescAux(m: BModule; typ: PType, name, baseType: Rope,
+                   check: var IntSet, hasField:var bool): Rope =                 
   if typ.kind == tyObject:
     if typ[0] == nil:
       if lacksMTypeField(typ):
@@ -603,8 +592,7 @@ proc getRecordDesc(m: BModule; typ: PType, name: Rope,
           appcg(m, result, " {$n#TNimType* m_type;\n", [])
         hasField = true
     elif m.compileToCpp:
-      appcg(m, result, " : public $1 {\n",
-                      [getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)])
+      appcg(m, result, " : public $1 {\n", [baseType])
       if typ.isException and m.config.exc == excCpp:
         when false:
           appcg(m, result, "virtual void raise() { throw *this; }\n", []) # required for polymorphic exceptions
@@ -616,18 +604,38 @@ proc getRecordDesc(m: BModule; typ: PType, name: Rope,
             appcg(m, cfsProcs, "inline $1::~$1() {if(this->raiseId) #popCurrentExceptionEx(this->raiseId);}\n", [name])
       hasField = true
     else:
-      appcg(m, result, " {$n  $1 Sup;\n",
-                      [getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)])
+      appcg(m, result, " {$n  $1 Sup;\n", [baseType])
       hasField = true
   else:
     result.addf(" {\n", [name])
 
-  let desc = getRecordFields(m, typ, check)
-  if desc == "" and not hasField:
-    result.addf("char dummy;\n", [])
+proc getRecordDesc(m: BModule; typ: PType, name: Rope,
+                   check: var IntSet): Rope =
+  # declare the record:
+  var hasField = false
+  var structOrUnion: string
+  if tfPacked in typ.flags:
+      if hasAttribute in CC[m.config.cCompiler].props:
+        structOrUnion = structOrUnion(typ) & " __attribute__((__packed__))"
+      else:
+        structOrUnion = "#pragma pack(push, 1)\L" & structOrUnion(typ)
   else:
-    result.add(desc)
-  result.add("};\L")
+    structOrUnion = structOrUnion(typ)
+  var baseType: string 
+  if typ[0] != nil: 
+    baseType = getTypeDescAux(m, typ[0].skipTypes(skipPtrs), check, skField)
+  if typ.sym == nil or typ.sym.constraint == nil:
+    result = structOrUnion & " " & name
+    result.add(getRecordDescAux(m, typ, name, baseType, check, hasField))
+    let desc = getRecordFields(m, typ, check)
+    if desc == "" and not hasField:
+      result.addf("char dummy;\n", [])
+    else:
+      result.add(desc)
+    result.add("};\L")
+  else:
+    let desc = getRecordFields(m, typ, check)
+    result = runtimeFormat(typ.sym.cgDeclFrmt, [name, desc, baseType])
   if tfPacked in typ.flags and hasAttribute notin CC[m.config.cCompiler].props:
     result.add "#pragma pack(pop)\L"
 
@@ -956,8 +964,6 @@ proc finishTypeDescriptions(m: BModule) =
     inc(i)
   m.typeStack.setLen 0
 
-template cgDeclFrmt*(s: PSym): string =
-  s.constraint.strVal
 
 proc isReloadable(m: BModule; prc: PSym): bool =
   return m.hcrOn and sfNonReloadable notin prc.flags
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 22677ba01..a91f359d5 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -71,7 +71,7 @@ const
     wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
     wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
     wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
-    wCppNonPod, wBorrow, wGcSafe, wPartial, wExplain, wPackage}
+    wCppNonPod, wBorrow, wGcSafe, wPartial, wExplain, wPackage, wCodegenDecl}
   fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
     wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
   varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,