[LLVMdev] weak_odr constant versus weak_odr global

Richard Smith
Wed, 02 Nov 2011 00:19:03 -0000

Hi

[Adding cfe-dev to widen the net]

On Tue, November 1, 2011 23:19, Richard Smith wrote:
> 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)?

I think this is best fixed in llvm, since that gives maximum optimization
opportunities: it's fine to propagate weak_odr constant values, even if some
other module has the same object as a non-constant. Plus, with LTO, we'd
want
to merge the weak_odr constant and weak_odr global symbols into a weak_odr
constant (and simultaneously remove any writes into the global).

Thanks,
Richard