From 9c85f4fd074661fcdd7fa233f2c152d4b560b32e Mon Sep 17 00:00:00 2001 From: metagn Date: Fri, 11 Oct 2024 11:36:40 +0300 Subject: [PATCH] fix deref/addr pair deleting assignment location in C++ (#24280) fixes #24274 The code in the `if` branch replaces the current destination `d` with a new one. But the location `d` can be an assignment location, in which case the provided expression isn't generated. To fix this, don't trigger this code for when the location already exists. An alternative would be to call `putIntoDest` in this case as is done below. --- compiler/ccgexprs.nim | 5 ++++- tests/ccgbugs/tvararrayiter.nim | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/ccgbugs/tvararrayiter.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 545d43ae83..a344816ba8 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -758,7 +758,10 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass: typ = typ.last typ = typ.skipTypes(abstractInstOwned) - if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e[0].kind == nkHiddenAddr: + if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and + p.module.compileToCpp and e[0].kind == nkHiddenAddr and + # don't override existing location: + d.k == locNone: d = initLocExprSingleUse(p, e[0][0]) return else: diff --git a/tests/ccgbugs/tvararrayiter.nim b/tests/ccgbugs/tvararrayiter.nim new file mode 100644 index 0000000000..b1f8c2087e --- /dev/null +++ b/tests/ccgbugs/tvararrayiter.nim @@ -0,0 +1,21 @@ +discard """ + targets: "c cpp" +""" + +block: # issue #24274 + iterator foo[T](x: var T): var T = + yield x + + var x: array[3, char] + for a in foo(x): + let b = a + + var y: array[3, char] = ['a', 'b', 'c'] + for a in foo(y): + let b = a + doAssert a[0] == 'a' + doAssert a[1] == 'b' + doAssert a[2] == 'c' + doAssert b[0] == 'a' + doAssert b[1] == 'b' + doAssert b[2] == 'c'