r270535 - [MSVC2015] dllexport for defaulted special class members
Dmitry Polukhin via cfe-commits
cfe-commits at lists.llvm.org
Mon May 23 23:37:16 PDT 2016
Author: dpolukhin
Date: Tue May 24 01:37:14 2016
New Revision: 270535
URL: http://llvm.org/viewvc/llvm-project?rev=270535&view=rev
Log:
[MSVC2015] dllexport for defaulted special class members
Clang doesn't dllexport defaulted special member function defaulted
inside class but does it if they defaulted outside class. MSVC doesn't
make any distinction where they were defaulted. Also MSVC 2013 and 2015
export different set of members. MSVC2015 doesn't emit trivial defaulted
x-tors but does emit copy assign operator.
Differential revision: http://reviews.llvm.org/D20422
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
cfe/trunk/test/CodeGenCXX/dllexport.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=270535&r1=270534&r2=270535&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue May 24 01:37:14 2016
@@ -4811,11 +4811,17 @@ void Sema::checkClassLevelDLLAttribute(C
// MSVC versions before 2015 don't export the move assignment operators
// and move constructor, so don't attempt to import/export them if
// we have a definition.
- auto *CXXC = dyn_cast<CXXConstructorDecl>(MD);
+ auto *Ctor = dyn_cast<CXXConstructorDecl>(MD);
if ((MD->isMoveAssignmentOperator() ||
- (CXXC && CXXC->isMoveConstructor())) &&
+ (Ctor && Ctor->isMoveConstructor())) &&
!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
continue;
+
+ // MSVC2015 doesn't export trivial defaulted x-tor but copy assign
+ // operator is exported anyway.
+ if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
+ (Ctor || isa<CXXDestructorDecl>(MD)) && MD->isTrivial())
+ continue;
}
}
@@ -4889,6 +4895,33 @@ void Sema::propagateDLLAttrToBaseClassTe
}
}
+static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
+ SourceLocation DefaultLoc) {
+ switch (S.getSpecialMember(MD)) {
+ case Sema::CXXDefaultConstructor:
+ S.DefineImplicitDefaultConstructor(DefaultLoc,
+ cast<CXXConstructorDecl>(MD));
+ break;
+ case Sema::CXXCopyConstructor:
+ S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
+ break;
+ case Sema::CXXCopyAssignment:
+ S.DefineImplicitCopyAssignment(DefaultLoc, MD);
+ break;
+ case Sema::CXXDestructor:
+ S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
+ break;
+ case Sema::CXXMoveConstructor:
+ S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
+ break;
+ case Sema::CXXMoveAssignment:
+ S.DefineImplicitMoveAssignment(DefaultLoc, MD);
+ break;
+ case Sema::CXXInvalid:
+ llvm_unreachable("Invalid special member.");
+ }
+}
+
/// \brief Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
@@ -4984,8 +5017,8 @@ void Sema::CheckCompletedCXXClass(CXXRec
// For an explicitly defaulted or deleted special member, we defer
// determining triviality until the class is complete. That time is now!
+ CXXSpecialMember CSM = getSpecialMember(M);
if (!M->isImplicit() && !M->isUserProvided()) {
- CXXSpecialMember CSM = getSpecialMember(M);
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
@@ -4993,6 +5026,20 @@ void Sema::CheckCompletedCXXClass(CXXRec
Record->finishedDefaultedOrDeletedMember(M);
}
}
+
+ if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
+ M->hasAttr<DLLExportAttr>()) {
+ if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
+ M->isTrivial() &&
+ (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor ||
+ CSM == CXXDestructor))
+ M->dropAttr<DLLExportAttr>();
+
+ if (M->hasAttr<DLLExportAttr>()) {
+ DefineImplicitSpecialMember(*this, M, M->getLocation());
+ ActOnFinishInlineFunctionDef(M);
+ }
+ }
}
}
@@ -13063,32 +13110,8 @@ void Sema::SetDeclDefaulted(Decl *Dcl, S
CheckExplicitlyDefaultedSpecialMember(MD);
- if (MD->isInvalidDecl())
- return;
-
- switch (Member) {
- case CXXDefaultConstructor:
- DefineImplicitDefaultConstructor(DefaultLoc,
- cast<CXXConstructorDecl>(MD));
- break;
- case CXXCopyConstructor:
- DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
- break;
- case CXXCopyAssignment:
- DefineImplicitCopyAssignment(DefaultLoc, MD);
- break;
- case CXXDestructor:
- DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
- break;
- case CXXMoveConstructor:
- DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
- break;
- case CXXMoveAssignment:
- DefineImplicitMoveAssignment(DefaultLoc, MD);
- break;
- case CXXInvalid:
- llvm_unreachable("Invalid special member.");
- }
+ if (!MD->isInvalidDecl())
+ DefineImplicitSpecialMember(*this, MD, DefaultLoc);
} else {
Diag(DefaultLoc, diag::err_default_special_members);
}
Modified: cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport-members.cpp?rev=270535&r1=270534&r2=270535&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport-members.cpp Tue May 24 01:37:14 2016
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -fms-compatibility-version=18 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M32 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -fms-compatibility-version=18 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=MSC --check-prefix=M64 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -fms-compatibility -fms-compatibility-version=19 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=M32VS2015 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-compatibility -fms-compatibility-version=19 -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=M64VS2015 %s
// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G32 %s
// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s | FileCheck --check-prefix=GNU --check-prefix=G64 %s
@@ -427,6 +429,32 @@ __declspec(dllexport) ExportDefaultedDef
ExportDefaultedDefs& ExportDefaultedDefs::operator=(ExportDefaultedDefs&&) = default;
+// Export defaulted member function definitions declared inside class.
+struct ExportDefaultedInclassDefs {
+ __declspec(dllexport) ExportDefaultedInclassDefs() = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+
+ __declspec(dllexport) ~ExportDefaultedInclassDefs() = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+
+ __declspec(dllexport) ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+
+ __declspec(dllexport) ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0 at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0 at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+};
+
+
// Export allocation functions.
struct ExportAlloc {
__declspec(dllexport) void* operator new(__SIZE_TYPE__);
Modified: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=270535&r1=270534&r2=270535&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Tue May 24 01:37:14 2016
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 %s
-// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2015 -check-prefix=M32MSVC2015 %s
+// RUN: %clang_cc1 -triple i686-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O1 -mconstructor-aliases -disable-llvm-optzns -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M32 -check-prefix=MSVC2013 -check-prefix=M32MSVC2013 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 %s
-// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=19.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2015 -check-prefix=M64MSVC2015 %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w -fms-compatibility-version=18.00 | FileCheck --check-prefix=MSC --check-prefix=M64 -check-prefix=MSVC2013 -check-prefix=M64MSVC2013 %s
// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G32 %s
// RUN: %clang_cc1 -triple x86_64-windows-gnu -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=GNU --check-prefix=G64 %s
@@ -561,7 +561,7 @@ struct __declspec(dllexport) T {
// Explicitly defaulted copy constructur:
T(const T&) = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE at ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.T* @"\01??0T@@QAE at ABU0@@Z"
void a() {}
// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a at T@@QAEXXZ"
@@ -647,9 +647,34 @@ namespace UseDtorAlias {
struct __declspec(dllexport) DefaultedCtorsDtors {
DefaultedCtorsDtors() = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE at XZ"
+ // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.DefaultedCtorsDtors* @"\01??0DefaultedCtorsDtors@@QAE at XZ"
~DefaultedCtorsDtors() = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE at XZ"
+ // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1DefaultedCtorsDtors@@QAE at XZ"
+};
+
+// Export defaulted member function definitions declared inside class.
+struct __declspec(dllexport) ExportDefaultedInclassDefs {
+ ExportDefaultedInclassDefs() = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+ // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* returned %this)
+
+ ~ExportDefaultedInclassDefs() = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2013-DAG: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc void @"\01??1ExportDefaultedInclassDefs@@QAE at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+ // M64VS2015-NOT: define weak_odr dllexport void @"\01??1ExportDefaultedInclassDefs@@QEAA at XZ"(%struct.ExportDefaultedInclassDefs* %this)
+
+ ExportDefaultedInclassDefs(const ExportDefaultedInclassDefs&) = default;
+ // M32VS2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2013-DAG: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M32VS2015-NOT: define weak_odr dllexport x86_thiscallcc %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QAE at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64VS2015-NOT: define weak_odr dllexport %struct.ExportDefaultedInclassDefs* @"\01??0ExportDefaultedInclassDefs@@QEAA at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* returned %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+
+ ExportDefaultedInclassDefs& operator=(const ExportDefaultedInclassDefs&) = default;
+ // M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QAEAAU0 at ABU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
+ // M64-DAG: define weak_odr dllexport dereferenceable({{[0-9]+}}) %struct.ExportDefaultedInclassDefs* @"\01??4ExportDefaultedInclassDefs@@QEAAAEAU0 at AEBU0@@Z"(%struct.ExportDefaultedInclassDefs* %this, %struct.ExportDefaultedInclassDefs* dereferenceable({{[0-9]+}}))
};
namespace ReferencedInlineMethodInNestedClass {
@@ -721,7 +746,7 @@ template <typename T> struct ExplicitIns
// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers at X@@QAE at XZ"
ExplicitInstConstexprMembers(const ExplicitInstConstexprMembers&) = default;
- // M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers at X@@QAE at ABU0@@Z"
+ // M32MSVC2013-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstConstexprMembers* @"\01??0?$ExplicitInstConstexprMembers at X@@QAE at ABU0@@Z"
constexpr int f() const { return 42; }
// M32-DAG: define weak_odr dllexport x86_thiscallcc i32 @"\01?f@?$ExplicitInstConstexprMembers at X@@QBEHXZ"
More information about the cfe-commits
mailing list