Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -2130,6 +2130,11 @@ InGroup>; def err_attribute_dll_member_of_dll_class : Error< "attribute %q0 cannot be applied to member of %q1 class">; +def warn_attribute_dll_instantiated_base_class : Warning< + "propagating dll attribute to %select{already instantiated|explicitly specialized}0 " + "base class template " + "%select{without dll attribute|with different dll attribute}1 is unsupported">, + InGroup>; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< @@ -3405,6 +3410,10 @@ "%select{implicit|explicit}0 instantiation of undefined template %1">; def err_implicit_instantiate_member_undefined : Error< "implicit instantiation of undefined member %0">; +def note_template_class_instantiation_was_here : Note< + "class template %0 was instantiated here">; +def note_template_class_explicit_specialization_was_here : Note< + "class template %0 was explicitly specialized here">; def note_template_class_instantiation_here : Note< "in instantiation of template class %0 requested here">; def note_template_member_class_here : Note< Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp @@ -1296,6 +1296,57 @@ return false; } +/// \brief Perform propagation of DLL attributes from a derived class to a +/// templated base class for MS compatibility. +static void propagateDLLAttrToBaseClassTemplate( + Sema &S, CXXRecordDecl *Class, Attr *ClassAttr, + ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) { + if (getDLLAttr( + BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) { + // If the base class template has a DLL attribute, don't try to change it. + return; + } + + if (BaseTemplateSpec->getSpecializationKind() == TSK_Undeclared) { + // If the base class is not already specialized, we can do the propagation. + auto *NewAttr = cast(ClassAttr->clone(S.getASTContext())); + NewAttr->setInherited(true); + BaseTemplateSpec->addAttr(NewAttr); + return; + } + + bool DifferentAttribute = false; + if (Attr *SpecializationAttr = getDLLAttr(BaseTemplateSpec)) { + if (!SpecializationAttr->isInherited()) { + // The template has previously been specialized or instantiated with an + // explicit attribute. We should not try to change it. + return; + } + if (SpecializationAttr->getKind() == ClassAttr->getKind()) { + // The specialization already has the right attribute. + return; + } + DifferentAttribute = true; + } + + // The template was previously instantiated or explicitly specialized without + // a dll attribute, or the template was previously instantiated with a + // different inherited attribute. It's too late for us to change the + // attribute, so warn that this is unsupported. + S.Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class) + << BaseTemplateSpec->isExplicitSpecialization() << DifferentAttribute; + S.Diag(ClassAttr->getLocation(), diag::note_attribute); + if (BaseTemplateSpec->isExplicitSpecialization()) { + S.Diag(BaseTemplateSpec->getLocation(), + diag::note_template_class_explicit_specialization_was_here) + << BaseTemplateSpec; + } else { + S.Diag(BaseTemplateSpec->getPointOfInstantiation(), + diag::note_template_class_instantiation_was_here) + << BaseTemplateSpec; + } +} + /// \brief Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics @@ -1362,6 +1413,17 @@ return nullptr; } + // For the MS ABI, propagate DLL attributes to base class templates. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + if (Attr *ClassAttr = getDLLAttr(Class)) { + if (auto *BaseTemplate = dyn_cast_or_null( + BaseType->getAsCXXRecordDecl())) { + propagateDLLAttrToBaseClassTemplate(*this, Class, ClassAttr, + BaseTemplate, BaseLoc); + } + } + } + // C++ [class.derived]p2: // The class-name in a base-specifier shall not be an incompletely // defined class. @@ -4361,9 +4423,6 @@ // FIXME: MSVC's docs say all bases must be exportable, but this doesn't // seem to be true in practice? - // FIXME: We also need to propagate the attribute upwards to class template - // specialization bases. - for (Decl *Member : Class->decls()) { VarDecl *VD = dyn_cast(Member); CXXMethodDecl *MD = dyn_cast(Member); @@ -4385,7 +4444,7 @@ if (InheritableAttr *MemberAttr = getDLLAttr(Member)) { if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && - !MemberAttr->isInherited()) { + !MemberAttr->isInherited() && !ClassAttr->isInherited()) { S.Diag(MemberAttr->getLocation(), diag::err_attribute_dll_member_of_dll_class) << MemberAttr << ClassAttr; Index: cfe/trunk/test/CodeGenCXX/dllexport.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/dllexport.cpp +++ cfe/trunk/test/CodeGenCXX/dllexport.cpp @@ -582,3 +582,101 @@ USEMEMFUNC(ExplicitlySpecializedClassTemplate, f); // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template struct ClassTemplate { void func() {} }; +template struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; +template struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; + +template struct ExplicitlySpecializedTemplate { void func() {} }; +template <> struct ExplicitlySpecializedTemplate { void func() {} }; +template struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate { void func() {} }; +template struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate { void func() {} }; + +template struct ExplicitlyInstantiatedTemplate { void func() {} }; +template struct ExplicitlyInstantiatedTemplate; +template struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate; +template struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate; + + +// MS: ClassTemplate gets exported. +struct __declspec(dllexport) DerivedFromTemplate : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv + +// ExportedTemplate is explicitly exported. +struct __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate {}; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv + +// ImportedClassTemplate is explicitly imported. +struct __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate {}; +USEMEMFUNC(ImportedClassTemplate, func) +// 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. +struct DerivedFromTemplateD : public ClassTemplate {}; +struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: define linkonce_odr 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. +struct __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate {}; +struct __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv + +// Base class already specialized without dll attribute. +struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate {}; +USEMEMFUNC(ExplicitlySpecializedTemplate, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv + +// Base class alredy specialized with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate {}; +USEMEMFUNC(ExplicitlyExportSpecializedTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv + +// Base class already specialized with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate {}; +USEMEMFUNC(ExplicitlyImportSpecializedTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv + +// Base class already instantiated without dll attribute. +struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyInstantiatedTemplate, func) +// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyExportInstantiatedTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyImportInstantiatedTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv + +// MS: A dll attribute propagates through multiple levels of instantiation. +template struct TopClass { void func() {} }; +template struct MiddleClass : public TopClass { }; +struct __declspec(dllexport) BottomClas : public MiddleClass { }; +USEMEMFUNC(TopClass, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv Index: cfe/trunk/test/CodeGenCXX/dllimport.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/dllimport.cpp +++ cfe/trunk/test/CodeGenCXX/dllimport.cpp @@ -662,3 +662,102 @@ USEMEMFUNC(ExplicitlySpecializedClassTemplate, f); // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlySpecializedClassTemplate@PAX@@QAEXXZ" // G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN34ExplicitlySpecializedClassTemplateIPvE1fEv + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template struct ClassTemplate { void func() {} }; +template struct __declspec(dllexport) ExportedClassTemplate { void func() {} }; +template struct __declspec(dllimport) ImportedClassTemplate { void func() {} }; + +template struct ExplicitlySpecializedTemplate { void func() {} }; +template <> struct ExplicitlySpecializedTemplate { void func() {} }; +template struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate { void func() {} }; +template struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate { void func() {} }; + +template struct ExplicitlyInstantiatedTemplate { void func() {} }; +template struct ExplicitlyInstantiatedTemplate; +template struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate; +template struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate; + + +// MS: ClassTemplate gets imported. +struct __declspec(dllimport) DerivedFromTemplate : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIiE4funcEv + +// ImportedTemplate is explicitly imported. +struct __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate {}; +USEMEMFUNC(ImportedClassTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" +// G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv + +// ExportedTemplate is explicitly exported. +struct __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate {}; +USEMEMFUNC(ExportedClassTemplate, func) +// 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. +struct DerivedFromTemplateD : public ClassTemplate {}; +struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: define linkonce_odr 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. +struct __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate {}; +struct __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate {}; +USEMEMFUNC(ClassTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@_N@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIbE4funcEv + +// Base class already specialized without dll attribute. +struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate {}; +USEMEMFUNC(ExplicitlySpecializedTemplate, func) +// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ExplicitlySpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN29ExplicitlySpecializedTemplateIiE4funcEv + +// Base class alredy specialized with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate {}; +USEMEMFUNC(ExplicitlyExportSpecializedTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN35ExplicitlyExportSpecializedTemplateIiE4funcEv + +// Base class already specialized with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate {}; +USEMEMFUNC(ExplicitlyImportSpecializedTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportSpecializedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN35ExplicitlyImportSpecializedTemplateIiE4funcEv + +// Base class already instantiated without dll attribute. +struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyInstantiatedTemplate, func) +// M32-DAG: define weak_odr x86_thiscallcc void @"\01?func@?$ExplicitlyInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN30ExplicitlyInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyExportInstantiatedTemplate, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitlyExportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN36ExplicitlyExportInstantiatedTemplateIiE4funcEv + +// Base class already instantiated with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate {}; +USEMEMFUNC(ExplicitlyImportInstantiatedTemplate, func) +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ExplicitlyImportInstantiatedTemplate@H@@QAEXXZ" +// G32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @_ZN36ExplicitlyImportInstantiatedTemplateIiE4funcEv + +// MS: A dll attribute propagates through multiple levels of instantiation. +template struct TopClass { void func() {} }; +template struct MiddleClass : public TopClass { }; +struct __declspec(dllimport) BottomClas : public MiddleClass { }; +USEMEMFUNC(TopClass, 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 Index: cfe/trunk/test/SemaCXX/dllexport.cpp =================================================================== --- cfe/trunk/test/SemaCXX/dllexport.cpp +++ cfe/trunk/test/SemaCXX/dllexport.cpp @@ -316,7 +316,7 @@ class __declspec(dllexport) ClassDecl; -class __declspec(dllexport) ClassDef { }; +class __declspec(dllexport) ClassDef {}; #ifdef MS // expected-warning@+3{{'dllexport' attribute ignored}} @@ -328,6 +328,86 @@ template <> struct __declspec(dllexport) ExpliciallySpecializedClassTemplate { void f() {} }; +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template class ClassTemplate {}; +template class __declspec(dllexport) ExportedClassTemplate {}; +template class __declspec(dllimport) ImportedClassTemplate {}; + +template struct ExplicitlySpecializedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlySpecializedTemplate' was explicitly specialized here}} +#endif +template <> struct ExplicitlySpecializedTemplate { void func() {} }; +template struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate { void func() {} }; +template struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate { void func() {} }; + +template struct ExplicitlyInstantiatedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlyInstantiatedTemplate' was instantiated here}} +#endif +template struct ExplicitlyInstantiatedTemplate; +template struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate; +template struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate; + +// ClassTemplate gets exported. +class __declspec(dllexport) DerivedFromTemplate : public ClassTemplate {}; + +// ClassTemplate is already exported. +class __declspec(dllexport) DerivedFromTemplate2 : public ClassTemplate {}; + +// ExportedTemplate is explicitly exported. +class __declspec(dllexport) DerivedFromExportedTemplate : public ExportedClassTemplate {}; + +// ImportedTemplate is explicitly imported. +class __declspec(dllexport) DerivedFromImportedTemplate : public ImportedClassTemplate {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template without dll attribute is unsupported}} +// expected-note@+3{{attribute is here}} +#endif +class DerivedFromTemplateD : public ClassTemplate {}; +class __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template with different dll attribute is unsupported}} +// expected-note@+3{{attribute is here}} +#endif +class __declspec(dllimport) DerivedFromTemplateB : public ClassTemplate {}; +class __declspec(dllexport) DerivedFromTemplateB2 : public ClassTemplate {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to explicitly specialized base class template without dll attribute is unsupported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllexport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate {}; + +// Base class alredy specialized with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate {}; + +// Base class already specialized with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to already instantiated base class template without dll attribute is unsupported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllexport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate {}; + +// Base class already instantiated with export attribute. +struct __declspec(dllexport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate {}; + +// Base class already instantiated with import attribute. +struct __declspec(dllexport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate {}; + //===----------------------------------------------------------------------===// // Precedence Index: cfe/trunk/test/SemaCXX/dllimport.cpp =================================================================== --- cfe/trunk/test/SemaCXX/dllimport.cpp +++ cfe/trunk/test/SemaCXX/dllimport.cpp @@ -955,6 +955,8 @@ class __declspec(dllimport) ClassDef { }; +template class ClassTemplate {}; + #ifdef MS // expected-note@+5{{previous attribute is here}} // expected-note@+4{{previous attribute is here}} @@ -1000,3 +1002,84 @@ template struct ExpliciallySpecializedClassTemplate {}; template <> struct __declspec(dllimport) ExpliciallySpecializedClassTemplate { void f() {} }; + + +//===----------------------------------------------------------------------===// +// Classes with template base classes +//===----------------------------------------------------------------------===// + +template class __declspec(dllexport) ExportedClassTemplate {}; + +template class __declspec(dllimport) ImportedClassTemplate {}; + +// ClassTemplate gets imported. +class __declspec(dllimport) DerivedFromTemplate : public ClassTemplate {}; + +// ClassTemplate is already imported. +class __declspec(dllimport) DerivedFromTemplate2 : public ClassTemplate {}; + +// ImportedClassTemplate is expliitly imported. +class __declspec(dllimport) DerivedFromImportedTemplate : public ImportedClassTemplate {}; + +// ExportedClassTemplate is explicitly exported. +class __declspec(dllimport) DerivedFromExportedTemplate : public ExportedClassTemplate {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template without dll attribute is unsupported}} +// expected-note@+3{{attribute is here}} +#endif +class DerivedFromTemplateD : public ClassTemplate {}; +class __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate {}; + +#ifdef MS +// expected-note@+4{{class template 'ClassTemplate' was instantiated here}} +// expected-warning@+4{{propagating dll attribute to already instantiated base class template with different dll attribute is unsupported}} +// expected-note@+3{{attribute is here}} +#endif +class __declspec(dllexport) DerivedFromTemplateB : public ClassTemplate {}; +class __declspec(dllimport) DerivedFromTemplateB2 : public ClassTemplate {}; + +template struct ExplicitlySpecializedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlySpecializedTemplate' was explicitly specialized here}} +#endif +template <> struct ExplicitlySpecializedTemplate { void func() {} }; +template struct ExplicitlyExportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllexport) ExplicitlyExportSpecializedTemplate { void func() {} }; +template struct ExplicitlyImportSpecializedTemplate { void func() {} }; +template <> struct __declspec(dllimport) ExplicitlyImportSpecializedTemplate { void func() {} }; + +template struct ExplicitlyInstantiatedTemplate { void func() {} }; +#ifdef MS +// expected-note@+2{{class template 'ExplicitlyInstantiatedTemplate' was instantiated here}} +#endif +template struct ExplicitlyInstantiatedTemplate; +template struct ExplicitlyExportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate; +template struct ExplicitlyImportInstantiatedTemplate { void func() {} }; +template struct __declspec(dllimport) ExplicitlyImportInstantiatedTemplate; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to explicitly specialized base class template without dll attribute is unsupported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllimport) DerivedFromExplicitlySpecializedTemplate : public ExplicitlySpecializedTemplate {}; + +// Base class already specialized with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportSpecializedTemplate : public ExplicitlyExportSpecializedTemplate {}; + +// Base class already specialized with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportSpecializedTemplate : public ExplicitlyImportSpecializedTemplate {}; + +#ifdef MS +// expected-warning@+3{{propagating dll attribute to already instantiated base class template without dll attribute is unsupported}} +// expected-note@+2{{attribute is here}} +#endif +struct __declspec(dllimport) DerivedFromExplicitlyInstantiatedTemplate : public ExplicitlyInstantiatedTemplate {}; + +// Base class already instantiated with export attribute. +struct __declspec(dllimport) DerivedFromExplicitlyExportInstantiatedTemplate : public ExplicitlyExportInstantiatedTemplate {}; + +// Base class already instantiated with import attribute. +struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : public ExplicitlyImportInstantiatedTemplate {};