[LLVMdev] weak_odr constant versus weak_odr global

Richard Smith
Tue, 01 Nov 2011 23:19:09 -0000

Hi,

We recently narrowed down a clang regression to the following testcase:

struct S {
  static const int x;
};
template<typename T> struct U {
  static const int k;
};
template<typename T> const int U<T>::k = T::x;

#ifdef TU1
extern int f();
const int S::x = 42;
int main() {
return f() + U::k;
}
#endif

#ifdef TU2
int f() { return U::k; }
#endif

/* Steps to repro:

clang repro.cpp -DTU1 -c -o tu1.o
clang repro.cpp -DTU2 -c -o tu2.o
clang tu1.o tu2.o
./a.out

*/

This segfaults, because... in TU1, we get:

  @_ZN1UI1SE1kE = weak_odr constant i32 42, align 4

and in TU2, we get:

  @_ZN1UI1SE1kE = weak_odr global i32 0, align 4

plus a global constructor which writes to @_ZN1UI1SE1kE. The linker then
selects the symbol from TU1, which ends up in a read-only section, resulting
in the binary crashing when TU2 tries to write to it.

Is this a clang bug (should we be generating a weak_odr global, and losing
optimization opportunities in TU1), or is this an llvm bug (should weak_odr
constants be banned from read-only sections, since another module might write
to them)?

Thanks,
Richard