forked from OSchip/llvm-project
[clang-cl] Inherit dllexport to static locals also in template instantiations (PR39496)
In the course of D51340, @takuto.ikuta discovered that Clang fails to put dllexport/import attributes on static locals during template instantiation. For regular functions, this happens in Sema::FinalizeDeclaration(), however for template instantiations we need to do something in or around TemplateDeclInstantiator::VisitVarDecl(). This patch does that, and extracts the code to a utility function. Differential Revision: https://reviews.llvm.org/D53870 llvm-svn: 345699
This commit is contained in:
parent
315357faca
commit
59f18f1b72
|
@ -2001,6 +2001,7 @@ public:
|
|||
SourceLocation AttrEnd);
|
||||
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
|
||||
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
|
||||
void CheckStaticLocalForDllExport(VarDecl *VD);
|
||||
void FinalizeDeclaration(Decl *D);
|
||||
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
|
||||
ArrayRef<Decl *> Group);
|
||||
|
|
|
@ -11924,6 +11924,23 @@ static bool hasDependentAlignment(VarDecl *VD) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Check if VD needs to be dllexport/dllimport due to being in a
|
||||
/// dllexport/import function.
|
||||
void Sema::CheckStaticLocalForDllExport(VarDecl *VD) {
|
||||
assert(VD->isStaticLocal());
|
||||
|
||||
auto *FD = dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod());
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
// Static locals inherit dll attributes from their function.
|
||||
if (Attr *A = getDLLAttr(FD)) {
|
||||
auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
|
||||
NewAttr->setInherited(true);
|
||||
VD->addAttr(NewAttr);
|
||||
}
|
||||
}
|
||||
|
||||
/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform
|
||||
/// any semantic actions necessary after any initializer has been attached.
|
||||
void Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
||||
|
@ -11977,14 +11994,9 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
|
|||
}
|
||||
|
||||
if (VD->isStaticLocal()) {
|
||||
if (FunctionDecl *FD =
|
||||
dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
|
||||
// Static locals inherit dll attributes from their function.
|
||||
if (Attr *A = getDLLAttr(FD)) {
|
||||
auto *NewAttr = cast<InheritableAttr>(A->clone(getASTContext()));
|
||||
NewAttr->setInherited(true);
|
||||
VD->addAttr(NewAttr);
|
||||
}
|
||||
CheckStaticLocalForDllExport(VD);
|
||||
|
||||
if (dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) {
|
||||
// CUDA 8.0 E.3.9.4: Within the body of a __device__ or __global__
|
||||
// function, only __shared__ variables or variables without any device
|
||||
// memory qualifiers may be declared with static storage class.
|
||||
|
|
|
@ -728,6 +728,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
|
|||
D->getLocation(), D->getIdentifier(), DI->getType(),
|
||||
DI, D->getStorageClass());
|
||||
|
||||
if (Var->isStaticLocal())
|
||||
SemaRef.CheckStaticLocalForDllExport(Var);
|
||||
|
||||
// In ARC, infer 'retaining' for variables of retainable type.
|
||||
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
|
||||
SemaRef.inferObjCARCLifetime(Var))
|
||||
|
|
|
@ -1012,6 +1012,18 @@ struct __declspec(dllexport) LayerTreeImpl {
|
|||
// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QAE@XZ"
|
||||
// M64-DAG: define weak_odr dso_local dllexport %"struct.LayerTreeImpl::ElementLayers"* @"??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
|
||||
|
||||
namespace pr39496 {
|
||||
// Make sure dll attribute are inherited by static locals also in template
|
||||
// specializations.
|
||||
template <typename> struct __declspec(dllexport) S { int foo() { static int x; return x++; } };
|
||||
int foo() { S<int> s; return s.foo(); }
|
||||
// MSC-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
|
||||
|
||||
template <typename> struct T { int foo() { static int x; return x++; } };
|
||||
template struct __declspec(dllexport) T<int>;
|
||||
// MSC-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = weak_odr dso_local dllexport global i32 0, comdat, align 4
|
||||
}
|
||||
|
||||
class __declspec(dllexport) ACE_Shared_Object {
|
||||
public:
|
||||
virtual ~ACE_Shared_Object();
|
||||
|
|
|
@ -996,3 +996,16 @@ template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int
|
|||
USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
|
||||
// M32-DAG: declare dllimport x86_thiscallcc void @"?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
|
||||
// G32-DAG: define weak_odr dso_local x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv
|
||||
|
||||
namespace pr39496 {
|
||||
// Make sure dll attribute are inherited by static locals also in template
|
||||
// specializations.
|
||||
template <typename> struct __declspec(dllimport) S { int foo() { static int x; return x++; } };
|
||||
int foo() { S<int> s; return s.foo(); }
|
||||
// MO1-DAG: @"?x@?{{1|2}}??foo@?$S@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4
|
||||
|
||||
template <typename> struct T { int foo() { static int x; return x++; } };
|
||||
extern template struct __declspec(dllimport) T<int>;
|
||||
int bar() { T<int> t; return t.foo(); }
|
||||
// MO1-DAG: @"?x@?{{1|2}}??foo@?$T@H@pr39496@@Q{{[A-Z]*}}HXZ@4HA" = available_externally dllimport global i32 0, align 4
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue