diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index eaf77e962544..ddde907522b9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7843,14 +7843,6 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, : StaticLocalLinkage; } - // On Darwin, the backing variable for a C++11 thread_local variable always - // has internal linkage; all accesses should just be calls to the - // Itanium-specified entry point, which has the normal linkage of the - // variable. - if (VD->getTLSKind() == VarDecl::TLS_Dynamic && - Context.getTargetInfo().getTriple().isMacOSX()) - return GVA_Internal; - switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b2d87db48800..79338787966f 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1903,6 +1903,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // Set the llvm linkage type as appropriate. llvm::GlobalValue::LinkageTypes Linkage = getLLVMLinkageVarDefinition(D, GV->isConstant()); + + // On Darwin, the backing variable for a C++11 thread_local variable always + // has internal linkage; all accesses should just be calls to the + // Itanium-specified entry point, which has the normal linkage of the + // variable. + if (const auto *VD = dyn_cast(D)) + if (!VD->isStaticLocal() && VD->getTLSKind() == VarDecl::TLS_Dynamic && + Context.getTargetInfo().getTriple().isMacOSX()) + Linkage = llvm::GlobalValue::InternalLinkage; + GV->setLinkage(Linkage); if (D->hasAttr()) GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 86eb36d86536..be8dac140ede 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1575,11 +1575,21 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, /// Get the appropriate linkage for the wrapper function. This is essentially /// the weak form of the variable's linkage; every translation unit which wneeds /// the wrapper emits a copy, and we want the linker to merge them. -static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage( - llvm::GlobalValue::LinkageTypes VarLinkage) { +static llvm::GlobalValue::LinkageTypes +getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) { + llvm::GlobalValue::LinkageTypes VarLinkage = + CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false); + // For internal linkage variables, we don't need an external or weak wrapper. 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; return llvm::GlobalValue::WeakODRLinkage; } @@ -1602,10 +1612,9 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, RetTy = RetTy->getPointerElementType(); llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false); - llvm::Function *Wrapper = llvm::Function::Create( - FnTy, getThreadLocalWrapperLinkage( - CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)), - WrapperName.str(), &CGM.getModule()); + llvm::Function *Wrapper = + llvm::Function::Create(FnTy, getThreadLocalWrapperLinkage(VD, CGM), + WrapperName.str(), &CGM.getModule()); // Always resolve references to the wrapper at link time. if (!Wrapper->hasLocalLinkage()) Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); diff --git a/clang/test/CodeGenCXX/tls-init-funcs.cpp b/clang/test/CodeGenCXX/tls-init-funcs.cpp index 17299dcb7b6c..99fe75f7f4f8 100644 --- a/clang/test/CodeGenCXX/tls-init-funcs.cpp +++ b/clang/test/CodeGenCXX/tls-init-funcs.cpp @@ -2,6 +2,7 @@ // CHECK: @a = internal thread_local global // CHECK: @_tlv_atexit({{.*}}@_ZN1AD1Ev +// CHECK: define weak hidden {{.*}} @_ZTW1a struct A { ~A();