Index: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp @@ -1818,6 +1818,15 @@ CGF.registerGlobalDtorWithAtExit(D, dtor, addr); } +static bool isThreadWrapperReplaceable(const VarDecl *VD, + CodeGen::CodeGenModule &CGM) { + assert(!VD->isStaticLocal() && "static local VarDecls don't need wrappers!"); + // OS X prefers to have references to thread local variables to go through + // the thread wrapper instead of directly referencing the backing variable. + return VD->getTLSKind() == VarDecl::TLS_Dynamic && + CGM.getTarget().getTriple().isMacOSX(); +} + /// Get the appropriate linkage for the wrapper function. This is essentially /// the weak form of the variable's linkage; every translation unit which needs /// the wrapper emits a copy, and we want the linker to merge them. @@ -1830,12 +1839,13 @@ if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) return VarLinkage; - // All accesses to the thread_local variable go through the thread wrapper. - // However, this means that we cannot allow the thread wrapper to get inlined - // into any functions. - if (VD->getTLSKind() == VarDecl::TLS_Dynamic && - CGM.getTarget().getTriple().isMacOSX()) - return llvm::GlobalValue::WeakAnyLinkage; + // If the thread wrapper is replaceable, give it appropriate linkage. + if (isThreadWrapperReplaceable(VD, CGM)) { + if (llvm::GlobalVariable::isLinkOnceLinkage(VarLinkage) || + llvm::GlobalVariable::isWeakODRLinkage(VarLinkage)) + return llvm::GlobalVariable::WeakAnyLinkage; + return VarLinkage; + } return llvm::GlobalValue::WeakODRLinkage; } @@ -1862,7 +1872,7 @@ llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM), WrapperName.str(), &CGM.getModule()); // Always resolve references to the wrapper at link time. - if (!Wrapper->hasLocalLinkage()) + if (!Wrapper->hasLocalLinkage() && !isThreadWrapperReplaceable(VD, CGM)) Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); return Wrapper; } @@ -1874,6 +1884,12 @@ const VarDecl *VD = Decls[I].first; llvm::GlobalVariable *Var = Decls[I].second; + // Some targets require that all access to thread local variables go through + // the thread wrapper. This means that we cannot attempt to create a thread + // wrapper or a thread helper. + if (isThreadWrapperReplaceable(VD, CGM) && !VD->hasDefinition()) + continue; + // Mangle the name for the thread_local initialization function. SmallString<256> InitFnName; { Index: cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp +++ cfe/trunk/test/CodeGenCXX/tls-init-funcs.cpp @@ -1,11 +1,34 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++11 -S -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8 -std=c++1y -S -emit-llvm %s -o - | FileCheck %s // CHECK: @a = internal thread_local global +// CHECK: @_Z2vtIiE = internal thread_local global i32 5 +// CHECK: @_ZZ3inlvE3loc = linkonce_odr thread_local global i32 0 // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev -// CHECK: define weak hidden {{.*}} @_ZTW1a +// CHECK: call i32* @_ZTW3ext() +// CHECK: declare i32* @_ZTW3ext() +// CHECK: define weak i32* @_ZTW2vtIiE() +// CHECK: define weak i32* @_ZTW2vtIvE() +// CHECK: define {{.*}} @_ZTW1a struct A { ~A(); }; thread_local A a; + +extern thread_local int ext; +int &get_ext() { return ext; } + +template +thread_local int vt = 5; + +int get_vt() { return vt; } + +inline int &inl() { + thread_local int loc; + return loc; +} +int &use_inl() { return inl(); } + +template int vt; +int &get_vt_void() { return vt; }