@@ -449,6 +449,53 @@ proc semOld(c: PContext; n: PNode): PNode =
449449 localError (c.config, n[1 ].info, n[1 ].sym.name.s & " does not belong to " & getCurrOwner (c).name.s)
450450 result = n
451451
452+ proc semNewFinalize (c: PContext ; n: PNode ): PNode =
453+ # Make sure the finalizer procedure refers to a procedure
454+ if n[^ 1 ].kind == nkSym and n[^ 1 ].sym.kind notin {skProc, skFunc}:
455+ localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
456+ elif optTinyRtti in c.config.globalOptions:
457+ let nfin = skipConvCastAndClosure (n[^ 1 ])
458+ let fin = case nfin.kind
459+ of nkSym: nfin.sym
460+ of nkLambda, nkDo: nfin[namePos].sym
461+ else :
462+ localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
463+ nil
464+ if fin != nil :
465+ if fin.kind notin {skProc, skFunc}:
466+ # calling convention is checked in codegen
467+ localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
468+
469+ # check if we converted this finalizer into a destructor already:
470+ let t = whereToBindTypeHook (c, fin.typ[1 ].skipTypes (abstractInst+ {tyRef}))
471+ if t != nil and getAttachedOp (c.graph, t, attachedDestructor) != nil and
472+ getAttachedOp (c.graph, t, attachedDestructor).owner == fin:
473+ discard " already turned this one into a finalizer"
474+ else :
475+ if sfForward in fin.flags:
476+ let wrapperSym = newSym (skProc, getIdent (c.graph.cache, fin.name.s & " FinalizerWrapper" ), nextSymId c.idgen, fin.owner, fin.info)
477+ let selfSymNode = newSymNode (copySym (fin.ast[paramsPos][1 ][0 ].sym, nextSymId c.idgen))
478+ wrapperSym.flags.incl sfUsed
479+ let wrapper = c.semExpr (c, newProcNode (nkProcDef, fin.info, body = newTree (nkCall, newSymNode (fin), selfSymNode),
480+ params = nkFormalParams.newTree (c.graph.emptyNode,
481+ newTree (nkIdentDefs, selfSymNode, fin.ast[paramsPos][1 ][1 ], c.graph.emptyNode)
482+ ),
483+ name = newSymNode (wrapperSym), pattern = c.graph.emptyNode,
484+ genericParams = c.graph.emptyNode, pragmas = c.graph.emptyNode, exceptions = c.graph.emptyNode), {})
485+ var transFormedSym = turnFinalizerIntoDestructor (c, wrapperSym, wrapper.info)
486+ transFormedSym.owner = fin
487+ if c.config.backend == backendCpp or sfCompileToCpp in c.module.flags:
488+ let origParamType = transFormedSym.ast[bodyPos][1 ].typ
489+ let selfSymbolType = makePtrType (c, origParamType.skipTypes (abstractPtrs))
490+ let selfPtr = newNodeI (nkHiddenAddr, transFormedSym.ast[bodyPos][1 ].info)
491+ selfPtr.add transFormedSym.ast[bodyPos][1 ]
492+ selfPtr.typ = selfSymbolType
493+ transFormedSym.ast[bodyPos][1 ] = c.semExpr (c, selfPtr)
494+ bindTypeHook (c, transFormedSym, n, attachedDestructor)
495+ else :
496+ bindTypeHook (c, turnFinalizerIntoDestructor (c, fin, n.info), n, attachedDestructor)
497+ result = n
498+
452499proc semPrivateAccess (c: PContext , n: PNode ): PNode =
453500 let t = n[1 ].typ[0 ].toObjectFromRefPtrGeneric
454501 c.currentScope.allowPrivateAccess.add t.sym
@@ -513,30 +560,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
513560 else :
514561 result = plugin (c, n)
515562 of mNewFinalize:
516- # Make sure the finalizer procedure refers to a procedure
517- if n[^ 1 ].kind == nkSym and n[^ 1 ].sym.kind notin {skProc, skFunc}:
518- localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
519- elif optTinyRtti in c.config.globalOptions:
520- let nfin = skipConvCastAndClosure (n[^ 1 ])
521- let fin = case nfin.kind
522- of nkSym: nfin.sym
523- of nkLambda, nkDo: nfin[namePos].sym
524- else :
525- localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
526- nil
527- if fin != nil :
528- if fin.kind notin {skProc, skFunc}:
529- # calling convention is checked in codegen
530- localError (c.config, n.info, " finalizer must be a direct reference to a proc" )
531-
532- # check if we converted this finalizer into a destructor already:
533- let t = whereToBindTypeHook (c, fin.typ[1 ].skipTypes (abstractInst+ {tyRef}))
534- if t != nil and getAttachedOp (c.graph, t, attachedDestructor) != nil and
535- getAttachedOp (c.graph, t, attachedDestructor).owner == fin:
536- discard " already turned this one into a finalizer"
537- else :
538- bindTypeHook (c, turnFinalizerIntoDestructor (c, fin, n.info), n, attachedDestructor)
539- result = n
563+ result = semNewFinalize (c, n)
540564 of mDestroy:
541565 result = n
542566 let t = n[1 ].typ.skipTypes (abstractVar)
0 commit comments