diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 70386443e9..795ccce87f 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -3271,7 +3271,11 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseObjectConversionError")) raiseInstr(p, p.s(cpsStmts)) - 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: let destTyp = getTypeDesc(p.module, n.typ) let val = rdLoc(a) if n.isLValue: @@ -3317,7 +3321,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) = cCast(ptrType(destType), wrapPar(cAddr(wrapPar(val))))), 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)