diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index ac2692b525..f3786c4c0c 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1774,12 +1774,20 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope = proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0 -proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; +proc generateRttiHook(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; info: TLineInfo; idgen: IdGenerator; theProc: PSym): PSym = # the wrapper is roughly like: # proc rttiDestroy(x: pointer) = # `=destroy`(cast[ptr T](x)[]) - let procname = getIdent(g.cache, "rttiDestroy") + # and for the =trace hook: + # proc rttiTrace(x, env: pointer) = + # `=trace`(cast[ptr T](x)[], env) + # The wrapper exists so that the RTTI slot is filled with a proc whose C + # signature really is `void (*)(void*)` / `void (*)(void*, void*)`. Calling + # the hook itself through such a pointer is UB and -fsanitize=function + # rightfully complains about it. + let hookName = if kind == attachedTrace: "rttiTrace" else: "rttiDestroy" + let procname = getIdent(g.cache, hookName) result = newSym(skProc, procname, idgen, owner, info) let dest = newSym(skParam, getIdent(g.cache, "dest"), idgen, result, info) @@ -1788,27 +1796,32 @@ proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TType result.typ = newProcType(info, idgen, result) result.typ.addParam dest + var env: PSym = nil + if kind == attachedTrace: + env = newSym(skParam, getIdent(g.cache, "env"), idgen, result, info) + env.typ = getSysType(g, info, tyPointer) + result.typ.addParam env + var n = newNodeI(nkProcDef, info, bodyPos+1) for i in 0..