The original issue is spread across hundreds of thousands LoC from different projects. It contains a lot of ingredients: in-line assembly, virtual inheritance, levels of indirection, different compilers and compiler options. (It's like a thriller.) I had a hard time to simplify to this SSCCE:
// a.hpp
struct A {
int i;
~A() { asm("" : "=r"(i)); }
};
struct B : public virtual A { };
struct C : public B { };
struct D {
D(C);
};
// a.cpp
#include "a.hpp"
void f(C) {
}
D::D(C c) {
f(c);
}
// main.cpp
#include "a.hpp"
int main() {
C c;
D d(c);
}
Build with these command lines:
g++ -O3 -fPIC -c a.cpp
clang++ -O3 -fPIC -c main.cpp
clang++ -fuse-ld=gold main.o a.o -o main
And the linker output is:
a.o:a.cpp:function D::D(C) [clone .cold]: error: relocation refers to global symbol "construction vtable for B-in-C", which is defined in a discarded section
section group signature: "_ZTV1C"
prevailing definition is from main.o
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
I believe there's a bug in either gcc, clang or gold. My question is where is it? (I guess it's gold but I want to be sure before reporting the bug.)
FWIW: As I said, all the ingredients are important and the issue goes away if, for instance, the asm
is removed. More notable changes that make the issue go away are:
- Use the same compiler for all TUs, (It doesn't matter whether g++ or clang++.)
- Link with ld (i.e., remove
-fuse-ld=gold
) - Compile
main.cpp
without-O3
. - Compile
main.cpp
without-fPIC
. - Swap
a.o
andmain.o
in the linker command line.