diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 6d0806424dd5fefc069e1dedc5cdd25164118df9..6567ffb07d88c8b199448413d0a466c80b9f2a95 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -257,11 +257,16 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, D->getInstantiatedFromStaticDataMember() && D->getInit()){ llvm::GlobalVariable *GV = dyn_cast(DeclPtr); assert(GV && "GenerateCXXGlobalVarDeclInitFunc - GV is null"); - GV->setConstant(false); - EmitCXXStaticLocalInit(*D, GV); + llvm::GlobalValue::LinkageTypes Linkage = + CGM.GetLLVMLinkageVarDefinition(D, GV); + if (Linkage == llvm::GlobalVariable::WeakAnyLinkage) { + GV->setConstant(false); + EmitCXXStaticLocalInit(*D, GV); + FinishFunction(); + return; + } } - else - EmitCXXGlobalVarDeclInit(*D, DeclPtr); + EmitCXXGlobalVarDeclInit(*D, DeclPtr); FinishFunction(); } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d35965e2c4e68323b6f628bd11d773dc6a633593..efcdce70a05f0164c1f936dca59f1c7a3e00422d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1154,42 +1154,51 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setConstant(true); GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); - + // Set the llvm linkage type as appropriate. + llvm::GlobalValue::LinkageTypes Linkage = + GetLLVMLinkageVarDefinition(D, GV); + GV->setLinkage(Linkage); + if (Linkage == llvm::GlobalVariable::CommonLinkage) + // common vars aren't constant even if declared const. + GV->setConstant(false); + + SetCommonAttributes(D, GV); + + // Emit global variable debug information. + if (CGDebugInfo *DI = getDebugInfo()) { + DI->setLocation(D->getLocation()); + DI->EmitGlobalVariable(GV, D); + } +} + +llvm::GlobalValue::LinkageTypes +CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, + llvm::GlobalVariable *GV) { GVALinkage Linkage = getContext().GetGVALinkageForVariable(D); if (Linkage == GVA_Internal) - GV->setLinkage(llvm::Function::InternalLinkage); + return llvm::Function::InternalLinkage; else if (D->hasAttr()) - GV->setLinkage(llvm::Function::DLLImportLinkage); + return llvm::Function::DLLImportLinkage; else if (D->hasAttr()) - GV->setLinkage(llvm::Function::DLLExportLinkage); + return llvm::Function::DLLExportLinkage; else if (D->hasAttr()) { if (GV->isConstant()) - GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage); + return llvm::GlobalVariable::WeakODRLinkage; else - GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); + return llvm::GlobalVariable::WeakAnyLinkage; } else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_ExplicitTemplateInstantiation) // FIXME: It seems like we can provide more specific linkage here // (LinkOnceODR, WeakODR). - GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); + return llvm::GlobalVariable::WeakAnyLinkage; else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon && !D->hasExternalStorage() && !D->getInit() && !D->getAttr() && !D->isThreadSpecified()) { // Thread local vars aren't considered common linkage. - GV->setLinkage(llvm::GlobalVariable::CommonLinkage); - // common vars aren't constant even if declared const. - GV->setConstant(false); - } else - GV->setLinkage(llvm::GlobalVariable::ExternalLinkage); - - SetCommonAttributes(D, GV); - - // Emit global variable debug information. - if (CGDebugInfo *DI = getDebugInfo()) { - DI->setLocation(D->getLocation()); - DI->EmitGlobalVariable(GV, D); + return llvm::GlobalVariable::CommonLinkage; } + return llvm::GlobalVariable::ExternalLinkage; } /// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 68898cf5d000ca6f664b1efe678870595622a5a2..683f175737dfdee45d5c05c7f1d463296100d4fb 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -511,7 +511,13 @@ public: /// GetTargetTypeStoreSize - Return the store size, in character units, of /// the given LLVM type. CharUnits GetTargetTypeStoreSize(const llvm::Type *Ty) const; - + + /// GetLLVMLinkageVarDefinition - Returns LLVM linkage for a global + /// variable. + llvm::GlobalValue::LinkageTypes + GetLLVMLinkageVarDefinition(const VarDecl *D, + llvm::GlobalVariable *GV); + std::vector DeferredVTables; private: @@ -552,7 +558,7 @@ private: void EmitAliasDefinition(GlobalDecl GD); void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D); void EmitObjCIvarInitializations(ObjCImplementationDecl *D); - + // C++ related functions. bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);