Imagine you have a file a.h
#include <iostream>
template<typename T> struct A{
int magic;
A():magic(1234){}
void f(){std::cout<<"default f"<<magic<<std::endl;}
};
void f(A<int>* a);
then the function f is defined in “a.cpp”
#include "a.h"
void f(A<int>* a){
a->f();
}
and finally, “main.cpp” specializes the template, and then uses f
#include "a.h"
template<> struct A<int>{
};
int main(){
A<int> a;
f(&a);
}
Clearly the compiler uses the non specialized version for a.o, and the specialized version for main.o, i.e. there happen to be two different implementations of A.
On execution, f can only print garbage / segfault, because the object passed has a different structure from the one expected.
Is there a way to make the linker warn that there’re two versions of A ?
The reason Gold doesn’t warn about this is that Gold only detects symbol mismatches (the same symbol being defined in multiple object files in incompatible ways), and there is no such mismatch in the example.
Running the example under Valgrind does produce this error though:
You should get even better report from Address Sanitizer:
Update:
I understand your point, but it is not currently possible for either the compiler (doesn’t have info about other translation units) or the linker (doesn’t have info about types involved) to warn you about this.
Now, for a debug build, the linker could in theory do this, if for every function it also compared the debug info for parameter types. I suggest filing a feature request for gold in bugzilla.