Bug 20802 – [REG2.088.0] Link failure with writefln

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2020-05-06T20:18:45Z
Last change time
2024-03-04T02:51:57Z
Keywords
link-failure, pull
Assigned to
No Owner
Creator
Tim
See also
https://issues.dlang.org/show_bug.cgi?id=24428

Comments

Comment #0 by tim.dlang — 2020-05-06T20:18:45Z
The following code worked with 2.087.1, but doesn't link since 2.088.0: //////////////////// test.d /////////////////// import std.uni, std.stdio; class C { size_t number; } int main() { C inst; mixin({ while(false) { dchar current; CodepointSet(current); } return ""; }()); writefln("%d %d %d", inst.number, C.sizeof, inst.number ); return 0; } /////////////////////////////////////////////// With 2.088.0 it produces the following link error: /usr/bin/ld: test.o: in function `_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk': test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0xd6): undefined reference to `_D3std6format__T9getNthIntVAyaa13_696e7465676572207769647468TmTmTmZQBzFNaNfkmmmZi' /usr/bin/ld: test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0x16f): undefined reference to `_D3std6format__T9getNthIntVAyaa13_696e7465676572207769647468TmTmTmZQBzFNaNfkmmmZi' /usr/bin/ld: test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0x1c6): undefined reference to `_D3std6format__T9getNthIntVAyaa17_696e746567657220707265636973696f6eTmTmTmZQChFNaNfkmmmZi' /usr/bin/ld: test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0x254): undefined reference to `_D3std6format__T9getNthIntVAyaa17_696e746567657220707265636973696f6eTmTmTmZQChFNaNfkmmmZi' /usr/bin/ld: test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0x2a0): undefined reference to `_D3std6format__T9getNthIntVAyaa21_736570617261746f72206469676974207769647468TmTmTmZQCpFNaNfkmmmZi' /usr/bin/ld: test.d:(.text._D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk[_D3std6format__T14formattedWriteTSQBg5stdio4File17LockingTextWriterTaTmTmTmZQCiFNfKQByMxAammmZk]+0x2c9): undefined reference to `_D3std6format__T6getNthVAyaa19_736570617261746f7220636861726163746572SQCq6traits10isSomeCharTwTmTmTmZQDhFNaNfkmmmZw' collect2: Fehler: ld gab 1 als Ende-Status zurück It may be related to issue 17155, but since it was introduced in a different release I have created a separate issue.
Comment #1 by ibuclaw — 2023-01-10T18:17:38Z
Now: --- issue20802.o: in function `_D4core8internal7switch___T14__switch_errorZQrFNaNbNiNfAyamZv': issue20802.d:(.text._D4core8internal7switch___T14__switch_errorZQrFNaNbNiNfAyamZv[_D4core8internal7switch___T14__switch_errorZQrFNaNbNiNfAyamZv]+0x19): undefined reference to `_D4core9exception__T15__switch_errorTZQsFNaNbNiNeAyamZv' collect2: error: ld returned 1 exit status Error: linker exited with status 1
Comment #2 by alphaglosined — 2024-02-07T11:52:51Z
Another more slimmed down version that was experienced by someone on the N.G. ```d import std.uni, std.stdio; void main() { auto c1 = CodepointSet('a','z'+1); writefln("%s", c1); } ``` ``` /dlang/dmd/linux/bin64/../../src/druntime/import/core/internal/switch_.d:189: error: undefined reference to '_D4core9exception__T15__switch_errorTZQsFNaNbNiNeAyamZv' ``` https://forum.dlang.org/post/[email protected]
Comment #3 by spoov0.707 — 2024-02-11T11:04:38Z
The example can be simplified a bit, same error as in previous comment: ############ test.d ############## import std.uni; void main() { CodepointSet('a', 'z'); dstring s; decodeGrapheme(s); } ################################## Reducing std.uni yields the code below, same error as above: #### phobos/std/uni/package.d #### module std.uni; enum TransformRes { goOn } void writeAligned()() { final switch (TransformRes.goOn) { case TransformRes.goOn: break; } } struct GcPolicy {} alias CodepointSet = InversionList!GcPolicy; struct InversionList(SP=GcPolicy) { this()(uint[] intervals...) { sanitize(); } void sanitize() { throw new Exception(""); writeAligned(); } } void decodeGrapheme(Input)(ref Input inp) { final switch (TransformRes.goOn) { case TransformRes.goOn: break; } } ################################## A final switch generates a call to core.internal.switch_.__switch_error for handling the default case. core.internal.switch_.__switch_error calls core.exception.__switch_errorT. Both functions are templates. By default a D program links with libphobos2.a. libphobos2.a contains sanitize and writeAligned but not __switch_error and __switch_errorT. This is because libphobos2.a gets build in release mode which causes the call to __switch_error to be replaced with a ud2 instruction. The linker error shows that __switch_error is present but __switch_errorT is missing. In the compiler is this code https://github.com/dlang/dmd/blob/8ab0636400d890a777889b3c84b09bcaa119fd57/compiler/src/dmd/dsymbolsem.d#L4666 which handles the case where a template that got instantiated from a non-root module, gets instantiated from a root module. The code fixes the template instantiation, but misses the template instantiations that are caused by it. Because of this __switch_errorT is not emitted to the object file. The following three files form a minimal example that reproduces the issue: ############# a.d ################ import b; extern(C) void main() => bar!true; ############# b.d ################ void missing()() {} void foo()() => missing(); void bar(bool b)() { version (Release) {} else foo(); } enum fptr = &bar!false; ########## object.d ############## // empty to make debugging simpler $ dmd -c -version=Release b.d $ dmd a.d b.o a.o: In function `_D1b__T3fooZQfFNaNbNiNfZv': a.d:(.text._D1b__T3fooZQfFNaNbNiNfZv[_D1b__T3fooZQfFNaNbNiNfZv]+0x5): undefined reference to `_D1b__T7missingZQjFNaNbNiNfZv' collect2: error: ld returned 1 exit status Error: linker exited with status 1
Comment #4 by dlang-bot — 2024-02-18T12:21:24Z
@tim-dlang created dlang/dmd pull request #16200 "Fix Bugzilla 20802 - Link failure with writefln" fixing this issue: - Fix Bugzilla 20802 - Link failure with writefln The issue is caused by compiling druntime/phobos and the application with different flags. The template instance for __switch_errorT is not included in the build of druntime/phobos, because they are compiled with -release. DMD will also not include it in an application compiled without -release, because it assumes, that it is already in druntime. See comment https://issues.dlang.org/show_bug.cgi?id=20802#c3 by Spoov. As a workaround the template instance for __switch_errorT is now always instantiated in druntime. https://github.com/dlang/dmd/pull/16200
Comment #5 by dlang-bot — 2024-02-18T22:35:06Z
dlang/dmd pull request #16200 "Fix Bugzilla 20802 - Link failure with writefln" was merged into stable: - f4ee5234bccf21a4d2b5ca6d3962ccc3dd7a7d06 by Tim Schendekehl: Fix Bugzilla 20802 - Link failure with writefln The issue is caused by compiling druntime/phobos and the application with different flags. The template instance for __switch_errorT is not included in the build of druntime/phobos, because they are compiled with -release. DMD will also not include it in an application compiled without -release, because it assumes, that it is already in druntime. See comment https://issues.dlang.org/show_bug.cgi?id=20802#c3 by Spoov. The template instance for __switch_errorT is now always instantiated in druntime, so it is part of the ABI of druntime. https://github.com/dlang/dmd/pull/16200
Comment #6 by dfj1esp02 — 2024-02-19T07:28:13Z
This looks like a rather fundamental collision between speculative instantiation and conditional compilation. __switch_errorT can't be in druntime unconditionally because its behavior changes depending on compilation options.
Comment #7 by ibuclaw — 2024-02-20T13:22:39Z
(In reply to anonymous4 from comment #6) > This looks like a rather fundamental collision between speculative > instantiation and conditional compilation. __switch_errorT can't be in > druntime unconditionally because its behavior changes depending on > compilation options. Because it's a weak symbol, any local instantiation would override the unconditional instantiation in druntime.
Comment #8 by ibuclaw — 2024-02-20T13:23:37Z
*** Issue 23255 has been marked as a duplicate of this issue. ***
Comment #9 by ibuclaw — 2024-02-20T13:23:59Z
*** Issue 23209 has been marked as a duplicate of this issue. ***
Comment #10 by dlang-bot — 2024-03-01T23:56:54Z
dlang/dmd pull request #16276 "merge stable" was merged into master: - 6a2fe78ba45b4fcd495f7ab340f784640b9daf01 by Tim Schendekehl: Fix Bugzilla 20802 - Link failure with writefln (#16200) The issue is caused by compiling druntime/phobos and the application with different flags. The template instance for __switch_errorT is not included in the build of druntime/phobos, because they are compiled with -release. DMD will also not include it in an application compiled without -release, because it assumes, that it is already in druntime. See comment https://issues.dlang.org/show_bug.cgi?id=20802#c3 by Spoov. The template instance for __switch_errorT is now always instantiated in druntime, so it is part of the ABI of druntime. https://github.com/dlang/dmd/pull/16276