]> granicus.if.org Git - clang/commitdiff
Re-commit r324991 "Fix for PR32992. Static const classes not exported."
authorHans Wennborg <hans@hanshq.net>
Mon, 26 Feb 2018 15:03:59 +0000 (15:03 +0000)
committerHans Wennborg <hans@hanshq.net>
Mon, 26 Feb 2018 15:03:59 +0000 (15:03 +0000)
Fix for PR32992. Static const classes not exported.

Patch by zahiraam!

(This re-lands the commit, but using S.MarkVariableReferenced instead of
S.PendingInstantiations.push_back, and with an additional test.)

Differential Revision: https://reviews.llvm.org/D42968

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@326089 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/dllexport.cpp

index 45adbe3a16edaa1f1d18024dfdaab8dd79545eb9..76ef9af73ffd0b95b2b9c8d05e3fa40b6ef388e8 100644 (file)
@@ -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,14 @@ 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.
+    auto *VD = dyn_cast<VarDecl>(Member);
+    if (VD && Member->getAttr<DLLExportAttr>() &&
+        VD->getStorageClass() == SC_Static &&
+        TSK == TSK_ImplicitInstantiation)
+      S.MarkVariableReferenced(VD->getLocation(), VD);
+
     auto *MD = dyn_cast<CXXMethodDecl>(Member);
     if (!MD)
       continue;
@@ -10902,12 +10910,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);
   }
 }
 
index 5c8a60b67da99dfa4de0673770919737fc19f274..4ab84c14f1b80e26aee237f7da3612278f3894e5 100644 (file)
@@ -29,6 +29,8 @@ 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
+
 
 //===----------------------------------------------------------------------===//
 // Globals
@@ -94,7 +96,35 @@ inline int __declspec(dllexport) inlineStaticLocalsFunc() {
   return x++;
 }
 
+namespace PR32992 {
+// Static data members of a instantiated base class should be exported.
+template <class T>
+class Base {
+  virtual void myfunc() {}
+  static int smember;
+};
+// MSC-DAG: @"\01?smember@?$Base@H@PR32992@@0HA" = weak_odr dso_local 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
 
+namespace PR32992_1 {
+namespace a { enum b { c }; }
+template <typename> class d {
+   static constexpr a::b e = a::c;
+};
+namespace f {
+  template <typename g = int> class h : d<g> {};
+}
+using f::h;
+class __declspec(dllexport) i : h<> {};
+}
 
 //===----------------------------------------------------------------------===//
 // Variable templates