From 1244ef260b2562d29a88dd3f8376fa352c36d9a4 Mon Sep 17 00:00:00 2001 From: drpriver Date: Tue, 15 Apr 2025 19:13:50 -0700 Subject: [PATCH] Fix #21241 - ImportC: wrong static function called after linking (#21242) Fixes https://github.com/dlang/dmd/issues/21241 C Static functions were being given the same externally mangled name as their identifier, which caused only one to be picked when linking with linkers that supported that. Additionally, the dmd glue code was only outputting one of these static functions as a workaround for a different linker issue. Solve this by giving C static functions a unique name (by using D mangling) and adding an `isStatic()` check to the dmd glue hack. --- compiler/src/dmd/mangle/package.d | 6 +++++- compiler/src/dmd/tocsym.d | 1 + compiler/test/runnable/imports/imp21241a.c | 9 +++++++++ compiler/test/runnable/imports/imp21241b.c | 9 +++++++++ compiler/test/runnable/test21241.d | 13 +++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 compiler/test/runnable/imports/imp21241a.c create mode 100644 compiler/test/runnable/imports/imp21241b.c create mode 100644 compiler/test/runnable/test21241.d diff --git a/compiler/src/dmd/mangle/package.d b/compiler/src/dmd/mangle/package.d index 3ad2c7d579..cc797614ed 100644 --- a/compiler/src/dmd/mangle/package.d +++ b/compiler/src/dmd/mangle/package.d @@ -1339,7 +1339,11 @@ extern (D) const(char)[] externallyMangledIdentifier(Declaration d) const par = d.toParent(); //toParent() skips over mixin templates if (!par || par.isModule() || linkage == LINK.cpp || (linkage == LINK.c && d.isCsymbol() && - (d.isFuncDeclaration() || + // https://github.com/dlang/dmd/issues/21241 + // Static check is so C static functions get a unique mangle so the linker + // won't merge them if compiling all-at-once. + // Non-static functions can use their ident as their mangle. + ((d.isFuncDeclaration() && !d.isStatic()) || (d.isVarDeclaration() && d.isDataseg() && d.storage_class & STC.extern_)))) { if (linkage != LINK.d && d.localNum) diff --git a/compiler/src/dmd/tocsym.d b/compiler/src/dmd/tocsym.d index 557e2d6e89..71ecf387e0 100644 --- a/compiler/src/dmd/tocsym.d +++ b/compiler/src/dmd/tocsym.d @@ -356,6 +356,7 @@ Symbol* toSymbol(Dsymbol s) mod.filetype == FileType.c && // a C file fd.fbody && // a function definition fd._linkage == LINK.c && + !fd.isStatic() && !fd.skipCodegen) // code gen is desired { __gshared DsymbolTable Csymtab; // sorry about another global variable diff --git a/compiler/test/runnable/imports/imp21241a.c b/compiler/test/runnable/imports/imp21241a.c new file mode 100644 index 0000000000..6a40949fcf --- /dev/null +++ b/compiler/test/runnable/imports/imp21241a.c @@ -0,0 +1,9 @@ +// https://github.com/dlang/dmd/issues/21241 +enum {aValue=1}; +static int foo(void){ + return aValue; +} + +int getA(void){ + return foo(); +} diff --git a/compiler/test/runnable/imports/imp21241b.c b/compiler/test/runnable/imports/imp21241b.c new file mode 100644 index 0000000000..4808fb6b97 --- /dev/null +++ b/compiler/test/runnable/imports/imp21241b.c @@ -0,0 +1,9 @@ +// https://github.com/dlang/dmd/issues/21241 +enum {bValue=2}; +static int foo(void){ + return bValue; +} + +int getB(void){ + return foo(); +} diff --git a/compiler/test/runnable/test21241.d b/compiler/test/runnable/test21241.d new file mode 100644 index 0000000000..c63011bcfa --- /dev/null +++ b/compiler/test/runnable/test21241.d @@ -0,0 +1,13 @@ +/* +REQUIRED_ARGS: runnable/imports/imp21241a.c runnable/imports/imp21241b.c +*/ +// https://github.com/dlang/dmd/issues/21241 +import imp21241a; +import imp21241b; + +void main(){ + int x = getA(); + assert(x==aValue); + x = getB(); + assert(x==bValue); +}