diff options
author | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-05-13 09:03:56 +0000 |
---|---|---|
committer | Dmitry Polukhin <dmitry.polukhin@gmail.com> | 2016-05-13 09:03:56 +0000 |
commit | 41581528a51df4bdce376fbbede413afb91f3c04 (patch) | |
tree | 76dbc762d3e7dfd90374d70d7a8e830d2478f8a1 | |
parent | 7e5e8684fb4d65953e388a77491438a5ecc4d2d3 (diff) | |
download | bcm5719-llvm-41581528a51df4bdce376fbbede413afb91f3c04.tar.gz bcm5719-llvm-41581528a51df4bdce376fbbede413afb91f3c04.zip |
[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
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 10 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/dllexport.cpp | 23 |
2 files changed, 26 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e3cca7f8105..96c47e29ef3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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; } diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index c839242e43f..a9759244564 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -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 |