[Issue 20802] [REG2.088.0] Link failure with writefln

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sun Feb 11 11:04:38 UTC 2024


https://issues.dlang.org/show_bug.cgi?id=20802

Spoov <spoov0.707 at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |spoov0.707 at gmail.com

--- Comment #3 from Spoov <spoov0.707 at gmail.com> ---
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

--


More information about the Digitalmars-d-bugs mailing list