diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 274477fc8b..b3d95b67f3 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2853,7 +2853,11 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = raiseInstr(p, p.s(cpsStmts)) linefmt p, cpsStmts, "}$n", [] - if n[0].typ.kind != tyObject: + # skip cast when types map to the same C type + # this avoids invalid C code like `*(T*)&x` for types that can't have their address taken (e.g., WASM __externref_t) + if getTypeDesc(p.module, n.typ) == getTypeDesc(p.module, n[0].typ): + expr(p, n[0], d) + elif n[0].typ.kind != tyObject: if n.isLValue: putIntoDest(p, d, n, "(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage) @@ -2881,7 +2885,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) = var a: TLoc = initLocExpr(p, arg) putIntoDest(p, d, n, "(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage) - elif p.module.compileToCpp: + elif p.module.compileToCpp or isImportedType(src): # C++ implicitly downcasts for us expr(p, arg, d) else: diff --git a/tests/ccgbugs2/tcodegen.nim b/tests/ccgbugs2/tcodegen.nim index 37579e0bf4..bca361e813 100644 --- a/tests/ccgbugs2/tcodegen.nim +++ b/tests/ccgbugs2/tcodegen.nim @@ -56,3 +56,22 @@ proc main = # bug #24677 for NDEBUG in 0..2: doAssert NDEBUG == NDEBUG main() + +block: # importc type inheritance + type + A {.inheritable, pure, bycopy, importc: "int".} = object + B {.importc: "int", bycopy.} = object of A + + {.emit: """ + int foo(int a) { + return 123; + } + """.} + + proc foo(a: A): B {.importc, nodecl.} + + var a: A + var b = foo(a) + doAssert(cast[cint](b) == 123) + var c = foo(b) + doAssert(cast[cint](c) == 123)