diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index dae04ba63..301b7b391 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -3230,6 +3230,11 @@ proc caseObjDefaultBranch(obj: PNode; branch: Int128): int = return i assert(false, "unreachable") +proc isEmptyCaseObjectBranch(n: PNode): bool = + for it in n: + if it.kind == nkSym and not isEmptyType(it.sym.typ): return false + return true + proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, result: var Rope; count: var int; isConst: bool, info: TLineInfo) = @@ -3258,7 +3263,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, let b = lastSon(obj[selectedBranch]) # designated initilization is the only way to init non first element of unions # branches are allowed to have no members (b.len == 0), in this case they don't need initializer - if b.kind == nkRecList and b.len > 0: + if b.kind == nkRecList and not isEmptyCaseObjectBranch(b): result.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {" getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info) result.add "}" diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index ff43c003d..2473db70d 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -514,21 +514,18 @@ proc genRecordFieldsAux(m: BModule, n: PNode, let structName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i var a = newRopeAppender() genRecordFieldsAux(m, k, rectype, check, a, unionPrefix & $structName & ".") - # When 'k' is 'void', 'a' is the empty string and we just generate - # empty struct. This prevents field access errors when generating - # static initializers for the type. - # See issue #20699 - if tfPacked notin rectype.flags: - unionBody.add("struct {") - else: - if hasAttribute in CC[m.config.cCompiler].props: - unionBody.add("struct __attribute__((__packed__)){") + if a != "": + if tfPacked notin rectype.flags: + unionBody.add("struct {") else: - unionBody.addf("#pragma pack(push, 1)$nstruct{", []) - unionBody.add(a) - unionBody.addf("} $1;$n", [structName]) - if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props: - unionBody.addf("#pragma pack(pop)$n", []) + if hasAttribute in CC[m.config.cCompiler].props: + unionBody.add("struct __attribute__((__packed__)){") + else: + unionBody.addf("#pragma pack(push, 1)$nstruct{", []) + unionBody.add(a) + unionBody.addf("} $1;$n", [structName]) + if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props: + unionBody.addf("#pragma pack(pop)$n", []) else: genRecordFieldsAux(m, k, rectype, check, unionBody, unionPrefix) else: internalError(m.config, "genRecordFieldsAux(record case branch)") diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 65dae64ff..789571bbf 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -476,20 +476,21 @@ template main {.dirty.} = foo2() - block: # issue #20699 - type - Either[A,B] = object - case kind:bool - of false: - b: B - of true: - a: A - O = object of RootRef - proc oToEither(o:O):Either[O,void] = - Either[O,void](kind:true,a: o) + block: # issue #20699 + type + Either[A,B] = object + case kind:bool + of false: + b: B + of true: + a: A + O = object of RootRef - discard oToEither(O()) + proc oToEither(o:O):Either[O,void] = + Either[O,void](kind:true,a: o) + + discard oToEither(O()) static: main() main()