From 2d1412a2eae9abc7c5827fac5bf028f71599790a Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:37:15 +0800 Subject: [PATCH] fixes #26015; Multiple definition error when using codegenDecl regression (#26018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #26015 Fixes imported global variables with codegenDecl being emitted as definitions instead of extern declarations. A variable’s codegenDecl format should customize its definition in the owning module. Other modules referencing the variable must emit a normal declaration: ```c extern NI variable; ``` After the variable-declaration builder refactor, genVarPrototype passed Extern visibility to addVar. However, the sfCodegenDecl branch returned before applying that visibility. This caused importing modules to emit another tentative definition, resulting in duplicate-symbol linker errors. The fix restores the previous distinction between the custom definition and cross-module prototypes. It also adds C and C++ regression coverage for both direct access and access through an inline procedure. follows up https://github.com/nim-lang/Nim/pull/24423 --- compiler/cgen.nim | 14 ++++++++++---- tests/ccgbugs/mcodegendeclglobal.nim | 4 ++++ tests/ccgbugs/tcodegendeclglobal.nim | 13 +++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 tests/ccgbugs/mcodegendeclglobal.nim create mode 100644 tests/ccgbugs/tcodegendeclglobal.nim diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 4cdd86347a..8566c62632 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1854,10 +1854,16 @@ proc genVarPrototype(m: BModule, n: PNode) = typ = ptrType(typ) if lfDynamicLib in sym.loc.flags: typ = ptrType(typ) - m.s[cfsVars].addVar(m, sym, - name = sym.loc.snippet, - typ = typ, - visibility = vis) + if sfCodegenDecl in sym.flags: + m.s[cfsVars].addDeclWithVisibility(vis): + m.s[cfsVars].addVar(m, sym, + name = sym.loc.snippet, + typ = typ) + else: + m.s[cfsVars].addVar(m, sym, + name = sym.loc.snippet, + typ = typ, + visibility = vis) if m.hcrOn: m.initProc.procSec(cpsLocals).add('\t') m.initProc.procSec(cpsLocals).addAssignment(sym.loc.snippet, diff --git a/tests/ccgbugs/mcodegendeclglobal.nim b/tests/ccgbugs/mcodegendeclglobal.nim new file mode 100644 index 0000000000..1f2ab904f4 --- /dev/null +++ b/tests/ccgbugs/mcodegendeclglobal.nim @@ -0,0 +1,4 @@ +var codegenDeclGlobal* {.codegenDecl: "$# /* custom declaration */ $#".} = 123 + +proc readCodegenDeclGlobal*(): int {.inline.} = + codegenDeclGlobal diff --git a/tests/ccgbugs/tcodegendeclglobal.nim b/tests/ccgbugs/tcodegendeclglobal.nim new file mode 100644 index 0000000000..b630d948c7 --- /dev/null +++ b/tests/ccgbugs/tcodegendeclglobal.nim @@ -0,0 +1,13 @@ +discard """ + output: ''' +123 +123 +''' + ccodecheck: "'extern NI /* custom declaration */ codegenDeclGlobal'" + targets: "c cpp" +""" + +import ./mcodegendeclglobal + +echo codegenDeclGlobal +echo readCodegenDeclGlobal()