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