Skip to content

Commit 9a3f8ee

Browse files
committed
[Clang] Allow simpler visibility annotations when targeting win32 and mingw
1 parent fa5025b commit 9a3f8ee

File tree

7 files changed

+68
-5
lines changed

7 files changed

+68
-5
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4185,6 +4185,14 @@ def DLLExport : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {
41854185
let Documentation = [DLLExportDocs];
41864186
}
41874187

4188+
def DLLExportOnDecl : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {
4189+
// This attribute is only used to warn if there was a `__declspec(dllexport)`
4190+
// on a declaration, but not on the defintion of an explciit instantiation
4191+
let Spellings = [];
4192+
let Subjects = SubjectList<[CXXRecord]>;
4193+
let Documentation = [InternalOnly];
4194+
}
4195+
41884196
def DLLExportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetHasDLLImportExport> {
41894197
// This attribute is used internally only when -fno-dllexport-inlines is
41904198
// passed. This attribute is added to inline functions of a class having the

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,9 @@ def Dangling : DiagGroup<"dangling", [DanglingAssignment,
487487
ReturnStackAddress]>;
488488
def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
489489
def DllexportExplicitInstantiationDecl : DiagGroup<"dllexport-explicit-instantiation-decl">;
490+
def DllexportExplicitInstantiation :
491+
DiagGroup<"dllexport-explicit-instantiation",
492+
[DllexportExplicitInstantiationDecl]>;
490493
def ExcessInitializers : DiagGroup<"excess-initializers">;
491494
def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
492495
def FlagEnum : DiagGroup<"flag-enum">;
@@ -870,7 +873,8 @@ def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
870873

871874
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
872875
def UnknownAttributes : DiagGroup<"unknown-attributes">;
873-
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
876+
def IgnoredAttributes : DiagGroup<"ignored-attributes",
877+
[DllexportExplicitInstantiation]>;
874878
def Attributes : DiagGroup<"attributes", [UnknownAttributes,
875879
IgnoredAttributes]>;
876880
def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3736,9 +3736,19 @@ def warn_attribute_dllimport_static_field_definition : Warning<
37363736
def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
37373737
"explicit instantiation declaration should not be 'dllexport'">,
37383738
InGroup<DllexportExplicitInstantiationDecl>;
3739-
def warn_attribute_dllexport_explicit_instantiation_def : Warning<
3739+
def warn_attr_dllexport_explicit_inst_def : Warning<
37403740
"'dllexport' attribute ignored on explicit instantiation definition">,
3741+
InGroup<DllexportExplicitInstantiation>;
3742+
def warn_attr_dllexport_explicit_inst_def_mismatch : Warning<
3743+
"'dllexport' attribute ignored on explicit instantiation definition">,
3744+
InGroup<IgnoredAttributes>;
3745+
def note_prev_decl_missing_dllexport : Note<
3746+
"'dllexport' attribute is missing on previous declaration">;
3747+
def warn_dllexport_on_decl_ignored : Warning<
3748+
"explicit instantiation definition is not exported without 'dllexport'">,
37413749
InGroup<IgnoredAttributes>;
3750+
def note_dllexport_on_decl : Note<
3751+
"'dllexport' attribute on the declaration is ignored">;
37423752
def warn_attribute_exclude_from_explicit_instantiation_local_class : Warning<
37433753
"%0 attribute ignored on local class%select{| member}1">,
37443754
InGroup<IgnoredAttributes>;

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6606,7 +6606,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
66066606
if (ClassExported && !ClassAttr->isInherited() &&
66076607
TSK == TSK_ExplicitInstantiationDeclaration &&
66086608
!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) {
6609-
Class->dropAttr<DLLExportAttr>();
6609+
if (auto *DEA = Class->getAttr<DLLExportAttr>()) {
6610+
Class->addAttr(DLLExportOnDeclAttr::Create(Context, DEA->getLoc()));
6611+
Class->dropAttr<DLLExportAttr>();
6612+
}
66106613
return;
66116614
}
66126615

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9845,13 +9845,29 @@ DeclResult Sema::ActOnExplicitInstantiation(
98459845
// mode, if a previous declaration of the instantiation was seen.
98469846
for (const ParsedAttr &AL : Attr) {
98479847
if (AL.getKind() == ParsedAttr::AT_DLLExport) {
9848-
Diag(AL.getLoc(),
9849-
diag::warn_attribute_dllexport_explicit_instantiation_def);
9848+
if (PrevDecl->hasAttr<DLLExportAttr>()) {
9849+
Diag(AL.getLoc(), diag::warn_attr_dllexport_explicit_inst_def);
9850+
} else {
9851+
Diag(AL.getLoc(),
9852+
diag::warn_attr_dllexport_explicit_inst_def_mismatch);
9853+
Diag(PrevDecl->getLocation(), diag::note_prev_decl_missing_dllexport);
9854+
}
98509855
break;
98519856
}
98529857
}
98539858
}
98549859

9860+
if (TSK == TSK_ExplicitInstantiationDefinition && PrevDecl &&
9861+
!Context.getTargetInfo().getTriple().isWindowsGNUEnvironment() &&
9862+
llvm::none_of(Attr, [](const ParsedAttr &AL) {
9863+
return AL.getKind() == ParsedAttr::AT_DLLExport;
9864+
})) {
9865+
if (const auto *DEA = PrevDecl->getAttr<DLLExportOnDeclAttr>()) {
9866+
Diag(TemplateLoc, diag::warn_dllexport_on_decl_ignored);
9867+
Diag(DEA->getLoc(), diag::note_dllexport_on_decl);
9868+
}
9869+
}
9870+
98559871
if (CheckExplicitInstantiation(*this, ClassTemplate, TemplateNameLoc,
98569872
SS.isSet(), TSK))
98579873
return true;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify=win32,win32-pedantic -DMS %s -Wdllexport-explicit-instantiation
2+
// RUN: %clang_cc1 -triple x86_64-win32 -fsyntax-only -fms-extensions -verify=win32 -DMS %s -Wno-dllexport-explicit-instantiation
3+
// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify=mingw,mingw-pedantic -DMS %s -Wdllexport-explicit-instantiation
4+
// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify=mingw -DMS %s -Wno-dllexport-explicit-instantiation
5+
6+
template <class>
7+
class S {};
8+
9+
extern template class __declspec(dllexport) S<short>; // win32-pedantic-warning {{explicit instantiation declaration should not be 'dllexport'}} \
10+
win32-pedantic-note {{attribute is here}}
11+
template class __declspec(dllexport) S<short>; // mingw-pedantic-warning {{'dllexport' attribute ignored on explicit instantiation definition}}
12+
13+
extern template class __declspec(dllexport) S<int>; // win32-pedantic-warning {{explicit instantiation declaration should not be 'dllexport'}} \
14+
win32-pedantic-note {{attribute is here}} \
15+
win32-note {{'dllexport' attribute on the declaration is ignored}}
16+
template class S<int>; // win32-warning {{explicit instantiation definition is not exported without 'dllexport'}}
17+
18+
extern template class S<long>; // mingw-note {{'dllexport' attribute is missing on previous declaration}}
19+
template class __declspec(dllexport) S<long>; // mingw-warning {{'dllexport' attribute ignored on explicit instantiation definition}}

clang/test/SemaCXX/dllexport.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ template struct ExplicitlyInstantiatedTemplate<int>;
462462
template <typename T> struct ExplicitlyExportInstantiatedTemplate { void func() {} };
463463
template struct __declspec(dllexport) ExplicitlyExportInstantiatedTemplate<int>;
464464
template <typename T> struct ExplicitlyExportDeclaredInstantiatedTemplate { void func() {} };
465+
#ifdef GNU
466+
// expected-note@+2 {{attribute is missing}}
467+
#endif
465468
extern template struct ExplicitlyExportDeclaredInstantiatedTemplate<int>;
466469
#if not defined(MS) && not defined (WI) && not defined(PS)
467470
// expected-warning@+2{{'dllexport' attribute ignored on explicit instantiation definition}}

0 commit comments

Comments
 (0)