Consider: extern "C" int __declspec(dllimport) x; extern "C" int *y = &x; Clang creates this LLVM IR: @x = external dllimport global i32 @y = global i32* @x, align 4 This is lowered to: .data .globl _y .align 4 _y: .long _x Which is incorrect, because x is dllimported, and its address isn't a link time constant. It must be loaded from __imp_x. Clang should emit something like the following IR instead: @y = global i32* null, align 4 @x = external dllimport global i32 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @init, i8* null }] define internal void @init() { entry: store i32* @x, i32** @y, align 4 ret void } This is consistent with what MSVC does, and it would be important to match them if x was selectany or a static data member of a class template. However, this is really a bug in LLVM, because LLVM will optimize that IR back to Clang's original output: $ opt t.ll -O2 -S -o - @y = global i32* @x, align 4 @x = external dllimport global i32 @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer If y were a function, this would actually link correctly, because import libraries provide thunks for functions. The only downside is that the address of a thunk isn't really the address of the function, but few programs rely on function identity. There's no way to create a forwarding thunk for data, so we get a link failure with this test case.
*** Bug 20076 has been marked as a duplicate of this bug. ***
Fixes are available. LLVM-related: http://reviews.llvm.org/D4249 Clang-related: http://reviews.llvm.org/D4250
Fixed in r211571, r211570, r211568.
Thanks, I verified this on our side!