[cfe-commits] r84140 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp

Daniel Dunbar daniel at zuster.org
Sun Oct 25 15:18:22 PDT 2009


Hi Doug,

On Wed, Oct 14, 2009 at 2:29 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Author: dgregor
> Date: Wed Oct 14 16:29:40 2009
> New Revision: 84140
>
> URL: http://llvm.org/viewvc/llvm-project?rev=84140&view=rev
> Log:
> Give explicit and implicit instantiations of static data members of
> class templates the proper linkage.
>
> Daniel, please look over the CodeGenModule bits.

Comments below.

> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Oct 14 16:29:40 2009
> @@ -541,7 +541,12 @@
>     }
>   }
>
> -  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?

For C++ we shouldn't be deferring anything that could have side
effects. Can you fix or file this FIXME?

> +  return VD->isInAnonymousNamespace() ||
> +         (VD->getStorageClass() == VarDecl::Static &&
> +          !(VD->isStaticDataMember() && VD->isOutOfLine()));
>  }

> +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.

I think we are moving towards using llvm_unreachable for these.

> +    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 @@
>   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);

This if can die? Never mind I see John got that.

> -  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 @@
>       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);
>

Otherwise seems fine.

 - Daniel




More information about the cfe-commits mailing list