From ae9b07011140037c364e5efa2bb3ff422163d5b5 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 16 Mar 2018 19:40:50 +0000 Subject: [PATCH] [MS] Always use base dtors in place of complete/vbase dtors when possible Summary: Previously we tried too hard to uphold the fiction that destructor variants work like they do on Itanium throughout the ABI-neutral parts of clang. This lead to MS C++ ABI incompatiblities and other bugs. Now, -mconstructor-aliases will no longer control this ABI detail, and clang -cc1's LLVM IR output will be this much closer to the clang driver's. Based on a patch by Zahira Ammarguellat: https://reviews.llvm.org/D39063 I've tried to move the logic that Zahira added into MicrosoftCXXABI.cpp. There is only one ABI-specific detail sticking out, and that is in CodeGenModule::getAddrOfCXXStructor, where we collapse complete dtors to base dtors in the MS ABI. This fixes PR32990. Reviewers: erichkeane, zahiraam, majnemer, rjmccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D44505 llvm-svn: 327732 --- clang/lib/CodeGen/CGCXX.cpp | 5 ++ clang/lib/CodeGen/CGCXXABI.cpp | 14 ++++ clang/lib/CodeGen/CGCXXABI.h | 8 +++ clang/lib/CodeGen/CodeGenModule.cpp | 18 ++--- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 79 ++++++++++++++++++---- clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp | 4 +- .../test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp | 6 +- clang/test/CodeGenCXX/dllexport-dtor-thunks.cpp | 2 +- clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp | 6 +- clang/test/CodeGenCXX/exceptions-cxx-new.cpp | 4 +- clang/test/CodeGenCXX/inheriting-constructor.cpp | 16 ++--- .../test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp | 2 +- clang/test/CodeGenCXX/microsoft-abi-methods.cpp | 6 +- clang/test/CodeGenCXX/regcall.cpp | 4 +- clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp | 2 +- clang/test/CodeGenCoroutines/coro-promise-dtor.cpp | 2 +- .../CodeGenCoroutines/coro-unhandled-exception.cpp | 2 +- 17 files changed, 124 insertions(+), 56 deletions(-) diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 738c635..dfae7d5 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -242,6 +242,11 @@ llvm::Constant *CodeGenModule::getAddrOfCXXStructor( if (auto *CD = dyn_cast(MD)) { GD = GlobalDecl(CD, toCXXCtorType(Type)); } else { + // Always alias equivalent complete destructors to base destructors in the + // MS ABI. + if (getTarget().getCXXABI().isMicrosoft() && + Type == StructorType::Complete && MD->getParent()->getNumVBases() == 0) + Type = StructorType::Base; GD = GlobalDecl(cast(MD), toCXXDtorType(Type)); } diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index a27c3e9..0611749 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -287,6 +287,20 @@ CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF, return nullptr; } +void CGCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, + const CXXDestructorDecl *Dtor, + CXXDtorType DT) const { + // Assume the base C++ ABI has no special rules for destructor variants. + CGM.setDLLImportDLLExport(GV, Dtor); +} + +llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( + GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { + // Delegate back to CGM by default. + return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, + /*isConstantVariable=*/false); +} + bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { return false; } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 65a4c3d..1e4e132 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -319,6 +319,14 @@ public: virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor, CXXDtorType DT) const = 0; + virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, + const CXXDestructorDecl *Dtor, + CXXDtorType DT) const; + + virtual llvm::GlobalValue::LinkageTypes + getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, + CXXDtorType DT) const; + /// Emit destructor variants required by this ABI. virtual void EmitCXXDestructors(const CXXDestructorDecl *D) = 0; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 3c503eb..cb1bfc14 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -786,12 +786,10 @@ void CodeGenModule::setDSOLocal(llvm::GlobalValue *GV) const { void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl GD) const { const auto *D = dyn_cast(GD.getDecl()); + // C++ destructors have a few C++ ABI specific special cases. if (const auto *Dtor = dyn_cast_or_null(D)) { - if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) { - // Don't dllexport/import destructor thunks. - GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - return; - } + getCXXABI().setCXXDestructorDLLStorage(GV, Dtor, GD.getDtorType()); + return; } setDLLImportDLLExport(GV, D); } @@ -1074,14 +1072,8 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); - if (isa(D) && - getCXXABI().useThunkForDtorVariant(cast(D), - GD.getDtorType())) { - // Destructor variants in the Microsoft C++ ABI are always internal or - // linkonce_odr thunks emitted on an as-needed basis. - return Linkage == GVA_Internal ? llvm::GlobalValue::InternalLinkage - : llvm::GlobalValue::LinkOnceODRLinkage; - } + if (const auto *Dtor = dyn_cast(D)) + return getCXXABI().getCXXDestructorLinkage(Linkage, Dtor, GD.getDtorType()); if (isa(D) && cast(D)->isInheritingConstructor() && diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index d48dfbf..221ee76 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -216,6 +216,14 @@ public: return DT != Dtor_Base; } + void setCXXDestructorDLLStorage(llvm::GlobalValue *GV, + const CXXDestructorDecl *Dtor, + CXXDtorType DT) const override; + + llvm::GlobalValue::LinkageTypes + getCXXDestructorLinkage(GVALinkage Linkage, const CXXDestructorDecl *Dtor, + CXXDtorType DT) const override; + void EmitCXXDestructors(const CXXDestructorDecl *D) override; const CXXRecordDecl * @@ -1310,6 +1318,52 @@ MicrosoftCXXABI::buildStructorSignature(const CXXMethodDecl *MD, StructorType T, return Added; } +void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, + const CXXDestructorDecl *Dtor, + CXXDtorType DT) const { + // Deleting destructor variants are never imported or exported. Give them the + // default storage class. + if (DT == Dtor_Deleting) { + GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); + } else { + const NamedDecl *ND = Dtor; + CGM.setDLLImportDLLExport(GV, ND); + } +} + +llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( + GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { + // Internal things are always internal, regardless of attributes. After this, + // we know the thunk is externally visible. + if (Linkage == GVA_Internal) + return llvm::GlobalValue::InternalLinkage; + + switch (DT) { + case Dtor_Base: + // The base destructor most closely tracks the user-declared constructor, so + // we delegate back to the normal declarator case. + return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, + /*isConstantVariable=*/false); + case Dtor_Complete: + // The complete destructor is like an inline function, but it may be + // imported and therefore must be exported as well. This requires changing + // the linkage if a DLL attribute is present. + if (Dtor->hasAttr()) + return llvm::GlobalValue::WeakODRLinkage; + if (Dtor->hasAttr()) + return llvm::GlobalValue::AvailableExternallyLinkage; + return llvm::GlobalValue::LinkOnceODRLinkage; + case Dtor_Deleting: + // Deleting destructors are like inline functions. They have vague linkage + // and are emitted everywhere they are used. They are internal if the class + // is internal. + return llvm::GlobalValue::LinkOnceODRLinkage; + case Dtor_Comdat: + llvm_unreachable("MS C++ ABI does not support comdat dtors"); + } + llvm_unreachable("invalid dtor type"); +} + void MicrosoftCXXABI::EmitCXXDestructors(const CXXDestructorDecl *D) { // The TU defining a dtor is only guaranteed to emit a base destructor. All // other destructor variants are delegating thunks. @@ -1549,6 +1603,12 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, Address This) { + // Use the base destructor variant in place of the complete destructor variant + // if the class has no virtual bases. This effectively implements some of the + // -mconstructor-aliases optimization, but as part of the MS C++ ABI. + if (Type == Dtor_Complete && DD->getParent()->getNumVBases() == 0) + Type = Dtor_Base; + CGCallee Callee = CGCallee::forDirect( CGM.getAddrOfCXXStructor(DD, getFromDtorType(Type)), DD); @@ -3821,19 +3881,12 @@ static void emitCXXConstructor(CodeGenModule &CGM, static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor, StructorType dtorType) { - // The complete destructor is equivalent to the base destructor for - // classes with no virtual bases, so try to emit it as an alias. - if (!dtor->getParent()->getNumVBases() && - (dtorType == StructorType::Complete || dtorType == StructorType::Base)) { - bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias( - GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base)); - if (ProducedAlias) { - if (dtorType == StructorType::Complete) - return; - if (dtor->isVirtual()) - CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete)); - } - } + // Emit the base destructor if the base and complete (vbase) destructors are + // equivalent. This effectively implements -mconstructor-aliases as part of + // the ABI. + if (dtorType == StructorType::Complete && + dtor->getParent()->getNumVBases() == 0) + dtorType = StructorType::Base; // The base destructor is equivalent to the base destructor of its // base class if there is exactly one non-virtual base class with a diff --git a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp index 9c6db1b..9e37eee 100644 --- a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp +++ b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -128,7 +128,7 @@ H::~H() { call_in_dtor(); } // CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"\01??_DH@@QEAAXXZ"( +// CHECK-MSABI: call void @"\01??1H@@UEAA@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } @@ -155,7 +155,7 @@ I::~I() { call_in_dtor(); } // CHECK-MSABI: call void @"\01??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32) // CHECK-MSABI: br label %[[RETURN:.*]] // -// CHECK-MSABI: call void @"\01??_DI@@QEAAXXZ"( +// CHECK-MSABI: call void @"\01??1I@@UEAA@XZ"( // CHECK-MSABI: br label %[[RETURN]] // // CHECK-MSABI: } diff --git a/clang/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp b/clang/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp index f876267..e05b51d 100644 --- a/clang/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp +++ b/clang/test/CodeGenCXX/debug-info-ms-dtor-thunks.cpp @@ -5,10 +5,10 @@ struct __declspec(dllexport) T { virtual ~T(); }; struct __declspec(dllexport) U : S, T { virtual ~U(); }; // CHECK-LABEL: define {{.*}} @"\01??_GS@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DS@@QAEXXZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK: call x86_thiscallcc void @"\01??1S@@UAE@XZ"(%struct.S* %this1){{.*}}!dbg !{{[0-9]+}} // CHECK-LABEL: define {{.*}} @"\01??_GT@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DT@@QAEXXZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK: call x86_thiscallcc void @"\01??1T@@UAE@XZ"(%struct.T* %this1){{.*}}!dbg !{{[0-9]+}} // CHECK-LABEL: define {{.*}} @"\01??_GU@@UAEPAXI@Z" -// CHECK: call x86_thiscallcc void @"\01??_DU@@QAEXXZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}} +// CHECK: call x86_thiscallcc void @"\01??1U@@UAE@XZ"(%struct.U* %this1){{.*}}!dbg !{{[0-9]+}} diff --git a/clang/test/CodeGenCXX/dllexport-dtor-thunks.cpp b/clang/test/CodeGenCXX/dllexport-dtor-thunks.cpp index 45cce8b..935dfa5 100644 --- a/clang/test/CodeGenCXX/dllexport-dtor-thunks.cpp +++ b/clang/test/CodeGenCXX/dllexport-dtor-thunks.cpp @@ -5,6 +5,6 @@ struct __declspec(dllexport) B { virtual ~B(); }; struct __declspec(dllexport) C : A, B { virtual ~C(); }; C::~C() {} +// CHECK: define dso_local dllexport void @"\01??1C@@UEAA@XZ" // This thunk should *not* be dllexport. // CHECK: define linkonce_odr dso_local i8* @"\01??_EC@@W7EAAPEAXI@Z" -// CHECK: define dso_local dllexport void @"\01??1C@@UEAA@XZ" diff --git a/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp b/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp index a1ff34c..99dd405 100644 --- a/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp +++ b/clang/test/CodeGenCXX/dllimport-dtor-thunks.cpp @@ -1,9 +1,5 @@ // RUN: %clang_cc1 -mconstructor-aliases %s -triple x86_64-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s -// FIXME: We should really consider removing -mconstructor-aliases for MS C++ -// ABI. The risk of bugs introducing ABI incompatibility under -// -mno-constructor-aliases is too high. - // PR32990 // Introduces the virtual destructor. We should use the base destructor @@ -44,6 +40,6 @@ extern "C" void testit() { // CHECK: call void @"\01??1ImportOverrideVDtor@@UEAA@XZ"(%struct.ImportOverrideVDtor* %{{.*}}) // CHECK: call void @"\01??1ImportIntroVDtor@@UEAA@XZ"(%struct.ImportIntroVDtor* %{{.*}}) -// CHECK-LABEL: define linkonce_odr dso_local void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" +// CHECK-LABEL: declare dllimport void @"\01??_DImportVBaseOverrideVDtor@@QEAAXXZ" // CHECK-LABEL: declare dllimport void @"\01??1ImportOverrideVDtor@@UEAA@XZ" // CHECK-LABEL: declare dllimport void @"\01??1ImportIntroVDtor@@UEAA@XZ" diff --git a/clang/test/CodeGenCXX/exceptions-cxx-new.cpp b/clang/test/CodeGenCXX/exceptions-cxx-new.cpp index 3a8ce7d5..bc65953 100644 --- a/clang/test/CodeGenCXX/exceptions-cxx-new.cpp +++ b/clang/test/CodeGenCXX/exceptions-cxx-new.cpp @@ -55,12 +55,12 @@ void test_cleanup() { // CHECK: to label %[[LEAVE_FUNC:.*]] unwind label %[[CLEANUP:.*]] // CHECK: [[LEAVE_FUNC]] -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"( +// CHECK: call x86_thiscallcc void @"\01??1Cleanup@@QAE@XZ"( // CHECK: ret void // CHECK: [[CLEANUP]] // CHECK: %[[CLEANUPPAD:.*]] = cleanuppad within none [] -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@@QAEXXZ"( +// CHECK: call x86_thiscallcc void @"\01??1Cleanup@@QAE@XZ"( // CHECK: cleanupret from %[[CLEANUPPAD]] unwind to caller diff --git a/clang/test/CodeGenCXX/inheriting-constructor.cpp b/clang/test/CodeGenCXX/inheriting-constructor.cpp index 1be59b9..5a3f5ab 100644 --- a/clang/test/CodeGenCXX/inheriting-constructor.cpp +++ b/clang/test/CodeGenCXX/inheriting-constructor.cpp @@ -137,7 +137,7 @@ namespace inalloca_nonvirt { // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( + // WIN32: call {{.*}} @"\01??1Q@@QAE@XZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -150,7 +150,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??1Q@@QEAA@XZ"({{.*}}* %[[TMP]]) struct C : B { using B::B; }; C c(1, 2, 3, 4); @@ -173,7 +173,7 @@ namespace inalloca_nonvirt { // WIN32: call {{.*}} @"\01??0A@inalloca_nonvirt@@QAE@UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]]) // WIN32: call void @llvm.stackrestore( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( + // WIN32: call {{.*}} @"\01??1Q@@QAE@XZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -186,7 +186,7 @@ namespace inalloca_nonvirt { // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0A@inalloca_nonvirt@@QEAA@UQ@@H0$$QEAU2@@Z"(%{{.*}}, %{{.*}}* %[[ARG1]], i32 2, %{{.*}}* %[[ARG3]], %{{.*}} %[[TMP]]) // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??1Q@@QEAA@XZ"({{.*}}* %[[TMP]]) } namespace inalloca_virt { @@ -224,7 +224,7 @@ namespace inalloca_virt { // destroy the parameters, but that's not actually possible. // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( + // WIN32: call {{.*}} @"\01??1Q@@QAE@XZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -239,7 +239,7 @@ namespace inalloca_virt { // WIN64: br // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??1Q@@QEAA@XZ"({{.*}}* %[[TMP]]) struct C : B { using B::B; }; C c(1, 2, 3, 4); @@ -281,7 +281,7 @@ namespace inalloca_virt { // // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( // WIN32: call {{.*}} @"\01??0Z@@QAE@XZ"( - // WIN32: call {{.*}} @"\01??_DQ@@QAEXXZ"( + // WIN32: call {{.*}} @"\01??1Q@@QAE@XZ"( // On Win64, the Q arguments would be destroyed in the callee. We don't yet // support that in the non-inlined case, so we force inlining. @@ -301,7 +301,7 @@ namespace inalloca_virt { // WIN64: br // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( // WIN64: call {{.*}} @"\01??0Z@@QEAA@XZ"( - // WIN64: call void @"\01??_DQ@@QEAAXXZ"({{.*}}* %[[TMP]]) + // WIN64: call void @"\01??1Q@@QEAA@XZ"({{.*}}* %[[TMP]]) } namespace inline_nonvirt { diff --git a/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index 07356e4..0ab6f1c 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -138,6 +138,6 @@ S3 *f(S2 &s) { // CHECK: [[CALL:%.*]] = invoke i8* @__RTDynamicCast // CHECK: [[BC:%.*]] = bitcast i8* [[CALL]] to %"struct.PR25606::S3"* -// CHECK: call x86_thiscallcc void @"\01??_DCleanup@PR25606@@QAEXXZ"( +// CHECK: call x86_thiscallcc void @"\01??1Cleanup@PR25606@@QAE@XZ"( // CHECK: ret %"struct.PR25606::S3"* [[BC]] } diff --git a/clang/test/CodeGenCXX/microsoft-abi-methods.cpp b/clang/test/CodeGenCXX/microsoft-abi-methods.cpp index 6dbbf45..7348eeb 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-methods.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-methods.cpp @@ -75,15 +75,15 @@ void constructors() { // CHECK: %{{[.0-9A-Z_a-z]+}} = call x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ" // CHECK: ret -// Make sure that the Base constructor definition uses the right CC: -// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ" - // Make sure that the Base destructor call in the Child denstructor uses // the right calling convention: // CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??1Child@@QAE@XZ" // CHECK: call x86_thiscallcc void @"\01??1Base@@QAE@XZ" // CHECK: ret +// Make sure that the Base constructor definition uses the right CC: +// CHECK: define linkonce_odr dso_local x86_thiscallcc %class.Base* @"\01??0Base@@QAE@XZ" + // Make sure that the Base destructor definition uses the right CC: // CHECK: define linkonce_odr dso_local x86_thiscallcc void @"\01??1Base@@QAE@XZ" } diff --git a/clang/test/CodeGenCXX/regcall.cpp b/clang/test/CodeGenCXX/regcall.cpp index ea1f878..b7bda1b 100644 --- a/clang/test/CodeGenCXX/regcall.cpp +++ b/clang/test/CodeGenCXX/regcall.cpp @@ -47,8 +47,8 @@ public: // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD2Ev // CHECK-LIN-DAG: define linkonce_odr x86_regcallcc void @_ZN10test_classD1Ev // Windows ignores calling convention on constructor/destructors. - // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"\01??_Dtest_class@@QEAAXXZ" - // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01??_Dtest_class@@QAEXXZ" + // CHECK-WIN64-DAG: define linkonce_odr dso_local void @"\01??1test_class@@QEAA@XZ" + // CHECK-WIN32-DAG: define linkonce_odr dso_local x86_thiscallcc void @"\01??1test_class@@QAE@XZ" test_class& __regcall operator+=(const test_class&){ return *this; diff --git a/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp b/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp index 5a3ecd1..1f21c69 100644 --- a/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp +++ b/clang/test/CodeGenCoroutines/coro-eh-cleanup.cpp @@ -50,7 +50,7 @@ coro_t f() { // CHECK: to label %[[CONT:.+]] unwind label %[[EHCLEANUP:.+]] // CHECK: [[EHCLEANUP]]: // CHECK: %[[INNERPAD:.+]] = cleanuppad within none [] -// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"( +// CHECK: call void @"\01??1Cleanup@@QEAA@XZ"( // CHECK: cleanupret from %{{.+}} unwind label %[[CATCHDISPATCH:.+]] // CHECK: [[CATCHDISPATCH]]: diff --git a/clang/test/CodeGenCoroutines/coro-promise-dtor.cpp b/clang/test/CodeGenCoroutines/coro-promise-dtor.cpp index 5cc4720..53e07ee 100644 --- a/clang/test/CodeGenCoroutines/coro-promise-dtor.cpp +++ b/clang/test/CodeGenCoroutines/coro-promise-dtor.cpp @@ -44,4 +44,4 @@ coro_t f() { // CHECK: br i1 %[[NRVO]], label %{{.+}}, label %[[DTOR:.+]] // CHECK: [[DTOR]]: -// CHECK: call void @"\01??_Dcoro_t@@QEAAXXZ"( +// CHECK: call void @"\01??1coro_t@@QEAA@XZ"( diff --git a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp index e26a518..e0fef07 100644 --- a/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp +++ b/clang/test/CodeGenCoroutines/coro-unhandled-exception.cpp @@ -37,7 +37,7 @@ coro_t f() { // CHECK: to label %{{.+}} unwind label %[[EHCLEANUP:.+]] // CHECK: [[EHCLEANUP]]: // CHECK: %[[INNERPAD:.+]] = cleanuppad within none [] -// CHECK: call void @"\01??_DCleanup@@QEAAXXZ"( +// CHECK: call void @"\01??1Cleanup@@QEAA@XZ"( // CHECK: cleanupret from %[[INNERPAD]] unwind label %[[CATCHSW:.+]] // CHECK: [[CATCHSW]]: // CHECK: %[[CATCHSWTOK:.+]] = catchswitch within none [label %[[CATCH:.+]]] unwind label -- 2.7.4