0

Suppose I have a contrived header file containing a single template class and two source files containing the exact same instantiation of the template class, along with one duplicate function. That is...

Contrived header (thing.hpp):

#pragma once

template <typename T>
class Thing {
  public:
    T t;
  public:
    T& value() {
        return t;
    }
};

thing.cpp:

#include <thing.hpp>

template class Thing<int>;

int MeaningOfLife() {
    return 42;
}

thingy.cpp: (exactly the same as thing.cpp)

Upon compilation and linkage (using clang on OS X), it seems that only MeaningOfLife was seen as a duplicate symbol, yet the symbols for the template instantiation (which is just Thing::value()) were not. Upon closer inspection of the disassembly, it seems that an assembly directive was placed on the symbol for Thing::value() called .weak_definition.

Question 0: It's implied that this directive is doing something to prevent the symbol(s) from being multiply defined, but what is it really doing?

Question 1: How might this be done elsewhere (e.g. on Linux, Windows, etc.) by other compilers?

Question 2: What if I perversely altered the assembly code of one of the duplicated template instantiations? That is, same symbols, different function body. Would a smart compiler detect discrepancies?

Mona the Monad
  • 2,265
  • 3
  • 19
  • 30
  • I believe all your questions are answered in [this](https://stackoverflow.com/questions/44335046/how-does-the-linker-handle-identical-template-instantiations-across-translation) thread. – Cheshar Jan 16 '19 at 12:44

1 Answers1

1

A cursory Google search leads us to these OSX docs, which states:

The .weak_definition directive causes symbol_name to be a weak definition. symbol_name can be defined only in a coalesced section. This is used by the C++ compiler to support template instantiation. [...]

It goes on to define coalesced thus:

A coalesced section can contain any instructions or data and is used when more than one definition of a symbol could be defined in multiple object files being linked together. The static link editor keeps the data associated with the coalesced symbol from the first object file it links and silently discards the data from other object files. An example of a coalesced section is one in which the compiler has generated code for implicit instantiations of C++ templates.

I don't know what would happen if you modified one of these definitions (I haven't tried it), but the docs imply that the linker just blindly takes whichever one it finds first.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • I had seen this earlier, but this seems like it's specific to OS X. I was wondering what other systems might do. – Mona the Monad Nov 25 '17 at 19:39
  • @MonatheMonad Other systems will do something similar. The language spec allows multiple definitions of template types. They should all match, but if they don't the compiler (linker) will take the first it finds and is not required to issue a diagnostic. – 1201ProgramAlarm Nov 25 '17 at 19:49