diff options
author | Hans Wennborg <hans@hanshq.net> | 2018-02-13 09:19:43 +0000 |
---|---|---|
committer | Hans Wennborg <hans@hanshq.net> | 2018-02-13 09:19:43 +0000 |
commit | 3bd0a1586712e40972269074283b35196aee0ddc (patch) | |
tree | 3fd3e011d3e71c9855428fbd1e0d1b704639c099 | |
parent | 0bb24cd4fabb15c4d17adb26db08bc1ef9de9920 (diff) | |
download | bcm5719-llvm-3bd0a1586712e40972269074283b35196aee0ddc.tar.gz bcm5719-llvm-3bd0a1586712e40972269074283b35196aee0ddc.zip |
Fix for PR32992. Static const classes not exported.
Patch by zahiraam!
Differential Revision: https://reviews.llvm.org/D42968
llvm-svn: 324991
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 16 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllexport.cpp | 19 |
2 files changed, 32 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 45adbe3a16e..d3f3a1a9382 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5476,7 +5476,7 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } -static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { +static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); if (!ClassAttr) return; @@ -5491,6 +5491,16 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { return; for (Decl *Member : Class->decls()) { + // Defined static variables that are members of an exported base + // class must be marked export too. Push them to implicit instantiation + // queue. + auto *VD = dyn_cast<VarDecl>(Member); + if (VD && Member->getAttr<DLLExportAttr>() && + VD->getStorageClass() == SC_Static && + TSK == TSK_ImplicitInstantiation) + S.PendingLocalImplicitInstantiations.push_back( + std::make_pair(VD, VD->getLocation())); + auto *MD = dyn_cast<CXXMethodDecl>(Member); if (!MD) continue; @@ -10902,12 +10912,12 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { void Sema::referenceDLLExportedClassMethods() { if (!DelayedDllExportClasses.empty()) { - // Calling ReferenceDllExportedMethods might cause the current function to + // Calling ReferenceDllExportedMembers might cause the current function to // be called again, so use a local copy of DelayedDllExportClasses. SmallVector<CXXRecordDecl *, 4> WorkList; std::swap(DelayedDllExportClasses, WorkList); for (CXXRecordDecl *Class : WorkList) - ReferenceDllExportedMethods(*this, Class); + ReferenceDllExportedMembers(*this, Class); } } diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index a446147b6cd..97ce5b54c4e 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -28,6 +28,7 @@ struct External { int v; }; // The vftable for struct W is comdat largest because we have RTTI. // M32-DAG: $"\01??_7W@@6B@" = comdat largest +// M32-DAG: $"\01?smember@?$Base@H@PR32992@@0HA" = comdat any //===----------------------------------------------------------------------===// @@ -977,3 +978,21 @@ class __declspec(dllexport) ACE_Service_Object : public ACE_Shared_Object {}; // MSVC2015-DAG: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q // The declarations should not be exported. // MSVC2013-NOT: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q + +namespace PR32992 { +// Static data members of a instantiated base class should be exported. +template <class T> +class Base { + virtual void myfunc() {} + static int smember; +}; +// MS-DAG: @"\01?smember@?$Base@H@PR32992@@0HA" = weak_odr dllexport global i32 77, comdat, align 4 +template <class T> int Base<T>::smember = 77; +template <class T> +class __declspec(dllexport) Derived2 : Base<T> { + void myfunc() {} +}; +class Derived : public Derived2<int> { + void myfunc() {} +}; +} // namespace PR32992 |