[ms][dll] #27212: Generating of implicit special members should take into account MSVC compatibility version

Clang creates implicit move constructor/assign operator in all cases if
there is std=c++11. But MSVC supports such generation starting from
version 1900 only. As result we have some binary incompatibility.

Differential Revision: http://reviews.llvm.org/D19156

Patch by Andrew V. Tischenko

llvm-svn: 269400
This commit is contained in:
Dmitry Polukhin 2016-05-13 09:03:56 +00:00
parent 7e5e8684fb
commit 41581528a5
2 changed files with 26 additions and 7 deletions

View File

@ -4774,7 +4774,6 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
// The class is either imported or exported.
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
const bool ClassImported = !ClassExported;
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
@ -4809,9 +4808,12 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
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() &&
// 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);
if ((MD->isMoveAssignmentOperator() ||
(CXXC && CXXC->isMoveConstructor())) &&
!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
continue;
}

View File

@ -1,5 +1,9 @@
// 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 | FileCheck --check-prefix=MSC --check-prefix=M32 %s
// RUN: %clang_cc1 -triple x86_64-windows-msvc -emit-llvm -std=c++1y -fno-threadsafe-statics -fms-extensions -O0 -o - %s -w | FileCheck --check-prefix=MSC --check-prefix=M64 %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 %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 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 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
@ -528,6 +532,8 @@ struct SomeTemplate {
SomeTemplate(T o = T()) : o(o) {}
T o;
};
// MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}@$$Q{{.+}}@@Z"
// MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
struct __declspec(dllexport) InheritFromTemplate : SomeTemplate<int> {};
// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
@ -616,7 +622,8 @@ struct __declspec(dllexport) X : public virtual W {};
struct __declspec(dllexport) Y {
// Move assignment operator:
// M32-DAG: define weak_odr dllexport x86_thiscallcc dereferenceable({{[0-9]+}}) %struct.Y* @"\01??4Y@@QAEAAU0@$$QAU0@@Z"
// MSVC2015-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}@$$Q{{.+}}@@Z"
// MSVC2013-DAG: define weak_odr dllexport {{.+}} @"\01??4Y@@Q{{.+}}0@A{{.+}}0@@Z"
int x;
};
@ -947,3 +954,13 @@ struct __declspec(dllexport) LayerTreeImpl {
};
// M32-DAG: define weak_odr dllexport x86_thiscallcc %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QAE@XZ"
// M64-DAG: define weak_odr dllexport %"struct.LayerTreeImpl::ElementLayers"* @"\01??0ElementLayers@LayerTreeImpl@@QEAA@XZ"
class __declspec(dllexport) ACE_Shared_Object {
public:
virtual ~ACE_Shared_Object();
};
class __declspec(dllexport) ACE_Service_Object : public ACE_Shared_Object {};
// Implicit move constructor declaration.
// MSVC2015-DAG: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q
// The declarations should not be exported.
// MSVC2013-NOT: define weak_odr dllexport {{.+}}ACE_Service_Object@@Q{{.+}}@$$Q