summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h1
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp36
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp11
-rw-r--r--clang/test/CodeGenCXX/dllexport.cpp5
-rw-r--r--clang/test/CodeGenCXX/dllimport.cpp12
5 files changed, 46 insertions, 19 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a7020589e85..39ea3c62a87 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5109,6 +5109,7 @@ public:
ArrayRef<CXXCtorInitializer*> MemInits,
bool AnyErrors);
+ void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
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 e52d29e45c5..b1dfe0e95e2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4739,15 +4739,15 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
}
/// \brief Check class-level dllimport/dllexport attribute.
-static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
+void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
- auto *A = cast<InheritableAttr>(TemplateAttr->clone(S.getASTContext()));
+ auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext()));
A->setInherited(true);
ClassAttr = A;
}
@@ -4758,12 +4758,12 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
return;
if (!Class->isExternallyVisible()) {
- S.Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
+ Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
<< Class << ClassAttr;
return;
}
- if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
@@ -4773,10 +4773,10 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
continue;
- S.Diag(MemberAttr->getLocation(),
+ Diag(MemberAttr->getLocation(),
diag::err_attribute_dll_member_of_dll_class)
<< MemberAttr << ClassAttr;
- S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
+ Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
Member->setInvalidDecl();
}
}
@@ -4798,7 +4798,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
}
// Force declaration of implicit members so they can inherit the attribute.
- S.ForceDeclarationOfImplicitMembers(Class);
+ ForceDeclarationOfImplicitMembers(Class);
// FIXME: MSVC's docs say all bases must be exportable, but this doesn't
// seem to be true in practice?
@@ -4818,13 +4818,13 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (MD->isInlined()) {
// MinGW does not import or export inline methods.
- if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
continue;
// MSVC versions before 2015 don't export the move assignment operators,
// so don't attempt to import them if we have a definition.
if (ClassImported && MD->isMoveAssignmentOperator() &&
- !S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
+ !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
continue;
}
}
@@ -4834,7 +4834,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (!getDLLAttr(Member)) {
auto *NewAttr =
- cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
+ cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
}
@@ -4849,7 +4849,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
continue;
- S.MarkFunctionReferenced(Class->getLocation(), MD);
+ MarkFunctionReferenced(Class->getLocation(), MD);
// The function will be passed to the consumer when its definition is
// encountered.
@@ -4860,17 +4860,17 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
// defaulted methods, and the copy and move assignment operators. The
// latter are exported even if they are trivial, because the address of
// an operator can be taken and should compare equal accross libraries.
- DiagnosticErrorTrap Trap(S.Diags);
- S.MarkFunctionReferenced(Class->getLocation(), MD);
+ DiagnosticErrorTrap Trap(Diags);
+ MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
- S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
- << Class->getName() << !S.getLangOpts().CPlusPlus11;
+ Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
+ << Class->getName() << !getLangOpts().CPlusPlus11;
break;
}
// There is no later point when we will see the definition of this
// function, so pass it to the consumer now.
- S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+ Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
}
}
}
@@ -5014,7 +5014,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// have inheriting constructors.
DeclareInheritingConstructors(Record);
- checkDLLAttribute(*this, Record);
+ checkClassLevelDLLAttribute(Record);
}
/// Look up the special member function that would be called by a special
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index b5d04cf1a12..37eeee2f886 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -7365,10 +7365,19 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Fix a TSK_ExplicitInstantiationDeclaration followed by a
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
- TSK == TSK_ExplicitInstantiationDefinition)
+ TSK == TSK_ExplicitInstantiationDefinition) {
// FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
+ if (!getDLLAttr(Def) && getDLLAttr(Specialization)) {
+ auto *A = cast<InheritableAttr>(
+ getDLLAttr(Specialization)->clone(getASTContext()));
+ A->setInherited(true);
+ Def->addAttr(A);
+ checkClassLevelDLLAttribute(Def);
+ }
+ }
+
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
}
diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp
index bc1486f0d7d..3a1a3ffd871 100644
--- a/clang/test/CodeGenCXX/dllexport.cpp
+++ b/clang/test/CodeGenCXX/dllexport.cpp
@@ -691,6 +691,11 @@ extern template struct ExplicitInstantiationDeclExportedTemplate<int>;
USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f);
// M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
+template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} };
+extern template struct ExplicitInstantiationDeclExportedDefTemplate<int>;
+template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefTemplate<int>;
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
+
namespace { struct InternalLinkageType {}; }
struct __declspec(dllexport) PR23308 {
void f(InternalLinkageType*);
diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp
index 639baea5a3d..6de856017b5 100644
--- a/clang/test/CodeGenCXX/dllimport.cpp
+++ b/clang/test/CodeGenCXX/dllimport.cpp
@@ -724,6 +724,18 @@ template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<in
USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
+template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} };
+extern template struct ExplicitInstantiationDeclImportedDefTemplate<int>;
+template struct __declspec(dllimport) ExplicitInstantiationDeclImportedDefTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclImportedDefTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
+
+template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} };
+extern template struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate <int>;
+template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefImportedTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
+
//===----------------------------------------------------------------------===//
// Classes with template base classes
OpenPOWER on IntegriCloud