[clang] d5aaf60 - [windows-itanium] handle dllimport/export code paths separately and share with PS4
Ben Dunbobbin via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 30 06:42:48 PST 2020
Author: Ben Dunbobbin
Date: 2020-11-30T14:36:39Z
New Revision: d5aaf6021476243de73f8eb8a7479a2288582225
URL: https://github.com/llvm/llvm-project/commit/d5aaf6021476243de73f8eb8a7479a2288582225
DIFF: https://github.com/llvm/llvm-project/commit/d5aaf6021476243de73f8eb8a7479a2288582225.diff
LOG: [windows-itanium] handle dllimport/export code paths separately and share with PS4
Similar to Windows Itanium, PS4 is also an Itanium C++ ABI variant
which shares the goal of semantic compatibility with Microsoft C++
code that uses dllimport/export.
This change introduces a new function to determine from the triple
if an environment aims for compatibility with MS C++ code w.r.t to
these attributes and guards the relevant code paths using that
function.
Differential Revision: https://reviews.llvm.org/D90299
Added:
Modified:
clang/include/clang/Basic/TargetInfo.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp
clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
clang/test/CodeGenCXX/windows-itanium-dllexport.cpp
clang/test/Sema/dllimport.c
clang/test/SemaCXX/dllexport.cpp
clang/test/SemaCXX/dllimport.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 698964b94ee2..de91ca2ee82e 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1098,6 +1098,13 @@ class TargetInfo : public virtual TransferrableTargetInfo,
/// either; the entire thing is pretty badly mangled.
virtual bool hasProtectedVisibility() const { return true; }
+ /// Does this target aim for semantic compatibility with
+ /// Microsoft C++ code using dllimport/export attributes?
+ virtual bool shouldDLLImportComdatSymbols() const {
+ return getTriple().isWindowsMSVCEnvironment() ||
+ getTriple().isWindowsItaniumEnvironment() || getTriple().isPS4CPU();
+ }
+
/// An optional hook that targets can implement to perform semantic
/// checking on attribute((section("foo"))) specifiers.
///
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ce7475b0d5da..9c282a73e0ed 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6510,9 +6510,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
// special MSVC extension: in the last case, the declaration is treated as if
// it were marked dllexport.
bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
- bool IsMicrosoft =
- S.Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment();
+ bool IsMicrosoftABI = S.Context.getTargetInfo().shouldDLLImportComdatSymbols();
if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) {
// Ignore static data because out-of-line definitions are diagnosed
// separately.
@@ -6526,9 +6524,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
}
if (OldImportAttr && !HasNewAttr &&
- (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember &&
+ (!IsInline || (IsMicrosoftABI && IsTemplate)) && !IsStaticDataMember &&
!NewDecl->isLocalExternDecl() && !IsQualifiedFriend) {
- if (IsMicrosoft && IsDefinition) {
+ if (IsMicrosoftABI && IsDefinition) {
S.Diag(NewDecl->getLocation(),
diag::warn_redeclaration_without_import_attribute)
<< NewDecl;
@@ -6545,7 +6543,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
OldDecl->dropAttr<DLLImportAttr>();
NewDecl->dropAttr<DLLImportAttr>();
}
- } else if (IsInline && OldImportAttr && !IsMicrosoft) {
+ } else if (IsInline && OldImportAttr && !IsMicrosoftABI) {
// In MinGW, seeing a function declared inline drops the dllimport
// attribute.
OldDecl->dropAttr<DLLImportAttr>();
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a14c16229419..d31d18eac474 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6791,16 +6791,14 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D,
static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
if (isa<ClassTemplatePartialSpecializationDecl>(D) &&
- (S.Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
+ (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A;
return;
}
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport &&
- !(S.Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
+ !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) {
// MinGW doesn't allow dllimport on inline functions.
S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline)
<< A;
@@ -6809,8 +6807,7 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) {
}
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
- if ((S.Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
+ if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) &&
MD->getParent()->isLambda()) {
S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A;
return;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9d2090dfd8eb..593f4a937c79 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -6092,8 +6092,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
- if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr) {
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
@@ -6113,8 +6112,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
return;
}
- if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
+ if (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
@@ -6179,8 +6177,7 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
if (MD->isInlined()) {
// MinGW does not import or export inline methods. But do it for
// template instantiations.
- if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() &&
+ if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition)
continue;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index bd38e6404b60..5b321bb74400 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -9759,11 +9759,11 @@ DeclResult Sema::ActOnExplicitInstantiation(
Def->setTemplateSpecializationKind(TSK);
if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
- (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
- // In the MS ABI, an explicit instantiation definition can add a dll
- // attribute to a template with a previous instantiation declaration.
- // MinGW doesn't allow this.
+ (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
+ !Context.getTargetInfo().getTriple().isPS4CPU())) {
+ // An explicit instantiation definition can add a dll attribute to a
+ // template with a previous instantiation declaration. MinGW doesn't
+ // allow this.
auto *A = cast<InheritableAttr>(
getDLLAttr(Specialization)->clone(getASTContext()));
A->setInherited(true);
@@ -9777,19 +9777,19 @@ DeclResult Sema::ActOnExplicitInstantiation(
bool NewlyDLLExported =
!PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported &&
- (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
- // In the MS ABI, an explicit instantiation definition can add a dll
- // attribute to a template with a previous implicit instantiation.
- // MinGW doesn't allow this. We limit clang to only adding dllexport, to
- // avoid potentially strange codegen behavior. For example, if we extend
- // this conditional to dllimport, and we have a source file calling a
- // method on an implicitly instantiated template class instance and then
- // declaring a dllimport explicit instantiation definition for the same
- // template class, the codegen for the method call will not respect the
- // dllimport, while it will with cl. The Def will already have the DLL
- // attribute, since the Def and Specialization will be the same in the
- // case of Old_TSK == TSK_ImplicitInstantiation, and we already added the
+ (Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
+ !Context.getTargetInfo().getTriple().isPS4CPU())) {
+ // An explicit instantiation definition can add a dll attribute to a
+ // template with a previous implicit instantiation. MinGW doesn't allow
+ // this. We limit clang to only adding dllexport, to avoid potentially
+ // strange codegen behavior. For example, if we extend this conditional
+ // to dllimport, and we have a source file calling a method on an
+ // implicitly instantiated template class instance and then declaring a
+ // dllimport explicit instantiation definition for the same template
+ // class, the codegen for the method call will not respect the dllimport,
+ // while it will with cl. The Def will already have the DLL attribute,
+ // since the Def and Specialization will be the same in the case of
+ // Old_TSK == TSK_ImplicitInstantiation, and we already added the
// attribute to the Specialization; we just need to make it take effect.
assert(Def == Specialization &&
"Def and Specialization should match for implicit instantiation");
diff --git a/clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp b/clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp
index 52947840d8d1..c951ae58c4b7 100644
--- a/clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp
+++ b/clang/test/CodeGenCXX/dllexport-vtable-thunks.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-windows-gnu -fdeclspec -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-windows-itanium -fdeclspec -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -fdeclspec -emit-llvm -o - %s | FileCheck %s -DDSO_ATTRS="dso_local dllexport"
+// RUN: %clang_cc1 -triple x86_64-windows-itanium -fdeclspec -emit-llvm -o - %s | FileCheck %s -DDSO_ATTRS="dso_local dllexport"
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm -o - %s | FileCheck %s -DDSO_ATTRS=dllexport
struct __declspec(dllexport) A {
virtual void m();
@@ -11,7 +12,7 @@ struct __declspec(dllexport) C : A, B {
virtual void m();
};
void C::m() {}
-// CHECK: define dso_local dllexport void @_ZThn8_N1C1mEv
+// CHECK: define [[DSO_ATTRS]] void @_ZThn8_N1C1mEv
struct Base {
virtual void m();
@@ -20,4 +21,4 @@ struct __declspec(dllexport) Derived : virtual Base {
virtual void m();
};
void Derived::m() {}
-// CHECK: define dso_local dllexport void @_ZTv0_n24_N7Derived1mEv
+// CHECK: define [[DSO_ATTRS]] void @_ZTv0_n24_N7Derived1mEv
diff --git a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
index 20ba4bc5d040..726be7355022 100644
--- a/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
+++ b/clang/test/CodeGenCXX/windows-implicit-dllexport-template-specialization.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS
+// RUN: %clang_cc1 -std=c++11 -triple i686-windows -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-MS
// RUN: %clang_cc1 -std=c++11 -triple i686-windows-itanium -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-IA
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -fdeclspec -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-PS4
template <typename>
struct s {};
@@ -16,3 +17,5 @@ template class __declspec(dllexport) t<char>;
// CHECK-IA: dllexport {{.*}} @_ZN1tIcEaSERKS0_
// CHECK-IA: dllexport {{.*}} @_ZN1sIcEaSERKS0_
+// CHECK-PS4-NOT: @_ZN1tIcEaSERKS0_
+// CHECK-PS4-NOT: @_ZN1sIcEaSERKS0_
diff --git a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp
index ff780c777822..6b30369e6835 100644
--- a/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp
+++ b/clang/test/CodeGenCXX/windows-itanium-dllexport.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple i686-windows-itanium -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,WI
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-scei-ps4 -fdeclspec %s -o - | FileCheck %s --check-prefixes=CHECK,PS4
#define JOIN2(x, y) x##y
#define JOIN(x, y) JOIN2(x, y)
@@ -25,14 +26,18 @@ template class __declspec(dllexport) c<int>;
extern template class c<char>;
template class __declspec(dllexport) c<char>;
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
+// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcEaSERKS0_
+// WI: define {{.*}} dllexport {{.*}} @_ZN1cIcE1fEv
+// PS4-NOT: @_ZN1cIcEaSERKS0_
+// PS4: define weak_odr void @_ZN1cIcE1fEv
c<double> g;
template class __declspec(dllexport) c<double>;
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_
-// CHECK: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
+// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdEaSERKS0_
+// WI: define {{.*}} dllexport {{.*}} @_ZN1cIdE1fEv
+// PS4-NOT: @_ZN1cIdEaSERKS0_
+// PS4: define weak_odr void @_ZN1cIdE1fEv
template <class T>
struct outer {
@@ -51,5 +56,6 @@ extern template class __declspec(dllimport) outer<char>;
USEMEMFUNC(outer<char>, f)
USEMEMFUNC(outer<char>::inner, f)
-// CHECK: declare dllimport {{.*}} @_ZN5outerIcE1fEv
-// CHECK: define {{.*}} @_ZN5outerIcE5inner1fEv
+// CHECK-DAG: declare dllimport {{.*}} @_ZN5outerIcE1fEv
+// WI-DAG: define {{.*}} @_ZN5outerIcE5inner1fEv
+// PS4-DAG: declare {{.*}} @_ZN5outerIcE5inner1fEv
diff --git a/clang/test/Sema/dllimport.c b/clang/test/Sema/dllimport.c
index 66bd2703e648..464623235b88 100644
--- a/clang/test/Sema/dllimport.c
+++ b/clang/test/Sema/dllimport.c
@@ -5,6 +5,8 @@
// RUN: %clang_cc1 -triple aarch64-win32 -fsyntax-only -fms-extensions -verify -std=c99 -DMS %s
// RUN: %clang_cc1 -triple i686-windows-itanium -fsyntax-only -fms-extensions -verify -std=c99 -DWI %s
// RUN: %clang_cc1 -triple x86_64-windows-itanium -fsyntax-only -fms-extensions -verify -std=c11 -DWI %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fsyntax-only -fms-extensions -verify -std=c11 -DWI %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fsyntax-only -fms-extensions -verify -std=c99 -DWI %s
// Invalid usage.
__declspec(dllimport) typedef int typedef1;
diff --git a/clang/test/SemaCXX/dllexport.cpp b/clang/test/SemaCXX/dllexport.cpp
index 820992212d9b..97ce9de86d7e 100644
--- a/clang/test/SemaCXX/dllexport.cpp
+++ b/clang/test/SemaCXX/dllexport.cpp
@@ -4,6 +4,7 @@
// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template %s
// RUN: %clang_cc1 -triple i686-windows-itanium -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template -DWI %s
// RUN: %clang_cc1 -triple x86_64-windows-itanium -fsyntax-only -fms-extensions -verify -std=c++1y -Wunsupported-dll-base-class-template -DWI %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fsyntax-only -fdeclspec -verify -std=c++1y -Wunsupported-dll-base-class-template -DWI %s
// Helper structs to make templates more expressive.
struct ImplicitInst_Exported {};
diff --git a/clang/test/SemaCXX/dllimport.cpp b/clang/test/SemaCXX/dllimport.cpp
index f0c77904b618..77929430d91b 100644
--- a/clang/test/SemaCXX/dllimport.cpp
+++ b/clang/test/SemaCXX/dllimport.cpp
@@ -5,6 +5,8 @@
// RUN: %clang_cc1 -triple x86_64-mingw32 -fsyntax-only -fms-extensions -verify -std=c++17 -Wunsupported-dll-base-class-template -DGNU %s
// RUN: %clang_cc1 -triple i686-windows-itanium -fsyntax-only -fms-extensions -verify -std=c++11 -Wunsupported-dll-base-class-template -DWI %s
// RUN: %clang_cc1 -triple x86_64-windows-itanium -fsyntax-only -fms-extensions -verify -std=c++17 -Wunsupported-dll-base-class-template -DWI %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fsyntax-only -fdeclspec -verify -std=c++11 -Wunsupported-dll-base-class-template -DWI %s
+// RUN: %clang_cc1 -triple x86_64-scei-ps4 -fsyntax-only -fdeclspec -verify -std=c++17 -Wunsupported-dll-base-class-template -DWI %s
// Helper structs to make templates more expressive.
struct ImplicitInst_Imported {};
More information about the cfe-commits
mailing list