Thread overview
template instantiation question
Mar 18, 2015
Dmitri Makarov
Mar 18, 2015
Ali Çehreli
Mar 18, 2015
Dmitri Makarov
Mar 18, 2015
Ali Çehreli
March 18, 2015
I have three modules a.d, b.d, and c.d:

file a.d:```
module i.a;

import i.c, i.b;

final class A {
public:
  void foo() {
    a.transmogrify();
  }
  S!void a;
}
```
--------------
file b.d:```
module i.b;

import i.a, i.c;

class B {
public:
  S!void b;
}
```
--------------
file c.d:```
module i.c;

struct C {}

struct S(T) {
  C transmogrify() {
    return C();
  }
}
```
--------------
When these modules compiled separately, I assume, both a.o and b.o contain a definition of i.c.S!void.S.transmogrify() instance. Is this correct? If so, how is the symbol redefinition resolved when the three object files are linked into a single executable?
March 18, 2015
On 03/18/2015 11:03 AM, Dmitri Makarov wrote:

> When these modules compiled separately, I assume, both a.o and b.o
> contain a definition of i.c.S!void.S.transmogrify() instance.

That is very likely but I played with different three files for a while and failed to see that.

> how is the symbol redefinition resolved when the three object
> files are linked into a single executable?

There are different kinds of symbols. For example, the following command on a Linux console will show that template instances are weak symbols (it is not an error to have one or more weak symbols).

$ nm b.o | grep transmogrify
0000000000000000 W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi

'man nm' tells us that W indicates a weak symbol:

  "W"
  "w" The symbol is a weak symbol that has not been specifically
      tagged as a weak object symbol.  When a weak defined symbol is
      linked with a normal defined symbol, the normal defined symbol
      is used with no error.  When a weak undefined symbol is linked
      and the symbol is not defined, the value of the symbol is
      determined in a system-specific manner without error.  On some
      systems, uppercase indicates that a default value has been
      specified.

Ali

March 18, 2015
On Wednesday, 18 March 2015 at 18:26:07 UTC, Ali Çehreli wrote:
> $ nm b.o | grep transmogrify
> 0000000000000000 W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi

What compiler do you use? For me, neither a.o nor b.o contain transmogrify definition:

$ dmd -c -Ix x/i/a.d
$ nm a.o | grep trans
                 U _D1i1c8__T1STvZ1S12transmogrifyMFNaNbNiNfZS1i1c1C
$ dmd -c -Ix x/i/b.d
$ nm b.o | grep trans
$
March 18, 2015
(My earlier response seems to be lost; trying one more time.)

On 03/18/2015 12:09 PM, Dmitri Makarov wrote:

> On Wednesday, 18 March 2015 at 18:26:07 UTC, Ali Çehreli wrote:
>> $ nm b.o | grep transmogrify
>> 0000000000000000 W _D1c8__T1CTvZ1C12transmogrifyMFNaNbNiNfZi
>
> What compiler do you use?

dmd git head. I used simpler files:

// a.d
module a;

import c;
import b;

auto foo()
{
    auto c = C!void();
    return c.transmogrify();
}

void main()
{
    assert(.foo() == b.foo());
}

// b.d
module b;

import c;

auto foo()
{
    auto c = C!void();
    return c.transmogrify();
}

// c.d
module c;

struct C(T) {
  int transmogrify() {
    return 42;
  }
}

Then I built the program like this:

$ dmd a.d -c
$ dmd b.d -c
$ dmd c.d -c
$ dmd a.o b.o c.o

Ali