Skip to content

Commit

Permalink
CodeGen: Clean up CommonLinkage calculation
Browse files Browse the repository at this point in the history
No functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205972 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
majnemer committed Apr 10, 2014
1 parent 4656ce0 commit eaa6166
Showing 1 changed file with 35 additions and 10 deletions.
45 changes: 35 additions & 10 deletions lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,34 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
DI->EmitGlobalVariable(GV, D);
}

static bool isVarDeclStrongDefinition(const VarDecl *D, bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
// was overridden by a NoCommon attribute.
if ((NoCommon || D->hasAttr<NoCommonAttr>()) && !D->hasAttr<CommonAttr>())
return true;

// C11 6.9.2/2:
// A declaration of an identifier for an object that has file scope without
// an initializer, and without a storage-class specifier or with the
// storage-class specifier static, constitutes a tentative definition.
if (D->getInit() || D->hasExternalStorage())
return true;

// A variable cannot be both common and exist in a section.
if (D->hasAttr<SectionAttr>())
return true;

// Thread local vars aren't considered common linkage.
if (D->getTLSKind())
return true;

// Tentative definitions marked with WeakImportAttr are true definitions.
if (D->hasAttr<WeakImportAttr>())
return true;

return false;
}

llvm::GlobalValue::LinkageTypes
CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
Expand All @@ -1950,21 +1978,18 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) {
return llvm::GlobalVariable::WeakAnyLinkage;
} else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_StrongODR)
return llvm::GlobalVariable::WeakODRLinkage;
else if (!getLangOpts().CPlusPlus &&
((!CodeGenOpts.NoCommon && !D->hasAttr<NoCommonAttr>()) ||
D->hasAttr<CommonAttr>()) &&
!D->hasExternalStorage() && !D->getInit() &&
!D->hasAttr<SectionAttr>() && !D->getTLSKind() &&
!D->hasAttr<WeakImportAttr>()) {
// Thread local vars aren't considered common linkage.
return llvm::GlobalVariable::CommonLinkage;
} else if (D->getTLSKind() == VarDecl::TLS_Dynamic &&
getTarget().getTriple().isMacOSX())
else if (D->getTLSKind() == VarDecl::TLS_Dynamic &&
getTarget().getTriple().isMacOSX())
// 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.
return llvm::GlobalValue::InternalLinkage;
// C++ doesn't have tentative definitions and thus cannot have common linkage.
else if (!getLangOpts().CPlusPlus &&
!isVarDeclStrongDefinition(D, CodeGenOpts.NoCommon))
return llvm::GlobalVariable::CommonLinkage;

return llvm::GlobalVariable::ExternalLinkage;
}

Expand Down

0 comments on commit eaa6166

Please sign in to comment.