Skip to content

fix #25870 #25846: var return type in C++ backend - #26008

Open
nimamasl114514 wants to merge 5 commits into
nim-lang:develfrom
nimamasl114514:fix-25870-final
Open

fix #25870 #25846: var return type in C++ backend#26008
nimamasl114514 wants to merge 5 commits into
nim-lang:develfrom
nimamasl114514:fix-25870-final

Conversation

@nimamasl114514

@nimamasl114514 nimamasl114514 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

fix #25870 #25846: C++ codegen for proc returning var T

The C++ codegen was generating conflicting types for procs with �ar T return:
the signature said T& but the internal result variable was T*, and callers
expected T& back. This caused link errors on some platforms (undefined symbols)
and clang errors on macOS.

The problem was that fVarIsPtr was being set too early (in semexprs) and leaked
into the proc type, so every place that looked at the return type saw T* instead
of T&. The fix moves the flag application into cgen where it belongs: we make a
shallow copy of the return type, set fVarIsPtr on the copy, and keep the
original clean for the signature.

There were also a few call sites that weren't updated when the signature changed
from T* to T&. Stuff like s[^1] in an �nd expression would hit the
splitDecls path and try to store a T& into a T* variable, which clang rightfully
refuses to compile. These now get the missing & operator.

Tested with
im c and
im cpp on the new test case, plus --threads:on.

@nimamasl114514
nimamasl114514 force-pushed the fix-25870-final branch 3 times, most recently from fbf941f to 68b3a92 Compare July 16, 2026 04:40
genProcParams strips tfVarIsPtr from the proc signature so C++
procs with var T return produce T& instead of T*. However the
call sites that assign results to T* temporaries (the else
branches of fixupCall, genClosureCall, and genNamedParamCall)
were not updated to match - they stored the T& result directly into
a T* variable, causing a dangling pointer (SIGSEGV) or a clang
compilation error on macOS.

This broke std/oserrors.nim in C++ mode when msg[^1] appeared
inside an and expression, triggering the splitDecls > 0 code path.

Fix: wrap the call result with cAddr() when tfVarIsPtr is set on
the return type, matching what getTempCpp already does.
Comment thread compiler/ccgcalls.nim Outdated
genNamedParamCall only runs for sfNamedParamCall procs, which come
from importObjC and compile to ObjC (.nim.m). ObjC has no C++
references, so var T is a pointer there and the cAddr() I added
would produce T**. The compileToCpp branch above it is also dead
since importObjC modules don't go through the C++ backend.

Pointed out by demotomohiro.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compile error from Clang when passing a procedural type with var return type

2 participants