From: Hans Wennborg Date: Wed, 18 Jun 2014 15:55:13 +0000 (+0000) Subject: Inherit dll attributes to static locals X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=34b52c0933c500bc569b11544be1d294bf9dda3e;p=clang Inherit dll attributes to static locals This makes us handle static locals in exported/imported functions correctly. Differential Revision: http://reviews.llvm.org/D4136 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211173 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index 114211b840..9199b0fba2 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -74,6 +74,18 @@ inline void MarkVarDeclODRUsed(VarDecl *Var, Var->markUsed(SemaRef.Context); } + +/// Return a DLL attribute from the declaration. +inline InheritableAttr *getDLLAttr(Decl *D) { + assert(!(D->hasAttr() && D->hasAttr()) && + "A declaration cannot be both dllimport and dllexport."); + if (auto *Import = D->getAttr()) + return Import; + if (auto *Export = D->getAttr()) + return Export; + return nullptr; +} + } #endif diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 12c520792f..a28e721377 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -201,6 +201,13 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D, if (D.getTLSKind()) CGM.setTLSMode(GV, D); + if (D.isExternallyVisible()) { + if (D.hasAttr()) + GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass); + else if (D.hasAttr()) + GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass); + } + // Make sure the result is of the correct type. unsigned ExpectedAddrSpace = CGM.getContext().getTargetAddressSpace(Ty); if (AddrSpace != ExpectedAddrSpace) { diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index ffcf76eb42..ca2aaa2edf 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1425,12 +1425,13 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, Out.flush(); } - // Create the guard variable with a zero-initializer. Just absorb linkage - // and visibility from the guarded variable. + // Create the guard variable with a zero-initializer. Just absorb linkage, + // visibility and dll storage class from the guarded variable. GI->Guard = new llvm::GlobalVariable(CGM.getModule(), GuardTy, false, GV->getLinkage(), Zero, GuardName.str()); GI->Guard->setVisibility(GV->getVisibility()); + GI->Guard->setDLLStorageClass(GV->getDLLStorageClass()); } else { assert(GI->Guard->getLinkage() == GV->getLinkage() && "static local from the same function had different linkage"); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 733fdddd16..304fd46cf9 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9097,6 +9097,18 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { checkAttributesAfterMerging(*this, *VD); + // Static locals inherit dll attributes from their function. + if (VD->isStaticLocal()) { + if (FunctionDecl *FD = + dyn_cast(VD->getParentFunctionOrMethod())) { + if (Attr *A = getDLLAttr(FD)) { + auto *NewAttr = cast(A->clone(getASTContext())); + NewAttr->setInherited(true); + VD->addAttr(NewAttr); + } + } + } + // Imported static data members cannot be defined out-of-line. if (const DLLImportAttr *IA = VD->getAttr()) { if (VD->isStaticDataMember() && VD->isOutOfLine() && diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 3f5321664c..b9eda84e5a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4347,17 +4347,6 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } -/// \brief Return a DLL attribute from the declaration. -static InheritableAttr *getDLLAttr(Decl *D) { - assert(!(D->hasAttr() && D->hasAttr()) && - "A declaration cannot be both dllimport and dllexport."); - if (auto *Import = D->getAttr()) - return Import; - if (auto *Export = D->getAttr()) - return Export; - return nullptr; -} - /// \brief Check class-level dllimport/dllexport attribute. static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index d393bc53d1..b2f2e563ab 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -72,6 +72,22 @@ namespace ns { __declspec(dllexport) int ExternalGlobal; } // GNU-DAG: @ExternalAutoTypeGlobal = dllexport global %struct.External zeroinitializer, align 4 __declspec(dllexport) auto ExternalAutoTypeGlobal = External(); +int f(); +// MSC-DAG: @"\01?x@?0??nonInlineStaticLocalsFunc@@YAHXZ@4HA" = internal {{(unnamed_addr )*}}global i32 0 +// MSC-DAG: @"\01?$S1@?0??nonInlineStaticLocalsFunc@@YAHXZ@4IA" = internal {{(unnamed_addr )*}}global i32 0 +int __declspec(dllexport) nonInlineStaticLocalsFunc() { + static int x = f(); + return x++; +}; + +// MSC-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = weak_odr dllexport global i32 0 +// MSC-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = weak_odr dllexport global i32 0 +// Note: MinGW doesn't seem to export the static local here. +inline int __declspec(dllexport) inlineStaticLocalsFunc() { + static int x = f(); + return x++; +} + //===----------------------------------------------------------------------===// diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 78a15b518e..6d29399885 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -85,6 +85,15 @@ USEVAR(GlobalRedecl3) namespace ns { __declspec(dllimport) int ExternalGlobal; } USEVAR(ns::ExternalGlobal) +int f(); +// MO1-DAG: @"\01?x@?1??inlineStaticLocalsFunc@@YAHXZ@4HA" = available_externally dllimport global i32 0 +// MO1-DAG: @"\01??_B?1??inlineStaticLocalsFunc@@YAHXZ@51" = available_externally dllimport global i32 0 +inline int __declspec(dllimport) inlineStaticLocalsFunc() { + static int x = f(); + return x++; +}; +USE(inlineStaticLocalsFunc); + //===----------------------------------------------------------------------===//