diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index e52be902b..eed29ff4b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2204,12 +2204,12 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: internalError(p.config, e.info, "unknown ast") let t = dotExpr[0].typ.skipTypes({tyTypeDesc}) + let tname = getTypeDesc(p.module, t) let member = if t.kind == tyTuple: "Field" & rope(dotExpr[1].sym.position) - else: - rope(dotExpr[1].sym.name.s) - putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [getTypeDesc(p.module, t), member]) + else: dotExpr[1].sym.loc.r + putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [tname, member]) of mChr: genSomeCast(p, e, d) of mOrd: genOrd(p, e, d) of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: @@ -2782,17 +2782,50 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, of nkRecCase: getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info) if count > 0: result.add ", " - # XXX select default case branch here! - #for i in 1..= x and branch <= y: + selectedBranch = i + break branchSelection + elif getOrdValue(obj[i][j]) == branch: + selectedBranch = i + break branchSelection + if obj[i].len == 1: + # else branch + selectedBranch = i + assert(selectedBranch >= 1) + + result.add "{" var countB = 0 - getNullValueAux(p, t, lastSon(obj[selectedBranch]), constOrNil, result, countB, isConst, info) - if lastSon(obj[selectedBranch]).kind != nkSym: + 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: + result.add "._i" & $selectedBranch & " = {" + getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info) result.add "}" + elif b.kind == nkSym: + result.add "." & lastSon(obj[selectedBranch]).sym.loc.r & " = " + getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info) result.add "}" + of nkSym: if count > 0: result.add ", " inc count diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 56f227e37..2bcaa5dc3 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -508,15 +508,15 @@ proc mangleRecFieldName(m: BModule; field: PSym): Rope = proc genRecordFieldsAux(m: BModule, n: PNode, rectype: PType, - check: var IntSet): Rope = + check: var IntSet, unionPrefix = ""): Rope = result = nil case n.kind of nkRecList: for i in 0.. 0: result.addf "NIM_ALIGN($1) ", [rope(field.alignment)] # for importcpp'ed objects, we only need to set field.loc, but don't diff --git a/tests/destructor/tarc3.nim b/tests/destructor/tarc3.nim index 1ca4c70e9..d3b9639ad 100644 --- a/tests/destructor/tarc3.nim +++ b/tests/destructor/tarc3.nim @@ -4,7 +4,7 @@ discard """ """ when defined(cpp): - {.passC: "-std=gnu++17".} + {.passC: "-std=gnu++2a".} type TokenKind* = enum @@ -24,6 +24,23 @@ type else: discard pos*: Natural + + Token2* = object + case kind*: TokenKind + of tkString: strVal*: string + of tkNumber: numVal*: float + of tkInt64, tkColon..tkComma: + str1*: array[2, string] + float: float + else: discard + pos*: Natural + + Token3* = object + case kind*: TokenKind + of tkNumber: numVal*: float + of tkInt64, tkComma..tkString: ff: seq[float] + else: str1*: string + BaseLexer* = object of RootObj input*: string pos*: Natural @@ -39,6 +56,8 @@ type Parser[T: Lexer] = object l: T tok: Token + tok2: Token2 + tok3: Token3 allowTrailingComma: bool allowIdentifierObjectKey: bool diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim index a2a9fe59e..7b92d3639 100644 --- a/tests/misc/tsizeof.nim +++ b/tests/misc/tsizeof.nim @@ -74,20 +74,23 @@ proc strAlign(arg: string): string = for i in 0 ..< minLen - arg.len: result &= ' ' -macro c_offsetof(a: typed, b: untyped): int32 = +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 = ## Bullet proof implementation that works using the sizeof operator ## in the c backend. Assuming of course this implementation is