From 9832a3d1e0d7e013fe1adceea2a0d99b6ec6186b Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 10 Apr 2014 16:53:16 +0000 Subject: CodeGen: Clean up CommonLinkage calculation No functionality change. llvm-svn: 205972 --- clang/lib/CodeGen/CodeGenModule.cpp | 45 ++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c26f76911821..2d877389adf0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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()) && !D->hasAttr()) + 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()) + 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()) + return true; + + return false; +} + llvm::GlobalValue::LinkageTypes CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D, bool isConstant) { GVALinkage Linkage = getContext().GetGVALinkageForVariable(D); @@ -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()) || - D->hasAttr()) && - !D->hasExternalStorage() && !D->getInit() && - !D->hasAttr() && !D->getTLSKind() && - !D->hasAttr()) { - // 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; } -- cgit v1.2.3