Author: hans
Date: Mon Jun  8 19:39:03 2015
New Revision: 239373

URL: http://llvm.org/viewvc/llvm-project?rev=239373&view=rev
Log:
Enable propagation of dll attributes to previously instantiated base class 
templates in some cases

It is safe to add a dll attribute if the base class template previously only had
an explicit instantiation declaration, or was implicitly instantiated.

I both those cases, the members would not have been codegenned yet. In the case
of explicit instantiation declaration this is natural, and for implicit
instantiations, codegen is deferred (see r225570).

This is work towards fixing PR23770.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/dllexport.cpp
    cfe/trunk/test/CodeGenCXX/dllimport.cpp
    cfe/trunk/test/SemaCXX/dllexport.cpp
    cfe/trunk/test/SemaCXX/dllimport.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=239373&r1=239372&r2=239373&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jun  8 19:39:03 2015
@@ -1356,11 +1356,23 @@ static void propagateDLLAttrToBaseClassT
     return;
   }
 
-  if (BaseTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
-    // If the base class is not already specialized, we can do the propagation.
+  auto TSK = BaseTemplateSpec->getSpecializationKind();
+  if (!getDLLAttr(BaseTemplateSpec) &&
+      (TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration ||
+       TSK == TSK_ImplicitInstantiation)) {
+    // The template hasn't been instantiated yet (or it has, but only as an
+    // explicit instantiation declaration or implicit instantiation, which 
means
+    // we haven't codegenned any members yet), so propagate the attribute.
     auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
     NewAttr->setInherited(true);
     BaseTemplateSpec->addAttr(NewAttr);
+
+    // If the template is already instantiated, 
checkDLLAttributeRedeclaration()
+    // needs to be run again to work see the new attribute. Otherwise this will
+    // get run whenever the template is instantiated.
+    if (TSK != TSK_Undeclared)
+      S.checkClassLevelDLLAttribute(BaseTemplateSpec);
+
     return;
   }
 
@@ -4783,8 +4795,9 @@ void Sema::checkClassLevelDLLAttribute(C
 
   TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
 
-  // Don't dllexport explicit class template instantiation declarations.
-  if (ClassExported && TSK == TSK_ExplicitInstantiationDeclaration) {
+  // Ignore explicit dllexport on explicit class template instantiation 
declarations.
+  if (ClassExported && !ClassAttr->isInherited() &&
+      TSK == TSK_ExplicitInstantiationDeclaration) {
     Class->dropAttr<DLLExportAttr>();
     return;
   }
@@ -4832,12 +4845,15 @@ void Sema::checkClassLevelDLLAttribute(C
     }
 
     if (MD && ClassExported) {
+      if (TSK == TSK_ExplicitInstantiationDeclaration)
+        // Don't go any further if this is just an explicit instantiation
+        // declaration.
+        continue;
+
       if (MD->isUserProvided()) {
         // Instantiate non-default class member functions ...
 
         // .. except for certain kinds of template specializations.
-        if (TSK == TSK_ExplicitInstantiationDeclaration)
-          continue;
         if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
           continue;
 

Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=239373&r1=239372&r2=239373&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Mon Jun  8 19:39:03 2015
@@ -755,11 +755,11 @@ USEMEMFUNC(DerivedFromImportedTemplate,
 // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc 
void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ"
 // G32-DAG: declare dllimport x86_thiscallcc void 
@_ZN21ImportedClassTemplateIiE4funcEv
 
-// Base class already instantiated without dll attribute.
+// Base class already implicitly instantiated without dll attribute.
 struct DerivedFromTemplateD : public ClassTemplate<double> {};
 struct __declspec(dllexport) DerivedFromTemplateD2 : public 
ClassTemplate<double> {};
 USEMEMFUNC(DerivedFromTemplateD2, func)
-// M32-DAG: define linkonce_odr x86_thiscallcc void 
@"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void 
@"\01?func@?$ClassTemplate@N@@QAEXXZ"
 // G32-DAG: define linkonce_odr x86_thiscallcc void 
@_ZN13ClassTemplateIdE4funcEv
 
 // MS: Base class already instantiated with different dll attribute.
@@ -812,3 +812,18 @@ struct __declspec(dllexport) BottomClass
 USEMEMFUNC(BottomClass, func)
 // M32-DAG: define weak_odr dllexport x86_thiscallcc void 
@"\01?func@?$TopClass@H@@QAEXXZ"
 // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
+
+template <typename T> struct ExplicitInstantiationDeclTemplateBase { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase<int>;
+struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase 
: public ExplicitInstantiationDeclTemplateBase<int> {};
+template struct ExplicitInstantiationDeclTemplateBase<int>;
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void 
@"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void 
@_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
+
+template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase2<int>;
+struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase2 
: public ExplicitInstantiationDeclTemplateBase2<int> {};
+template struct __declspec(dllimport) 
ExplicitInstantiationDeclTemplateBase2<int>;
+USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void 
@"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void 
@_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv

Modified: cfe/trunk/test/CodeGenCXX/dllimport.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllimport.cpp?rev=239373&r1=239372&r2=239373&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllimport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllimport.cpp Mon Jun  8 19:39:03 2015
@@ -785,11 +785,11 @@ USEMEMFUNC(ExportedClassTemplate<int>, f
 // M32-DAG: define weak_odr dllexport x86_thiscallcc void 
@"\01?func@?$ExportedClassTemplate@H@@QAEXXZ"
 // G32-DAG: define weak_odr dllexport x86_thiscallcc void 
@_ZN21ExportedClassTemplateIiE4funcEv
 
-// Base class already instantiated without attribute.
+// Base class already implicitly instantiated without attribute.
 struct DerivedFromTemplateD : public ClassTemplate<double> {};
 struct __declspec(dllimport) DerivedFromTemplateD2 : public 
ClassTemplate<double> {};
 USEMEMFUNC(ClassTemplate<double>, func)
-// M32-DAG: define linkonce_odr x86_thiscallcc void 
@"\01?func@?$ClassTemplate@N@@QAEXXZ"
+// M32-DAG: declare dllimport x86_thiscallcc void 
@"\01?func@?$ClassTemplate@N@@QAEXXZ"
 // G32-DAG: define linkonce_odr x86_thiscallcc void 
@_ZN13ClassTemplateIdE4funcEv
 
 // MS: Base class already instantiated with dfferent attribute.
@@ -842,3 +842,19 @@ struct __declspec(dllimport) BottomClass
 USEMEMFUNC(TopClass<int>, func)
 // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc 
void @"\01?func@?$TopClass@H@@QAEXXZ"
 // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv
+
+template <typename T> struct ExplicitInstantiationDeclTemplateBase { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase<int>;
+struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase 
: public ExplicitInstantiationDeclTemplateBase<int> {};
+template struct ExplicitInstantiationDeclTemplateBase<int>;
+USEMEMFUNC(ExplicitInstantiationDeclTemplateBase<int>, func)
+// M32-DAG: declare dllimport x86_thiscallcc void 
@"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void 
@_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv
+
+template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase2<int>;
+struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase2 
: public ExplicitInstantiationDeclTemplateBase2<int> {};
+template struct __declspec(dllexport) 
ExplicitInstantiationDeclTemplateBase2<int>;
+USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func)
+// M32-DAG: declare dllimport x86_thiscallcc void 
@"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ"
+// G32-DAG: define weak_odr x86_thiscallcc void 
@_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv

Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=239373&r1=239372&r2=239373&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Mon Jun  8 19:39:03 2015
@@ -439,14 +439,14 @@ class __declspec(dllexport) DerivedFromE
 // ImportedTemplate is explicitly imported.
 class __declspec(dllexport) DerivedFromImportedTemplate : public 
ImportedClassTemplate<int> {};
 
-#ifdef MS
-// expected-note@+4{{class template 'ClassTemplate<double>' was instantiated 
here}}
-// expected-warning@+4{{propagating dll attribute to already instantiated base 
class template without dll attribute is not supported}}
-// expected-note@+3{{attribute is here}}
-#endif
 class DerivedFromTemplateD : public ClassTemplate<double> {};
+// Base class previously implicitly instantiated without attribute; it will 
get propagated.
 class __declspec(dllexport) DerivedFromTemplateD2 : public 
ClassTemplate<double> {};
 
+// Base class has explicit instantiation declaration; the attribute will get 
propagated.
+extern template class ClassTemplate<float>;
+class __declspec(dllexport) DerivedFromTemplateF : public ClassTemplate<float> 
{};
+
 class __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate<bool> 
{};
 // The second derived class doesn't change anything, the attribute that was 
propagated first wins.
 class __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate<bool> 
{};
@@ -475,6 +475,10 @@ struct __declspec(dllexport) DerivedFrom
 // Base class already instantiated with import attribute.
 struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : 
public ExplicitlyImportInstantiatedTemplate<int> {};
 
+template <typename T> struct ExplicitInstantiationDeclTemplateBase { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase<int>;
+struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase 
: public ExplicitInstantiationDeclTemplateBase<int> {};
+
 
 
//===----------------------------------------------------------------------===//
 // Precedence

Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=239373&r1=239372&r2=239373&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Mon Jun  8 19:39:03 2015
@@ -1274,14 +1274,14 @@ class __declspec(dllimport) DerivedFromI
 // ExportedClassTemplate is explicitly exported.
 class __declspec(dllimport) DerivedFromExportedTemplate : public 
ExportedClassTemplate<int> {};
 
-#ifdef MS
-// expected-note@+4{{class template 'ClassTemplate<double>' was instantiated 
here}}
-// expected-warning@+4{{propagating dll attribute to already instantiated base 
class template without dll attribute is not supported}}
-// expected-note@+3{{attribute is here}}
-#endif
 class DerivedFromTemplateD : public ClassTemplate<double> {};
+// Base class previously implicitly instantiated without attribute; it will 
get propagated.
 class __declspec(dllimport) DerivedFromTemplateD2 : public 
ClassTemplate<double> {};
 
+// Base class has explicit instantiation declaration; the attribute will get 
propagated.
+extern template class ClassTemplate<float>;
+class __declspec(dllimport) DerivedFromTemplateF : public ClassTemplate<float> 
{};
+
 class __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate<bool> 
{};
 // The second derived class doesn't change anything, the attribute that was 
propagated first wins.
 class __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate<bool> 
{};
@@ -1329,3 +1329,7 @@ struct __declspec(dllimport) DerivedFrom
 
 // Base class already instantiated with import attribute.
 struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : 
public ExplicitlyImportInstantiatedTemplate<int> {};
+
+template <typename T> struct ExplicitInstantiationDeclTemplateBase { void 
func() {} };
+extern template struct ExplicitInstantiationDeclTemplateBase<int>;
+struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase 
: public ExplicitInstantiationDeclTemplateBase<int> {};


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to