diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-10-14 21:29:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-10-14 21:29:40 +0000 |
commit | 3cc3cdeea96c6a3c024e3c47daad2853e8017d6e (patch) | |
tree | 2a683cf77fdf7c23a9ba5c73a1de62bea42930d6 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | b1d6fde13e529e7a5217e2b7c48c0437cea9dee5 (diff) | |
download | bcm5719-llvm-3cc3cdeea96c6a3c024e3c47daad2853e8017d6e.tar.gz bcm5719-llvm-3cc3cdeea96c6a3c024e3c47daad2853e8017d6e.zip |
Give explicit and implicit instantiations of static data members of
class templates the proper linkage.
Daniel, please look over the CodeGenModule bits.
llvm-svn: 84140
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 36ad7f514ec..ecf8eb0d27d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -541,7 +541,12 @@ bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { } } - return VD->getStorageClass() == VarDecl::Static; + // Static data may be deferred, but out-of-line static data members + // cannot be. + // FIXME: What if the initializer has side effects? + return VD->isInAnonymousNamespace() || + (VD->getStorageClass() == VarDecl::Static && + !(VD->isStaticDataMember() && VD->isOutOfLine())); } void CodeGenModule::EmitGlobal(GlobalDecl GD) { @@ -928,6 +933,37 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) { EmitGlobalVarDefinition(D); } +static CodeGenModule::GVALinkage +GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) { + // Everything located semantically within an anonymous namespace is + // always internal. + if (VD->isInAnonymousNamespace()) + return CodeGenModule::GVA_Internal; + + // Handle linkage for static data members. + if (VD->isStaticDataMember()) { + switch (VD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDefinition: + return CodeGenModule::GVA_StrongExternal; + + case TSK_ExplicitInstantiationDeclaration: + assert(false && "Variable should not be instantiated"); + // Fall through to treat this like any other instantiation. + + case TSK_ImplicitInstantiation: + return CodeGenModule::GVA_TemplateInstantiation; + } + } + + // Static variables get internal linkage. + if (VD->getStorageClass() == VarDecl::Static) + return CodeGenModule::GVA_Internal; + + return CodeGenModule::GVA_StrongExternal; +} + void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = 0; QualType ASTTy = D->getType(); @@ -1021,9 +1057,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setAlignment(getContext().getDeclAlignInBytes(D)); // Set the llvm linkage type as appropriate. + GVALinkage Linkage = GetLinkageForVariable(getContext(), D); if (D->isInAnonymousNamespace()) GV->setLinkage(llvm::Function::InternalLinkage); - else if (D->getStorageClass() == VarDecl::Static) + else if (Linkage == GVA_Internal) GV->setLinkage(llvm::Function::InternalLinkage); else if (D->hasAttr<DLLImportAttr>()) GV->setLinkage(llvm::Function::DLLImportLinkage); @@ -1034,7 +1071,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setLinkage(llvm::GlobalVariable::WeakODRLinkage); else GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - } else if (!CompileOpts.NoCommon && + } else if (Linkage == GVA_TemplateInstantiation) + GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); + else if (!CompileOpts.NoCommon && !D->hasExternalStorage() && !D->getInit() && !D->getAttr<SectionAttr>()) { GV->setLinkage(llvm::GlobalVariable::CommonLinkage); |