fixes addr/hiddenAddr in strictdefs (#23477)

(cherry picked from commit 9b378296f6)
(cherry picked from commit 744b241e4b7cb8c8d9e21e8a7f078d17d9ef90d4)
This commit is contained in:
ringabout
2024-04-10 20:41:16 +08:00
committed by narimiran
parent a70b4712fc
commit fe72db98c1
28 changed files with 66 additions and 75 deletions

View File

@@ -890,7 +890,7 @@ proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym =
result = nextIter(ti, tab)
iterator items*(tab: TStrTable): PSym =
var it: TTabIter
var it: TTabIter = default(TTabIter)
var s = initTabIter(it, tab)
while s != nil:
yield s
@@ -1054,14 +1054,6 @@ proc iiTablePut(t: var TIITable, key, val: int) =
iiTableRawInsert(t.data, key, val)
inc(t.counter)
proc isAddrNode*(n: PNode): bool =
case n.kind
of nkAddr, nkHiddenAddr: true
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mAddr: true
else: false
else: false
proc listSymbolNames*(symbols: openArray[PSym]): string =
for sym in symbols:
if result.len > 0:

View File

@@ -760,7 +760,7 @@ proc getRecordFields(m: BModule; typ: PType, check: var IntSet): Rope =
genMemberProcHeader(m, prc, header, false, true)
result.addf "$1;$n", [header]
if isCtorGen and not isDefaultCtorGen:
var ch: IntSet
var ch: IntSet = default(IntSet)
result.addf "$1() = default;$n", [getTypeDescAux(m, typ, ch, dkOther)]
proc fillObjectFields*(m: BModule; typ: PType) =
@@ -1594,7 +1594,7 @@ proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TType
))
)
else:
let addrOf = newNodeIT(nkAddr, info, theProc.typ[1])
let addrOf = newNodeIT(nkHiddenAddr, info, theProc.typ[1])
addrOf.add newDeref(newTreeIT(
nkCast, info, castType, newNodeIT(nkType, info, castType),
newSymNode(dest)

View File

@@ -423,8 +423,8 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
proc callForeignFunction*(conf: ConfigRef, call: PNode): PNode =
internalAssert conf, call[0].kind == nkPtrLit
var cif: TCif
var sig: ParamList
var cif: TCif = default(TCif)
var sig: ParamList = default(ParamList)
# use the arguments' types for varargs support:
for i in 1..<call.len:
sig[i-1] = mapType(conf, call[i].typ)
@@ -463,8 +463,8 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
info: TLineInfo): PNode =
internalAssert conf, fn.kind == nkPtrLit
var cif: TCif
var sig: ParamList
var cif: TCif = default(TCif)
var sig: ParamList = default(ParamList)
for i in 0..len-1:
var aTyp = args[i+start].typ
if aTyp.isNil:

View File

@@ -141,7 +141,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym; importSet: var IntSet) =
# for an enumeration we have to add all identifiers
if multiImport:
# for a overloadable syms add all overloaded routines
var it: ModuleIter
var it: ModuleIter = default(ModuleIter)
var e = initModuleIter(it, c.graph, fromMod, s.name)
while e != nil:
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")

View File

@@ -896,7 +896,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
p.body.add("++excHandler;\L")
var tmpFramePtr = rope"F"
lineF(p, "try {$n", [])
var a: TCompRes
var a: TCompRes = default(TCompRes)
gen(p, n[0], a)
moveInto(p, a, r)
var generalCatchBranchExists = false

View File

@@ -137,7 +137,7 @@ proc nextIdentIter(ti: var ModuleIter; marked: var IntSet; im: ImportedModule;
return result
iterator symbols(im: ImportedModule; marked: var IntSet; name: PIdent; g: ModuleGraph): PSym =
var ti: ModuleIter
var ti: ModuleIter = default(ModuleIter)
var candidate = initIdentIter(ti, marked, im, name, g)
while candidate != nil:
yield candidate
@@ -150,7 +150,7 @@ iterator importedItems*(c: PContext; name: PIdent): PSym =
yield s
proc allPureEnumFields(c: PContext; name: PIdent): seq[PSym] =
var ti: TIdentIter
var ti: TIdentIter = default(TIdentIter)
result = @[]
var res = initIdentIter(ti, c.pureEnumFields, name)
while res != nil:
@@ -222,7 +222,7 @@ proc debugScopes*(c: PContext; limit=0, max = int.high) {.deprecated.} =
proc searchInScopesAllCandidatesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSym] =
result = @[]
for scope in allScopes(c.currentScope):
var ti: TIdentIter
var ti: TIdentIter = default(TIdentIter)
var candidate = initIdentIter(ti, scope.symbols, s)
while candidate != nil:
if candidate.kind in filter:
@@ -240,7 +240,7 @@ proc searchInScopesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSy
result = @[]
block outer:
for scope in allScopes(c.currentScope):
var ti: TIdentIter
var ti: TIdentIter = default(TIdentIter)
var candidate = initIdentIter(ti, scope.symbols, s)
while candidate != nil:
if candidate.kind in filter:
@@ -272,7 +272,7 @@ proc isAmbiguous*(c: PContext, s: PIdent, filter: TSymKinds, sym: var PSym): boo
result = false
block outer:
for scope in allScopes(c.currentScope):
var ti: TIdentIter
var ti: TIdentIter = default(TIdentIter)
var candidate = initIdentIter(ti, scope.symbols, s)
var scopeHasCandidate = false
while candidate != nil:
@@ -347,7 +347,7 @@ proc getSymRepr*(conf: ConfigRef; s: PSym, getDeclarationPath = true): string =
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
# check if all symbols have been used and defined:
var it: TTabIter
var it: TTabIter = default(TTabIter)
var s = initTabIter(it, scope.symbols)
var missingImpls = 0
var unusedSyms: seq[tuple[sym: PSym, key: string]]
@@ -557,7 +557,7 @@ proc errorUseQualifier(c: PContext; info: TLineInfo; s: PSym; amb: var bool): PS
amb = false
proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
var amb: bool
var amb: bool = false
discard errorUseQualifier(c, info, s, amb)
proc errorUseQualifier*(c: PContext; info: TLineInfo; candidates: seq[PSym]; prefix = "use one of") =
@@ -680,7 +680,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
result = strTableGet(c.topLevelScope.symbols, ident)
else:
if c.importModuleLookup.getOrDefault(m.name.id).len > 1:
var amb: bool
var amb: bool = false
result = errorUseQualifier(c, n.info, m, amb)
else:
result = someSym(c.graph, m, ident)

View File

@@ -195,8 +195,8 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
var stream = llStreamOpen(f, fmRead)
if stream != nil:
var
L: Lexer
tok: Token
L: Lexer = default(Lexer)
tok: Token = default(Token)
initToken(tok)
openLexer(L, f, stream, cache, config)
while true:

View File

@@ -251,7 +251,7 @@ proc nextModuleIter*(mi: var ModuleIter; g: ModuleGraph): PSym =
iterator allSyms*(g: ModuleGraph; m: PSym): PSym =
let importHidden = optImportHidden in m.options
if isCachedModule(g, m):
var rodIt: RodIter
var rodIt: RodIter = default(RodIter)
var r = initRodIterAllSyms(rodIt, g.config, g.cache, g.packed, FileIndex m.position, importHidden)
while r != nil:
yield r
@@ -272,7 +272,7 @@ proc systemModuleSym*(g: ModuleGraph; name: PIdent): PSym =
result = someSym(g, g.systemModule, name)
iterator systemModuleSyms*(g: ModuleGraph; name: PIdent): PSym =
var mi: ModuleIter
var mi: ModuleIter = default(ModuleIter)
var r = initModuleIter(mi, g, g.systemModule, name)
while r != nil:
yield r

View File

@@ -125,14 +125,14 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
conf.m.filenameToIndexTbl[canon2] = result
proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
var dummy: bool
var dummy: bool = false
result = fileInfoIdx(conf, filename, dummy)
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile; isKnownFile: var bool): FileIndex =
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), isKnownFile)
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
var dummy: bool
var dummy: bool = false
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =

View File

@@ -40,7 +40,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
assert i != nil
assert i.mainModule != nil, "no main module selected"
let n = getIdent(i.graph.cache, name)
var it: ModuleIter
var it: ModuleIter = default(ModuleIter)
var s = initModuleIter(it, i.graph, i.mainModule, n)
result = nil
while s != nil:

View File

@@ -279,8 +279,8 @@ proc optimize*(n: PNode): PNode =
Now assume 'use' raises, then we shouldn't do the 'wasMoved(s)'
]#
var c: Con
var b: BasicBlock
var c: Con = Con()
var b: BasicBlock = default(BasicBlock)
analyse(c, b, n)
if c.somethingTodo:
result = shallowCopy(n)

View File

@@ -91,7 +91,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
stream: PLLStream): bool =
if graph.stopCompile(): return true
var
p: Parser
p: Parser = default(Parser)
s: PLLStream
fileIdx = module.fileIdx

View File

@@ -31,7 +31,7 @@ proc equalGenericParams(procA, procB: PNode): bool =
proc searchForProcAux(c: PContext, scope: PScope, fn: PSym): PSym =
const flags = {ExactGenericParams, ExactTypeDescValues,
ExactConstraints, IgnoreCC}
var it: TIdentIter
var it: TIdentIter = default(TIdentIter)
result = initIdentIter(it, scope.symbols, fn.name)
while result != nil:
if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags):
@@ -74,7 +74,7 @@ when false:
proc searchForBorrowProc*(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searches for the fn in the symbol table. If the parameter lists are suitable
# for borrowing the sym in the symbol table is returned, else nil.
var it: TIdentIter
var it: TIdentIter = default(TIdentIter)
for scope in walkScopes(startScope):
result = initIdentIter(it, scope.symbols, fn.Name)
while result != nil:

View File

@@ -408,7 +408,8 @@ proc strongConnect(v: var DepN, idx: var int, s: var seq[DepN],
proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
## Tarjan's algorithm. Performs a topological sort
## and detects strongly connected components.
var s: seq[DepN]
result = @[]
var s: seq[DepN] = @[]
var idx = 0
for v in g.mitems:
if v.idx < 0:

View File

@@ -68,7 +68,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
# `matches` may find new symbols, so keep track of count
var symCount = c.currentScope.symbols.counter
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
# https://github.com/nim-lang/Nim/issues/21272
# prevent mutation during iteration by storing them in a seq
# luckily `initCandidateSymbols` does just that
@@ -399,7 +399,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
proc bracketNotFoundError(c: PContext; n: PNode) =
var errors: CandidateErrors = @[]
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
let headSymbol = n[0]
var symx = initOverloadIter(o, c, headSymbol)
while symx != nil:
@@ -421,7 +421,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
# also avoid slowdowns in evaluating `compiles(expr)`.
discard
else:
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var sym = initOverloadIter(o, c, f)
while sym != nil:
result &= "\n found $1" % [getSymRepr(c.config, sym)]
@@ -465,7 +465,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
filter, result, alt, errors, efExplain in flags,
errorsEnabled, flags)
var dummyErrors: CandidateErrors
var dummyErrors: CandidateErrors = @[]
template pickSpecialOp(headSymbol) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
filter, result, alt, dummyErrors, efExplain in flags,

View File

@@ -2265,7 +2265,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
let headSymbol = macroCall[0]
var cands = 0
var cand: PSym = nil
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var symx = initOverloadIter(o, c, headSymbol)
while symx != nil:
if symx.kind in {skTemplate, skMacro} and symx.typ.len == macroCall.len:
@@ -2516,9 +2516,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
of mAddr:
markUsed(c, n.info, s)
checkSonsLen(n, 2, c.config)
result[0] = newSymNode(s, n[0].info)
result[1] = semAddrArg(c, n[1])
result.typ = makePtrType(c, result[1].typ)
result = semAddr(c, n[1])
of mTypeOf:
markUsed(c, n.info, s)
result = semTypeOf(c, n)
@@ -2933,7 +2931,7 @@ proc semExport(c: PContext, n: PNode): PNode =
result = newNodeI(nkExportStmt, n.info)
for i in 0..<n.len:
let a = n[i]
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var s = initOverloadIter(o, c, a)
if s == nil:
localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a))
@@ -3075,7 +3073,7 @@ proc getNilType(c: PContext): PType =
c.nilTypeCache = result
proc enumFieldSymChoice(c: PContext, n: PNode, s: PSym; flags: TExprFlags): PNode =
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var i = 0
var a = initOverloadIter(o, c, n)
while a != nil:
@@ -3401,8 +3399,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
of nkAddr:
result = n
checkSonsLen(n, 1, c.config)
result[0] = semAddrArg(c, n[0])
result.typ = makePtrType(c, result[0].typ)
result = semAddr(c, n[0])
of nkHiddenAddr, nkHiddenDeref:
checkSonsLen(n, 1, c.config)
n[0] = semExpr(c, n[0], flags, expectedType)

View File

@@ -251,7 +251,7 @@ proc semGenericStmt(c: PContext, n: PNode,
#var s = qualifiedLookUp(c, n, luf)
#if s != nil: result = semGenericStmtSymbol(c, n, s)
# XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
var dummy: bool
var dummy: bool = false
result = fuzzyLookup(c, n, flags, ctx, dummy)
of nkSym:
let a = n.sym

View File

@@ -30,13 +30,15 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode =
if asgnExpr.sons.len > 1:
result = newTree(nkAsgn, result[1], asgnExpr)
proc semAddrArg(c: PContext; n: PNode): PNode =
proc semAddr(c: PContext; n: PNode): PNode =
result = newNodeI(nkAddr, n.info)
let x = semExprWithType(c, n)
if x.kind == nkSym:
x.sym.flags.incl(sfAddrTaken)
if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}:
localError(c.config, n.info, errExprHasNoAddress)
result = x
result.add x
result.typ = makePtrType(c, x.typ)
proc semTypeOf(c: PContext; n: PNode): PNode =
var m = BiggestInt 1 # typeOfIter
@@ -551,9 +553,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
case n[0].sym.magic
of mAddr:
checkSonsLen(n, 2, c.config)
result = n
result[1] = semAddrArg(c, n[1])
result.typ = makePtrType(c, result[1].typ)
result = semAddr(c, n[1])
of mTypeOf:
result = semTypeOf(c, n)
of mSizeOf:

View File

@@ -581,7 +581,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
if paramType != nil and tfNotNil in paramType.flags and n.typ != nil:
let ntyp = n.typ.skipTypesOrNil({tyVar, tyLent, tySink})
if ntyp != nil and tfNotNil notin ntyp.flags:
if isAddrNode(n):
if n.kind in {nkAddr, nkHiddenAddr}:
# addr(x[]) can't be proven, but addr(x) can:
if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
elif (n.kind == nkSym and n.sym.kind in routineKinds) or
@@ -1059,7 +1059,8 @@ proc track(tracked: PEffects, n: PNode) =
# bug #15038: ensure consistency
if n.typ == nil or (not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ)): n.typ = n.sym.typ
of nkHiddenAddr, nkAddr:
if n[0].kind == nkSym and isLocalSym(tracked, n[0].sym):
if n[0].kind == nkSym and isLocalSym(tracked, n[0].sym) and
n.typ.kind notin {tyVar, tyLent}:
useVarNoInitCheck(tracked, n[0], n[0].sym)
else:
track(tracked, n[0])

View File

@@ -1159,7 +1159,7 @@ proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string;
if maType == nil: return
let headSymbol = selector[0]
var o: TOverloadIter
var o: TOverloadIter = default(TOverloadIter)
var match: PSym = nil
var symx = initOverloadIter(o, c, headSymbol)
while symx != nil:
@@ -1193,7 +1193,7 @@ proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
toResolve.add newIdentNode(getIdent(c.cache, "case"), n.info)
toResolve.add n[0]
var errors: CandidateErrors
var errors: CandidateErrors = @[]
var r = resolveOverloads(c, toResolve, toResolve, {skTemplate, skMacro}, {efNoDiagnostics},
errors, false)
if r.state == csMatch:

View File

@@ -51,7 +51,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
isField = false): PNode =
var
a: PSym
o: TOverloadIter
o: TOverloadIter = default(TOverloadIter)
var i = 0
a = initOverloadIter(o, c, n)
while a != nil:

View File

@@ -1873,7 +1873,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
return errorSym(c, n)
if result.kind != skType and result.magic notin {mStatic, mType, mTypeOf}:
# this implements the wanted ``var v: V, x: V`` feature ...
var ov: TOverloadIter
var ov: TOverloadIter = default(TOverloadIter)
var amb = initOverloadIter(ov, c, n)
while amb != nil and amb.kind != skType:
amb = nextOverloadIter(ov, c, n)

View File

@@ -260,7 +260,8 @@ when defined(debugSigHashes):
# (select hash from sighashes group by hash having count(*) > 1) order by hash;
proc hashType*(t: PType; conf: ConfigRef; flags: set[ConsiderFlag] = {CoType}): SigHash =
var c: MD5Context
result = default(SigHash)
var c: MD5Context = default(MD5Context)
md5Init c
hashType c, t, flags+{CoOwnerSig}, conf
md5Final c, result.MD5Digest
@@ -269,7 +270,8 @@ proc hashType*(t: PType; conf: ConfigRef; flags: set[ConsiderFlag] = {CoType}):
typeToString(t), $result)
proc hashProc(s: PSym; conf: ConfigRef): SigHash =
var c: MD5Context
result = default(SigHash)
var c: MD5Context = default(MD5Context)
md5Init c
hashType c, s.typ, {CoProc}, conf
@@ -289,7 +291,8 @@ proc hashProc(s: PSym; conf: ConfigRef): SigHash =
md5Final c, result.MD5Digest
proc hashNonProc*(s: PSym): SigHash =
var c: MD5Context
result = default(SigHash)
var c: MD5Context = default(MD5Context)
md5Init c
hashSym(c, s)
var it = s
@@ -305,7 +308,8 @@ proc hashNonProc*(s: PSym): SigHash =
md5Final c, result.MD5Digest
proc hashOwner*(s: PSym): SigHash =
var c: MD5Context
result = default(SigHash)
var c: MD5Context = default(MD5Context)
md5Init c
var m = s
while m.kind != skModule: m = m.owner
@@ -378,7 +382,7 @@ proc symBodyDigest*(graph: ModuleGraph, sym: PSym): SigHash =
graph.symBodyHashes.withValue(sym.id, value):
return value[]
var c: MD5Context
var c: MD5Context = default(MD5Context)
md5Init(c)
c.hashType(sym.typ, {CoProc}, graph.config)
c &= char(sym.kind)

View File

@@ -57,7 +57,7 @@ proc parsePipe(filename: AbsoluteFile, inputStream: PLLStream; cache: IdentCache
else:
inc(i, 2)
while i < line.len and line[i] in Whitespace: inc(i)
var p: Parser
var p: Parser = default(Parser)
openParser(p, filename, llStreamOpen(substr(line, i)), cache, config)
result = parseAll(p)
closeParser(p)

View File

@@ -875,10 +875,6 @@ proc transformCall(c: PTransf, n: PNode): PNode =
inc(j)
result.add(a)
if result.len == 2: result = result[1]
elif magic == mAddr:
result = newTransNode(nkAddr, n, 1)
result[0] = n[1]
result = transformAddrDeref(c, result, {nkDerefExpr, nkHiddenDeref})
elif magic in {mNBindSym, mTypeOf, mRunnableExamples}:
# for bindSym(myconst) we MUST NOT perform constant folding:
result = n

View File

@@ -286,7 +286,7 @@ proc loadAny(p: var JsonParser, t: PType,
proc loadAny*(s: string; t: PType; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator): PNode =
var tab = initTable[BiggestInt, PNode]()
var p: JsonParser
var p: JsonParser = default(JsonParser)
open(p, newStringStream(s), "unknown file")
next(p)
result = loadAny(p, t, tab, cache, conf, idgen)

View File

@@ -1414,7 +1414,7 @@ proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
doAssert a.hasKey('a') == true
doAssert a.hasKey('z') == false
var hc: Hash
var hc: Hash = default(Hash)
result = rawGet(t, key, hc) >= 0
proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =

View File

@@ -124,7 +124,7 @@ static:
let fn4s = "proc fn4(x: int): int =\n if x mod 2 == 0:\n return x + 2\n else:\n return 0\n"
let fn5s = "proc fn5(a, b: float): float =\n result = -a * a / (b * b)\n"
let fn6s = "proc fn6() =\n var a = @[1.0, 2.0]\n let z = a{0, 1}\n a{2} = 5.0\n"
let fnAddr = "proc fn_unsafeaddr(x: int): int =\n result = cast[int](unsafeAddr(x))\n"
let fnAddr = "proc fn_unsafeaddr(x: int): int =\n result = cast[int](addr(x))\n"
doAssert fn1.repr_to_string == fn1s
doAssert fn2.repr_to_string == fn2s