summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Sema/Sema.h4
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp114
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp7
-rw-r--r--clang/test/CodeGenCXX/dllexport.cpp5
-rw-r--r--clang/test/CodeGenCXX/dllimport.cpp6
5 files changed, 79 insertions, 57 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 39ea3c62a87..60664c5fdc9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5110,6 +5110,10 @@ public:
bool AnyErrors);
void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
+ void propagateDLLAttrToBaseClassTemplate(
+ CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec,
+ SourceLocation BaseLoc);
void CheckCompletedCXXClass(CXXRecordDecl *Record);
void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
Decl *TagDecl,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 8859cc1b67d..c80ef2d2bdc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1345,61 +1345,6 @@ static bool findCircularInheritance(const CXXRecordDecl *Class,
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;
- }
-
- 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;
- }
-
- if (getDLLAttr(BaseTemplateSpec)) {
- // The template has already been specialized or instantiated with an
- // attribute, explicitly or through propagation. We should not try to change
- // it.
- return;
- }
-
- // The template was previously instantiated or explicitly specialized without
- // a dll attribute, It's too late for us to add an attribute, so warn that
- // this is unsupported.
- S.Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
- << BaseTemplateSpec->isExplicitSpecialization();
- 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
@@ -1471,8 +1416,8 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (Attr *ClassAttr = getDLLAttr(Class)) {
if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
BaseType->getAsCXXRecordDecl())) {
- propagateDLLAttrToBaseClassTemplate(*this, Class, ClassAttr,
- BaseTemplate, BaseLoc);
+ propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate,
+ BaseLoc);
}
}
}
@@ -4884,6 +4829,61 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
}
}
+/// \brief Perform propagation of DLL attributes from a derived class to a
+/// templated base class for MS compatibility.
+void Sema::propagateDLLAttrToBaseClassTemplate(
+ 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;
+ }
+
+ 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(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)
+ checkClassLevelDLLAttribute(BaseTemplateSpec);
+
+ return;
+ }
+
+ if (getDLLAttr(BaseTemplateSpec)) {
+ // The template has already been specialized or instantiated with an
+ // attribute, explicitly or through propagation. We should not try to change
+ // it.
+ return;
+ }
+
+ // The template was previously instantiated or explicitly specialized without
+ // a dll attribute, It's too late for us to add an attribute, so warn that
+ // this is unsupported.
+ Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
+ << BaseTemplateSpec->isExplicitSpecialization();
+ Diag(ClassAttr->getLocation(), diag::note_attribute);
+ if (BaseTemplateSpec->isExplicitSpecialization()) {
+ Diag(BaseTemplateSpec->getLocation(),
+ diag::note_template_class_explicit_specialization_was_here)
+ << BaseTemplateSpec;
+ } else {
+ Diag(BaseTemplateSpec->getPointOfInstantiation(),
+ diag::note_template_class_instantiation_was_here)
+ << BaseTemplateSpec;
+ }
+}
+
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4fb7cb8f1dd..19c0f2a9390 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -7379,6 +7379,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
A->setInherited(true);
Def->addAttr(A);
checkClassLevelDLLAttribute(Def);
+
+ // Propagate attribute to base class templates.
+ for (auto &B : Def->bases()) {
+ if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ B.getType()->getAsCXXRecordDecl()))
+ propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getLocStart());
+ }
}
}
diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp
index 3795cbcbee6..477e7dcf0b5 100644
--- a/clang/test/CodeGenCXX/dllexport.cpp
+++ b/clang/test/CodeGenCXX/dllexport.cpp
@@ -707,6 +707,11 @@ void PR23308::f(InternalLinkageType*) {}
long use(PR23308* p) { p->f(nullptr); }
// M32-DAG: define internal x86_thiscallcc void @"\01?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z"
+template <typename T> struct PR23770BaseTemplate { void f() {} };
+template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
+extern template struct PR23770DerivedTemplate<int>;
+template struct __declspec(dllexport) PR23770DerivedTemplate<int>;
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp
index 9e3813e5e1b..0f15ff0291b 100644
--- a/clang/test/CodeGenCXX/dllimport.cpp
+++ b/clang/test/CodeGenCXX/dllimport.cpp
@@ -741,6 +741,12 @@ USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f);
// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ"
+template <typename T> struct PR23770BaseTemplate { void f() {} };
+template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {};
+extern template struct PR23770DerivedTemplate<int>;
+template struct __declspec(dllimport) PR23770DerivedTemplate<int>;
+USEMEMFUNC(PR23770BaseTemplate<int>, f);
+// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ"
//===----------------------------------------------------------------------===//
// Classes with template base classes
OpenPOWER on IntegriCloud