summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--lib/CodeGen/CodeGenModule.cpp47
1 files changed, 42 insertions, 5 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 36ad7f514ec8..4763b7fc1ee2 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/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,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setAlignment(getContext().getDeclAlignInBytes(D));
// Set the llvm linkage type as appropriate.
- if (D->isInAnonymousNamespace())
- GV->setLinkage(llvm::Function::InternalLinkage);
- else if (D->getStorageClass() == VarDecl::Static)
+ GVALinkage Linkage = GetLinkageForVariable(getContext(), D);
+ if (Linkage == GVA_Internal)
GV->setLinkage(llvm::Function::InternalLinkage);
else if (D->hasAttr<DLLImportAttr>())
GV->setLinkage(llvm::Function::DLLImportLinkage);
@@ -1034,7 +1069,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);