diff --git a/compiler/ast.nim b/compiler/ast.nim index 2b428cec090d..6754f1140959 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -814,8 +814,11 @@ type template nodeId(n: PNode): int = cast[int](n) -template owner*(s: PSym|PType): PSym = - s.ownerField +proc owner*(s: PSym|PType): PSym {.inline.} = + result = s.ownerField + +proc setOwner*(s: PSym|PType, owner: PSym) {.inline.} = + s.ownerField = owner type Gconfig = object # we put comments in a side channel to avoid increasing `sizeof(TNode)`, which diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index e3c1c310754d..e5032d743116 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -77,9 +77,7 @@ type needsComma: bool proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer = - ## starts building a struct initializer, `orderCompliant = true` means - ## built fields must be ordered correctly - assert kind != siNamedStruct, "named struct constructors unimplemented" + ## starts building a struct initializer, i.e. braced initializer list result = StructInitializer(kind: kind, needsComma: false) if kind != siWrapper: builder.add("{") @@ -100,7 +98,11 @@ template addField(builder: var Builder, constr: var StructInitializer, name: str assert name.len != 0, "name has to be given for struct initializer field" valueBody of siNamedStruct: - assert false, "named struct constructors unimplemented" + assert name.len != 0, "name has to be given for struct initializer field" + builder.add(".") + builder.add(name) + builder.add(" = ") + valueBody proc finishStructInitializer(builder: var Builder, constr: StructInitializer) = ## finishes building a struct initializer diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index d59dd7aec95f..88d177800ba2 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -3289,26 +3289,35 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, break let selectedBranch = caseObjDefaultBranch(obj, branch) - # XXX siNamedStruct needs to be implemented to replace `res` here - var res = "{" - var branchInit: StructInitializer 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 + var fieldName: string = "" if b.kind == nkRecList and not isEmptyCaseObjectBranch(b): - res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = " - res.addStructInitializer(branchInit, kind = siOrderedStruct): - getNullValueAux(p, t, b, constOrNil, res, branchInit, isConst, info) + fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch + result.addField(init, name = ""): + # XXX figure out name for the union, see use of `addAnonUnion` + var branchInit: StructInitializer + result.addStructInitializer(branchInit, kind = siNamedStruct): + result.addField(branchInit, name = fieldName): + var branchObjInit: StructInitializer + result.addStructInitializer(branchObjInit, kind = siOrderedStruct): + getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info) elif b.kind == nkSym: - res.add "." & mangleRecFieldName(p.module, b.sym) & " = " - res.addStructInitializer(branchInit, kind = siWrapper): - getNullValueAux(p, t, b, constOrNil, res, branchInit, isConst, info) - else: + fieldName = mangleRecFieldName(p.module, b.sym) + result.addField(init, name = ""): + # XXX figure out name for the union, see use of `addAnonUnion` + var branchInit: StructInitializer + result.addStructInitializer(branchInit, kind = siNamedStruct): + result.addField(branchInit, name = fieldName): + # we need to generate the default value of the single sym, + # to do this create a dummy wrapper initializer and recurse + var branchFieldInit: StructInitializer + result.addStructInitializer(branchFieldInit, kind = siWrapper): + getNullValueAux(p, t, b, constOrNil, result, branchFieldInit, isConst, info) + else: + # no fields, don't initialize return - result.addField(init, name = ""): - # XXX figure out name for the union, see use of `addAnonUnion` - result.add res - result.add "}" of nkSym: let field = obj.sym diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 154ab7475da2..2337c70e63af 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -340,7 +340,12 @@ proc getSimpleTypeDesc(m: BModule; typ: PType): Rope = of tyNil: result = typeNameOrLiteral(m, typ, "void*") of tyInt..tyUInt64: result = typeNameOrLiteral(m, typ, NumericalTypeToStr[typ.kind]) - of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.skipModifier) + of tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.skipModifier) + of tyDistinct: + result = getSimpleTypeDesc(m, typ.skipModifier) + if isImportedType(typ) and result != "": + useHeader(m, typ.sym) + result = typ.sym.loc.snippet of tyStatic: if typ.n != nil: result = getSimpleTypeDesc(m, skipModifier typ) else: @@ -861,7 +866,8 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym) let sig = hashType(origTyp, m.config) - result = getTypePre(m, t, sig) + # tyDistinct matters if it is an importc type + result = getTypePre(m, origTyp.skipTypes(irrelevantForBackend-{tyOwned, tyDistinct}), sig) defer: # defer is the simplest in this case if isImportedType(t) and not m.typeABICache.containsOrIncl(sig): addAbiCheck(m, t, result) diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 199a047d4aa9..d2e60460947c 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -64,7 +64,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = if x == nil: x = copySym(s, c.idgen) # sem'check needs to set the owner properly later, see bug #9476 - x.owner() = nil # c.genSymOwner + setOwner(x, nil) # c.genSymOwner #if x.kind == skParam and x.owner.kind == skModule: # internalAssert c.config, false idTablePut(c.mapping, s, x) diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim index 238825ac5643..3a1acd4b1645 100644 --- a/compiler/ic/ic.nim +++ b/compiler/ic/ic.nim @@ -942,7 +942,7 @@ proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; result.guard = loadSym(c, g, si, s.guard) result.bitsize = s.bitsize result.alignment = s.alignment - result.owner() = loadSym(c, g, si, s.owner) + setOwner(result, loadSym(c, g, si, s.owner)) let externalName = g[si].fromDisk.strings[s.externalName] if externalName != "": result.loc.snippet = externalName @@ -998,7 +998,7 @@ proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; proc typeBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph; t: PackedType; si, item: int32; result: PType) = result.sym = loadSym(c, g, si, t.sym) - result.owner() = loadSym(c, g, si, t.owner) + setOwner(result, loadSym(c, g, si, t.owner)) when false: for op, item in pairs t.attachedOps: result.attachedOps[op] = loadSym(c, g, si, item) @@ -1062,7 +1062,7 @@ proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa name: getIdent(cache, splitFile(filename).name), info: newLineInfo(fileIdx, 1, 1), position: int(fileIdx)) - m.module.owner() = getPackage(conf, cache, fileIdx) + setOwner(m.module, getPackage(conf, cache, fileIdx)) m.module.flags = m.fromDisk.moduleFlags proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; diff --git a/compiler/modules.nim b/compiler/modules.nim index 6b893f11ee61..7f56119cccc3 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -25,7 +25,7 @@ template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent = proc partialInitModule*(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) = let packSym = getPackage(graph, fileIdx) - result.owner() = packSym + setOwner(result, packSym) result.position = int fileIdx proc newModule*(graph: ModuleGraph; fileIdx: FileIndex): PSym = diff --git a/compiler/sem.nim b/compiler/sem.nim index 43da92285474..86f92f851e81 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -256,7 +256,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 - result.owner() = getCurrOwner(c) + setOwner(result, getCurrOwner(c)) else: result = newSym(kind, considerQuotedIdent(c, n), c.idgen, getCurrOwner(c), n.info) if find(result.name.s, '`') >= 0: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 34f0f8ccae75..ef389c7ca40a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2965,7 +2965,7 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = ni if sfGenSym notin labl.flags: addDecl(c, labl) elif labl.owner == nil: - labl.owner() = c.p.owner + setOwner(labl, c.p.owner) n[0] = newSymNode(labl, n[0].info) suggestSym(c.graph, n[0].info, labl, c.graph.usageSym) styleCheckDef(c, labl) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 6d37b5354d3c..00f81a2f270a 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -111,7 +111,7 @@ proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var SymMappi elif s.owner == nil or s.owner.kind == skPackage: #echo "copied this ", s.name.s x = copySym(s, c.idgen) - x.owner() = owner + setOwner(x, owner) idTablePut(symMap, s, x) n.sym = x else: @@ -273,7 +273,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable, internalAssert c.config, originalParams[i].kind == nkSym let oldParam = originalParams[i].sym let param = copySym(oldParam, c.idgen) - param.owner() = prc + setOwner(param, prc) param.typ = result[i] # The default value is instantiated and fitted against the final @@ -395,9 +395,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable, let passc = getLocalPassC(c, producer) if passc != "": #pass the local compiler options to the consumer module too extccomp.addLocalCompileOption(c.config, passc, toFullPathConsiderDirty(c.config, c.module.info.fileIndex)) - result.owner() = c.module + setOwner(result, c.module) else: - result.owner() = fn + setOwner(result, fn) result.ast = n pushOwner(c, result) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index e65f1445ad88..cf5cfad6d8c7 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -453,7 +453,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym result = copySym(orig, c.idgen) result.info = info result.flags.incl sfFromGeneric - result.owner() = orig + setOwner(result, orig) let origParamType = orig.typ.firstParamType let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs), c.idgen) let oldParam = orig.typ.n[1].sym @@ -524,7 +524,7 @@ proc semNewFinalize(c: PContext; n: PNode): PNode = discard "already turned this one into a finalizer" else: if fin.instantiatedFrom != nil and fin.instantiatedFrom != fin.owner: #undo move - fin.owner() = fin.instantiatedFrom + setOwner(fin, fin.instantiatedFrom) let wrapperSym = newSym(skProc, getIdent(c.graph.cache, fin.name.s & "FinalizerWrapper"), c.idgen, fin.owner, fin.info) let selfSymNode = newSymNode(copySym(fin.ast[paramsPos][1][0].sym, c.idgen)) selfSymNode.typ = fin.typ.firstParamType @@ -539,7 +539,7 @@ proc semNewFinalize(c: PContext; n: PNode): PNode = genericParams = fin.ast[genericParamsPos], pragmas = fin.ast[pragmasPos], exceptions = fin.ast[miscPos]), {}) var transFormedSym = turnFinalizerIntoDestructor(c, wrapperSym, wrapper.info) - transFormedSym.owner() = fin + setOwner(transFormedSym, fin) if c.config.backend == backendCpp or sfCompileToCpp in c.module.flags: let origParamType = transFormedSym.ast[bodyPos][1].typ let selfSymbolType = makePtrType(c, origParamType.skipTypes(abstractPtrs)) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 506e0694c610..2bf5877402fa 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -908,7 +908,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if sfGenSym notin v.flags: if not isDiscardUnderscore(v): addInterfaceDecl(c, v) else: - if v.owner == nil: v.owner() = c.p.owner + if v.owner == nil: setOwner(v, c.p.owner) when oKeepVariableNames: if c.inUnrolledContext > 0: v.flags.incl(sfShadowed) else: @@ -1026,7 +1026,7 @@ proc semConst(c: PContext, n: PNode): PNode = when defined(nimsuggest): v.hasUserSpecifiedType = hasUserSpecifiedType if sfGenSym notin v.flags: addInterfaceDecl(c, v) - elif v.owner == nil: v.owner() = getCurrOwner(c) + elif v.owner == nil: setOwner(v, getCurrOwner(c)) styleCheckDef(c, v) onDef(a[j].info, v) @@ -1097,7 +1097,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = v.typ = iter[i] n[0][i] = newSymNode(v) if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v) - elif v.owner == nil: v.owner() = getCurrOwner(c) + elif v.owner == nil: setOwner(v, getCurrOwner(c)) else: var v = symForVar(c, n[0]) if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) @@ -1107,7 +1107,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = v.typ = iterBase n[0] = newSymNode(v) if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v) - elif v.owner == nil: v.owner() = getCurrOwner(c) + elif v.owner == nil: setOwner(v, getCurrOwner(c)) else: localError(c.config, n.info, errWrongNumberOfVariables) elif n.len-2 != iterAfterVarLent.len: @@ -1141,7 +1141,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = v.typ = iter[i][j] n[i][j] = newSymNode(v) if not isDiscardUnderscore(v): addDecl(c, v) - elif v.owner == nil: v.owner() = getCurrOwner(c) + elif v.owner == nil: setOwner(v, getCurrOwner(c)) else: var v = symForVar(c, n[i]) if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal) @@ -1156,7 +1156,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = n[i] = newSymNode(v) if sfGenSym notin v.flags: if not isDiscardUnderscore(v): addDecl(c, v) - elif v.owner == nil: v.owner() = getCurrOwner(c) + elif v.owner == nil: setOwner(v, getCurrOwner(c)) inc(c.p.nestedLoopCounter) let oldBreakInLoop = c.p.breakInLoop c.p.breakInLoop = true @@ -1475,7 +1475,7 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) = s = typsym # add it here, so that recursive types are possible: if sfGenSym notin s.flags: addInterfaceDecl(c, s) - elif s.owner == nil: s.owner() = getCurrOwner(c) + elif s.owner == nil: setOwner(s, getCurrOwner(c)) if name.kind == nkPragmaExpr: if name[0].kind == nkPostfix: @@ -2362,7 +2362,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, n[namePos] = newSymNode(s) of nkSym: s = n[namePos].sym - s.owner() = c.getCurrOwner + setOwner(s, c.getCurrOwner) else: # Highlighting needs to be done early so the position for # name isn't changed (see taccent_highlight). We don't want to check if this is the @@ -2629,7 +2629,7 @@ proc semIterator(c: PContext, n: PNode): PNode = # gensym'ed iterator? if n[namePos].kind == nkSym: # gensym'ed iterators might need to become closure iterators: - n[namePos].sym.owner() = getCurrOwner(c) + setOwner(n[namePos].sym, getCurrOwner(c)) n[namePos].sym.transitionRoutineSymKind(skIterator) result = semProcAux(c, n, skIterator, iteratorPragmas) # bug #7093: if after a macro transformation we don't have an diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index eb03bffb3fd7..6e509ddc1f59 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1096,7 +1096,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = if sfGenSym in param.flags: # bug #XXX, fix the gensym'ed parameters owner: if param.owner == nil: - param.owner() = getCurrOwner(c) + setOwner(param, getCurrOwner(c)) else: addDecl(c, param) template shouldHaveMeta(t) = diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index f2964f86bcfe..09cf422b494f 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -358,7 +358,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym, t: PType): PSym = result = copySym(s, cl.c.idgen) incl(result.flags, sfFromGeneric) #idTablePut(cl.symMap, s, result) - result.owner() = s.owner + setOwner(result, s.owner) result.typ = t if result.kind != skType: result.ast = replaceTypeVarsN(cl, s.ast) diff --git a/compiler/transf.nim b/compiler/transf.nim index 93b1e2c733b1..747f49e8be9b 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -176,7 +176,7 @@ proc freshVar(c: PTransf; v: PSym): PNode = let owner = getCurrOwner(c) var newVar = copySym(v, c.idgen) incl(newVar.flags, sfFromGeneric) - newVar.owner() = owner + setOwner(newVar, owner) result = newSymNode(newVar) proc transformVarSection(c: PTransf, v: PNode): PNode = diff --git a/tests/ccgbugs/timportc_distinct.nim b/tests/ccgbugs/timportc_distinct.nim new file mode 100644 index 000000000000..afeadf33f9ed --- /dev/null +++ b/tests/ccgbugs/timportc_distinct.nim @@ -0,0 +1,13 @@ +discard """ + ccodecheck: "time_t" + joinable: false +""" + +type + Time* {.importc: "time_t", header: "".} = distinct clong + +proc foo = + var s: Time = default(Time) + discard s + +foo()