https://github.com/Fznamznon created https://github.com/llvm/llvm-project/pull/135611
Finding operator delete[] is still problematic, without it the extension is a security hazard, so reverting until the problem with operator delete[] is figured out. >From 460d4807104c925232def63b516853f9ee22e428 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 14 Apr 2025 02:41:48 -0700 Subject: [PATCH 1/5] Revert "[MS][clang] Error about ambiguous operator delete[] only when required (#135041)" This reverts commit 2b3aa56fd742775c5b05c3053778832aa76c0feb. --- clang/lib/Sema/SemaDeclCXX.cpp | 26 +++++++------------ clang/lib/Sema/SemaExprCXX.cpp | 18 ++------------ clang/test/SemaCXX/gh134265.cpp | 44 +++------------------------------ 3 files changed, 14 insertions(+), 74 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e4f09ca60d7d8..2dc10d4ded48a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11097,23 +11097,15 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - // Lookup delete[] too in case we have to emit a vector deleting dtor; - DeclarationName VDeleteName = - Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); - // Diagnose if there is no available operator delete[] found and the - // destructor is exported. Vector deleting dtor body emission requires - // operator delete[] to be present. Whenever the destructor is exported, - // we just always emit vector deleting dtor body, because we don't know - // if new[] will be used with the type outside of the library. Otherwise - // when the dtor is not exported then new[]/delete[] in the TU will make - // sure the operator is referenced and its uses diagnosed. - bool Diagnose = - Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined(); - FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor( - Loc, RD, VDeleteName, Diagnose); - Destructor->setOperatorArrayDelete(ArrOperatorDelete); - } + // Lookup delete[] too in case we have to emit a vector deleting dtor; + DeclarationName VDeleteName = + Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); + FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor( + Loc, RD, VDeleteName, /*Diagnose=*/false); + // delete[] in the TU will make sure the operator is referenced and its + // uses diagnosed, otherwise vector deleting dtor won't be called anyway, + // so just record it in the destructor. + Destructor->setOperatorArrayDelete(ArrOperatorDelete); } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index a87cf6087b71d..f928dcc3e7059 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3016,19 +3016,8 @@ bool Sema::FindAllocationFunctions( return true; } - // new[] will force emission of vector deleting dtor which needs delete[]. - bool MaybeVectorDeletingDtor = false; - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (AllocElemType->isRecordType() && IsArray) { - auto *RD = - cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl()); - CXXDestructorDecl *DD = RD->getDestructor(); - MaybeVectorDeletingDtor = DD && DD->isVirtual() && !DD->isDeleted(); - } - } - // We don't need an operator delete if we're running under -fno-exceptions. - if (!getLangOpts().Exceptions && !MaybeVectorDeletingDtor) { + if (!getLangOpts().Exceptions) { OperatorDelete = nullptr; return false; } @@ -3619,11 +3608,8 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // Try to find operator delete/operator delete[] in class scope. LookupQualifiedName(Found, RD); - if (Found.isAmbiguous()) { - if (!Diagnose) - Found.suppressDiagnostics(); + if (Found.isAmbiguous()) return true; - } Found.suppressDiagnostics(); diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp index baef10bec8bff..c7bdeb2add0cc 100644 --- a/clang/test/SemaCXX/gh134265.cpp +++ b/clang/test/SemaCXX/gh134265.cpp @@ -1,6 +1,4 @@ -// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu -// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu -std=c++20 -// RUN: %clang_cc1 %s -verify=expected,ms -fms-extensions -fms-compatibility -triple=x86_64-pc-windows-msvc -DMS +// RUN: %clang_cc1 %s -verify -fsyntax-only struct Foo { virtual ~Foo() {} // expected-error {{attempt to use a deleted function}} @@ -15,46 +13,10 @@ struct Bar { struct Baz { virtual ~Baz() {} - static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}\ - ms-note{{explicitly marked deleted here}}} -}; - -struct BarBaz { - ~BarBaz() {} - static void operator delete[](void* ptr) = delete; + static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}} }; void foobar() { - Baz *B = new Baz[10](); // ms-error {{attempt to use a deleted function}} + Baz *B = new Baz[10](); delete [] B; // expected-error {{attempt to use a deleted function}} - BarBaz *BB = new BarBaz[10](); -} - -struct BaseDelete1 { - void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}} -}; -struct BaseDelete2 { - void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}} -}; -struct BaseDestructor { - BaseDestructor() {} - virtual ~BaseDestructor() = default; -}; -struct Final : BaseDelete1, BaseDelete2, BaseDestructor { - Final() {} -}; -struct FinalExplicit : BaseDelete1, BaseDelete2, BaseDestructor { - FinalExplicit() {} - inline ~FinalExplicit() {} -}; - -#ifdef MS -struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor { - __declspec(dllexport) ~Final1() {} // ms-error {{member 'operator delete[]' found in multiple base classes of different types}} -}; -#endif // MS - -void foo() { - Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}} - FinalExplicit* b = new FinalExplicit[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}} } >From 6c92d47f3c810fc68770a95f5e9f6ce1914452ec Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 14 Apr 2025 03:13:28 -0700 Subject: [PATCH 2/5] Revert "[clang] Do not diagnose unused deleted operator delete[] (#134357)" This reverts commit 16a1d5d51f6bafa19afc140b033db2cfb090743a. --- clang/include/clang/AST/DeclCXX.h | 2 +- clang/lib/AST/DeclCXX.cpp | 3 ++- clang/lib/Sema/SemaDeclCXX.cpp | 6 +++--- clang/test/SemaCXX/gh134265.cpp | 22 ---------------------- 4 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 clang/test/SemaCXX/gh134265.cpp diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 49d48bf711f33..ba8e7e1cf52aa 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2878,7 +2878,7 @@ class CXXDestructorDecl : public CXXMethodDecl { static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); - void setOperatorArrayDelete(FunctionDecl *OD); + void setOperatorArrayDelete(FunctionDecl *OD, Expr *ThisArg); const FunctionDecl *getOperatorDelete() const { return getCanonicalDecl()->OperatorDelete; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index d11225285c578..a6e90c8690ee7 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -3064,7 +3064,8 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { } } -void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD) { +void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD, + Expr *ThisArg) { auto *First = cast<CXXDestructorDecl>(getFirstDecl()); if (OD && !First->OperatorArrayDelete) First->OperatorArrayDelete = OD; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2dc10d4ded48a..cf51fd9d9540e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11100,12 +11100,12 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { // Lookup delete[] too in case we have to emit a vector deleting dtor; DeclarationName VDeleteName = Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); - FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor( - Loc, RD, VDeleteName, /*Diagnose=*/false); + FunctionDecl *ArrOperatorDelete = + FindDeallocationFunctionForDestructor(Loc, RD, VDeleteName); // delete[] in the TU will make sure the operator is referenced and its // uses diagnosed, otherwise vector deleting dtor won't be called anyway, // so just record it in the destructor. - Destructor->setOperatorArrayDelete(ArrOperatorDelete); + Destructor->setOperatorArrayDelete(ArrOperatorDelete, ThisArg); } } diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp deleted file mode 100644 index c7bdeb2add0cc..0000000000000 --- a/clang/test/SemaCXX/gh134265.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only - -struct Foo { - virtual ~Foo() {} // expected-error {{attempt to use a deleted function}} - static void operator delete(void* ptr) = delete; // expected-note {{explicitly marked deleted here}} -}; - - -struct Bar { - virtual ~Bar() {} - static void operator delete[](void* ptr) = delete; -}; - -struct Baz { - virtual ~Baz() {} - static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}} -}; - -void foobar() { - Baz *B = new Baz[10](); - delete [] B; // expected-error {{attempt to use a deleted function}} -} >From 29e534d5c44ccafe52f31d8d473cd367abb419f6 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 14 Apr 2025 03:13:45 -0700 Subject: [PATCH 3/5] Revert "[MS][clang] Fix crash on deletion of array of pointers (#134088)" This reverts commit 22130ca486b2fb43198453a53eb048cd8a97e9a8. --- clang/lib/AST/Expr.cpp | 3 -- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 3 -- .../microsoft-vector-deleting-dtors.cpp | 47 ------------------- 3 files changed, 53 deletions(-) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4deed08d693ac..5fab2c73f214b 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -71,9 +71,6 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const { if (const PointerType *PTy = DerivedType->getAs<PointerType>()) DerivedType = PTy->getPointeeType(); - while (const ArrayType *ATy = DerivedType->getAsArrayTypeUnsafe()) - DerivedType = ATy->getElementType(); - if (DerivedType->isDependentType()) return nullptr; diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 93ca8704de742..a664f00ffc0f0 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2034,9 +2034,6 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - while (const ArrayType *ATy = Context.getAsArrayType(ThisTy)) - ThisTy = ATy->getElementType(); - This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, diff --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp index 9d23708602a43..439ff84456033 100644 --- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp +++ b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp @@ -35,10 +35,6 @@ void operator delete(void *p) { i-=2; } void operator delete[](void *p) { i--; } }; -struct AllocatedAsArray : public Bird { - -}; - // Vector deleting dtor for Bird is an alias because no new Bird[] expressions // in the TU. // X64: @"??_EBird@@UEAAPEAXI@Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UEAAPEAXI@Z" @@ -59,14 +55,6 @@ Bird* alloc() { return P; } - -template<class C> -struct S { - void foo() { void *p = new C(); delete (C *)p; } -}; - -S<AllocatedAsArray[1][3]> sp; - void bar() { dealloc(alloc()); @@ -75,8 +63,6 @@ void bar() { Bird *p = new HasOperatorDelete[2]; dealloc(p); - - sp.foo(); } // CHECK-LABEL: define dso_local void @{{.*}}dealloc{{.*}}( @@ -113,36 +99,6 @@ void bar() { // CHECK: delete.end: // CHECK-NEXT: ret void -// Definition of S::foo, check that it has vector deleting destructor call -// X64-LABEL: define linkonce_odr dso_local void @"?foo@?$S@$$BY102UAllocatedAsArray@@@@QEAAXXZ" -// X86-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo@?$S@$$BY102UAllocatedAsArray@@@@QAEXXZ" -// CHECK: delete.notnull: ; preds = %arrayctor.cont -// CHECK-NEXT: %[[DEL_PTR:.*]] = getelementptr inbounds [1 x [3 x %struct.AllocatedAsArray]], ptr %[[THE_ARRAY:.*]], i32 0, i32 0 -// X64-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[DEL_PTR]], i64 -8 -// X86-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[DEL_PTR]], i32 -4 -// X64-NEXT: %[[HOWMANY:.*]] = load i64, ptr %[[COOKIEGEP]] -// X86-NEXT: %[[HOWMANY:.*]] = load i32, ptr %[[COOKIEGEP]] -// X64-NEXT: %[[ISNOELEM:.*]] = icmp eq i64 %[[HOWMANY]], 0 -// X86-NEXT: %[[ISNOELEM:.*]] = icmp eq i32 %[[HOWMANY]], 0 -// CHECK-NEXT: br i1 %[[ISNOELEM]], label %vdtor.nocall, label %vdtor.call -// CHECK: vdtor.nocall: ; preds = %delete.notnull -// X64-NEXT: %[[HOWMANYBYTES:.*]] = mul i64 8, %[[HOWMANY]] -// X86-NEXT: %[[HOWMANYBYTES:.*]] = mul i32 4, %[[HOWMANY]] -// X64-NEXT: %[[ADDCOOKIESIZE:.*]] = add i64 %[[HOWMANYBYTES]], 8 -// X86-NEXT: %[[ADDCOOKIESIZE:.*]] = add i32 %[[HOWMANYBYTES]], 4 -// X64-NEXT: call void @"??_V@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef %[[ADDCOOKIESIZE]]) -// X86-NEXT: call void @"??_V@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef %[[ADDCOOKIESIZE]]) -// CHECK-NEXT: br label %delete.end -// CHECK: vdtor.call: ; preds = %delete.notnull -// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[DEL_PTR]] -// CHECK-NEXT: %[[FPGEP:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0 -// CHECK-NEXT: %[[FPLOAD:.*]] = load ptr, ptr %[[FPGEP]] -// X64-NEXT: %[[CALL:.*]] = call noundef ptr %[[FPLOAD]](ptr noundef nonnull align 8 dereferenceable(8) %[[DEL_PTR]], i32 noundef 3) -// X86-NEXT: %[[CALL:.*]] = call x86_thiscallcc noundef ptr %[[FPLOAD]](ptr noundef nonnull align 4 dereferenceable(4) %[[DEL_PTR]], i32 noundef 3) -// CHECK-NEXT: br label %delete.end -// CHECK: delete.end: -// CHECK-NEXT: ret void - // Vector dtor definition for Parrot. // X64-LABEL: define weak dso_local noundef ptr @"??_EParrot@@UEAAPEAXI@Z"( // X64-SAME: ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[IMPLICIT_PARAM:.*]]) unnamed_addr @@ -213,6 +169,3 @@ void bar() { // CHECK: dtor.call_delete: // X64-NEXT: call void @"??3HasOperatorDelete@@SAXPEAX@Z" // X86-NEXT: call void @"??3HasOperatorDelete@@SAXPAX@Z" - -// X64: define weak dso_local noundef ptr @"??_EAllocatedAsArray@@UEAAPEAXI@Z" -// X86: define weak dso_local x86_thiscallcc noundef ptr @"??_EAllocatedAsArray@@UAEPAXI@Z" >From 4f368fe32973325cca3a84bc51da058365b8846d Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 14 Apr 2025 03:22:41 -0700 Subject: [PATCH 4/5] Revert "[MS][clang] Make sure vector deleting dtor calls correct operator delete (#133950)" This reverts commit 8a691cc6157b2c3bc91af767eb1154d7a715562a. --- clang/include/clang/AST/DeclCXX.h | 6 ----- clang/include/clang/Sema/Sema.h | 1 - clang/lib/AST/DeclCXX.cpp | 7 ------ clang/lib/CodeGen/CGClass.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 13 +---------- clang/lib/Sema/SemaExprCXX.cpp | 5 ++-- .../microsoft-vector-deleting-dtors.cpp | 23 ++----------------- 7 files changed, 7 insertions(+), 50 deletions(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index ba8e7e1cf52aa..dd325815ee28d 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2852,7 +2852,6 @@ class CXXDestructorDecl : public CXXMethodDecl { // FIXME: Don't allocate storage for these except in the first declaration // of a virtual destructor. FunctionDecl *OperatorDelete = nullptr; - FunctionDecl *OperatorArrayDelete = nullptr; Expr *OperatorDeleteThisArg = nullptr; CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, @@ -2878,16 +2877,11 @@ class CXXDestructorDecl : public CXXMethodDecl { static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); - void setOperatorArrayDelete(FunctionDecl *OD, Expr *ThisArg); const FunctionDecl *getOperatorDelete() const { return getCanonicalDecl()->OperatorDelete; } - const FunctionDecl *getArrayOperatorDelete() const { - return getCanonicalDecl()->OperatorArrayDelete; - } - Expr *getOperatorDeleteThisArg() const { return getCanonicalDecl()->OperatorDeleteThisArg; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0595e3dff3bb9..5ab0af8234e26 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8366,7 +8366,6 @@ class Sema final : public SemaBase { DeclarationName Name); FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc, CXXRecordDecl *RD, - DeclarationName Name, bool Diagnose = true); /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index a6e90c8690ee7..36131d19cbcdf 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -3064,13 +3064,6 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) { } } -void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD, - Expr *ThisArg) { - auto *First = cast<CXXDestructorDecl>(getFirstDecl()); - if (OD && !First->OperatorArrayDelete) - First->OperatorArrayDelete = OD; -} - bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const { // C++20 [expr.delete]p6: If the value of the operand of the delete- // expression is not a null pointer value and the selected deallocation diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 0f2422a6a665a..779888e6ac8bd 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1486,7 +1486,7 @@ static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD, CGF.EmitBlock(callDeleteBB); const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getArrayOperatorDelete(), allocatedPtr, + CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr, CGF.getContext().getTagDeclType(ClassDecl)); CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index cf51fd9d9540e..74f925f18560a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11058,11 +11058,9 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { else Loc = RD->getLocation(); - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OO_Delete); // If we have a virtual destructor, look up the deallocation function if (FunctionDecl *OperatorDelete = - FindDeallocationFunctionForDestructor(Loc, RD, Name)) { + FindDeallocationFunctionForDestructor(Loc, RD)) { Expr *ThisArg = nullptr; // If the notional 'delete this' expression requires a non-trivial @@ -11097,15 +11095,6 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); - // Lookup delete[] too in case we have to emit a vector deleting dtor; - DeclarationName VDeleteName = - Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); - FunctionDecl *ArrOperatorDelete = - FindDeallocationFunctionForDestructor(Loc, RD, VDeleteName); - // delete[] in the TU will make sure the operator is referenced and its - // uses diagnosed, otherwise vector deleting dtor won't be called anyway, - // so just record it in the destructor. - Destructor->setOperatorArrayDelete(ArrOperatorDelete, ThisArg); } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f928dcc3e7059..16a39f8b5a4dd 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3576,8 +3576,8 @@ Sema::FindUsualDeallocationFunction(SourceLocation StartLoc, FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc, CXXRecordDecl *RD, - DeclarationName Name, bool Diagnose) { + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); FunctionDecl *OperatorDelete = nullptr; QualType DeallocType = Context.getRecordType(RD); @@ -3591,7 +3591,8 @@ FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc, if (OperatorDelete) return OperatorDelete; - // If there's no class-specific operator delete, look up the global delete. + // If there's no class-specific operator delete, look up the global + // non-array delete. QualType RecordType = Context.getRecordType(RD); IDP.PassAlignment = alignedAllocationModeFromBool(hasNewExtendedAlignment(*this, RecordType)); diff --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp index 439ff84456033..ebff4f6a851b0 100644 --- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp +++ b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp @@ -28,13 +28,6 @@ struct JustAWeirdBird { } }; -int i = 0; -struct HasOperatorDelete : public Bird{ -~HasOperatorDelete() { } -void operator delete(void *p) { i-=2; } -void operator delete[](void *p) { i--; } -}; - // Vector deleting dtor for Bird is an alias because no new Bird[] expressions // in the TU. // X64: @"??_EBird@@UEAAPEAXI@Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UEAAPEAXI@Z" @@ -60,9 +53,6 @@ void bar() { JustAWeirdBird B; B.doSmth(38); - - Bird *p = new HasOperatorDelete[2]; - dealloc(p); } // CHECK-LABEL: define dso_local void @{{.*}}dealloc{{.*}}( @@ -139,8 +129,8 @@ void bar() { // CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0 // CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete_after_array_destroy // CHECK: dtor.call_delete_after_array_destroy: -// X64-NEXT: call void @"??_V@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8) -// X86-NEXT: call void @"??_V@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef 4) +// X64-NEXT: call void @"??3@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8) +// X86-NEXT: call void @"??3@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef 4) // CHECK-NEXT: br label %dtor.continue // CHECK: dtor.scalar: // X64-NEXT: call void @"??1Parrot@@UEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[LTHIS]]) @@ -160,12 +150,3 @@ void bar() { // X64-SAME: ptr noundef nonnull align 8 dereferenceable(8) %this, i32 noundef %should_call_delete) // X86: define weak dso_local x86_thiscallcc noundef ptr @"??_EJustAWeirdBird@@UAEPAXI@Z"( // X86-SAME: ptr noundef nonnull align 4 dereferenceable(4) %this, i32 noundef %should_call_delete) unnamed_addr - -// X64-LABEL: define weak dso_local noundef ptr @"??_EHasOperatorDelete@@UEAAPEAXI@Z" -// X86-LABEL: define weak dso_local x86_thiscallcc noundef ptr @"??_EHasOperatorDelete@@UAEPAXI@Z" -// CHECK: dtor.call_delete_after_array_destroy: -// X64-NEXT: call void @"??_VHasOperatorDelete@@SAXPEAX@Z" -// X86-NEXT: call void @"??_VHasOperatorDelete@@SAXPAX@Z" -// CHECK: dtor.call_delete: -// X64-NEXT: call void @"??3HasOperatorDelete@@SAXPEAX@Z" -// X86-NEXT: call void @"??3HasOperatorDelete@@SAXPAX@Z" >From 47277d5fb1d371ba0df729b89c225dabb07d4b87 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Mon, 14 Apr 2025 03:23:04 -0700 Subject: [PATCH 5/5] Revert "Reland [MS][clang] Add support for vector deleting destructors (#133451)" This reverts commit 842b57b77520abf202999946d3bb01b5dcabb179. --- clang/docs/ReleaseNotes.rst | 1 - clang/include/clang/AST/VTableBuilder.h | 6 +- clang/include/clang/Basic/ABI.h | 9 +- clang/lib/AST/ItaniumMangle.cpp | 2 - clang/lib/AST/MicrosoftMangle.cpp | 22 ++- clang/lib/AST/VTableBuilder.cpp | 19 +-- clang/lib/CodeGen/CGCXX.cpp | 37 +---- clang/lib/CodeGen/CGCXXABI.cpp | 14 -- clang/lib/CodeGen/CGCXXABI.h | 7 - clang/lib/CodeGen/CGClass.cpp | 77 +-------- clang/lib/CodeGen/CGDebugInfo.cpp | 3 +- clang/lib/CodeGen/CGExprCXX.cpp | 42 +---- clang/lib/CodeGen/CGVTables.cpp | 3 +- clang/lib/CodeGen/CodeGenModule.cpp | 48 ------ clang/lib/CodeGen/CodeGenModule.h | 6 - clang/lib/CodeGen/ItaniumCXXABI.cpp | 6 +- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 49 ++---- .../CodeGenCXX/debug-info-windows-dtor.cpp | 2 +- clang/test/CodeGenCXX/dllexport.cpp | 2 +- .../microsoft-abi-extern-template.cpp | 2 +- .../CodeGenCXX/microsoft-abi-structors.cpp | 5 +- .../test/CodeGenCXX/microsoft-abi-thunks.cpp | 3 +- .../CodeGenCXX/microsoft-abi-vftables.cpp | 20 +-- .../microsoft-abi-virtual-inheritance.cpp | 17 +- ...multiple-nonvirtual-inheritance-vdtors.cpp | 18 +-- .../microsoft-abi-vtables-return-thunks.cpp | 2 +- ...crosoft-abi-vtables-single-inheritance.cpp | 20 +-- ...-vtables-virtual-inheritance-vtordisps.cpp | 30 ++-- ...rosoft-abi-vtables-virtual-inheritance.cpp | 18 +-- .../CodeGenCXX/microsoft-no-rtti-data.cpp | 2 +- .../microsoft-vector-deleting-dtors.cpp | 152 ------------------ clang/test/CodeGenCXX/vtable-consteval.cpp | 4 +- clang/test/Modules/vtable-windows.cppm | 2 +- clang/test/Profile/cxx-abc-deleting-dtor.cpp | 9 +- 34 files changed, 125 insertions(+), 534 deletions(-) delete mode 100644 clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fd9b9a80e9938..840a52a693c7a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -530,7 +530,6 @@ Windows Support - Clang now can process the `i128` and `ui128` integeral suffixes when MSVC extensions are enabled. This allows for properly processing ``intsafe.h`` in the Windows SDK. -- Clang now supports MSVC vector deleting destructors (GH19772). LoongArch Support ^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h index e1efe8cddcc5e..a5de41dbc22f1 100644 --- a/clang/include/clang/AST/VTableBuilder.h +++ b/clang/include/clang/AST/VTableBuilder.h @@ -150,7 +150,7 @@ class VTableComponent { bool isRTTIKind() const { return isRTTIKind(getKind()); } - GlobalDecl getGlobalDecl(bool HasVectorDeletingDtors) const { + GlobalDecl getGlobalDecl() const { assert(isUsedFunctionPointerKind() && "GlobalDecl can be created only from virtual function"); @@ -161,9 +161,7 @@ class VTableComponent { case CK_CompleteDtorPointer: return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete); case CK_DeletingDtorPointer: - return GlobalDecl(DtorDecl, (HasVectorDeletingDtors) - ? CXXDtorType::Dtor_VectorDeleting - : CXXDtorType::Dtor_Deleting); + return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting); case CK_VCallOffset: case CK_VBaseOffset: case CK_OffsetToTop: diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h index 48969e4f295c3..231bad799a42c 100644 --- a/clang/include/clang/Basic/ABI.h +++ b/clang/include/clang/Basic/ABI.h @@ -31,11 +31,10 @@ enum CXXCtorType { /// C++ destructor types. enum CXXDtorType { - Dtor_Deleting, ///< Deleting dtor - Dtor_Complete, ///< Complete object dtor - Dtor_Base, ///< Base object dtor - Dtor_Comdat, ///< The COMDAT used for dtors - Dtor_VectorDeleting ///< Vector deleting dtor + Dtor_Deleting, ///< Deleting dtor + Dtor_Complete, ///< Complete object dtor + Dtor_Base, ///< Base object dtor + Dtor_Comdat ///< The COMDAT used for dtors }; } // end namespace clang diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c73f040ba1cb7..140f29b431fc3 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -6047,8 +6047,6 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { case Dtor_Comdat: Out << "D5"; break; - case Dtor_VectorDeleting: - llvm_unreachable("Itanium ABI does not use vector deleting dtors"); } } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 4d14614fc1ec7..ba6dbd99e0e1e 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1490,9 +1490,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) { // <operator-name> ::= ?_G # scalar deleting destructor case Dtor_Deleting: Out << "?_G"; return; // <operator-name> ::= ?_E # vector deleting destructor - case Dtor_VectorDeleting: - Out << "?_E"; - return; + // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need + // it. case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT"); } @@ -2893,12 +2892,9 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // ::= @ # structors (they have no declared return type) if (IsStructor) { if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) { - // The deleting destructors take an extra argument of type int that - // indicates whether the storage for the object should be deleted and - // whether a single object or an array of objects is being destroyed. This - // extra argument is not reflected in the AST. - if (StructorType == Dtor_Deleting || - StructorType == Dtor_VectorDeleting) { + // The scalar deleting destructor takes an extra int argument which is not + // reflected in the AST. + if (StructorType == Dtor_Deleting) { Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z"); return; } @@ -3871,10 +3867,10 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD, const ThunkInfo &Thunk, bool /*ElideOverrideInfo*/, raw_ostream &Out) { - // The dtor thunk should use vector deleting dtor mangling, however as an - // optimization we may end up emitting only scalar deleting dtor body, so just - // use the vector deleting dtor mangling manually. - assert(Type == Dtor_Deleting || Type == Dtor_VectorDeleting); + // FIXME: Actually, the dtor thunk should be emitted for vector deleting + // dtors rather than scalar deleting dtors. Just use the vector deleting dtor + // mangling manually until we support both deleting dtor types. + assert(Type == Dtor_Deleting); msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type); Mangler.getStream() << "??_E"; diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 21f9d343c6ee7..6c97b8718c65e 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -1735,8 +1735,8 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( const CXXMethodDecl *MD = I.first; const MethodInfo &MI = I.second; if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] = - MI.VTableIndex - AddressPoint; + MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] + = MI.VTableIndex - AddressPoint; MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)] = MI.VTableIndex + 1 - AddressPoint; } else { @@ -2657,11 +2657,7 @@ class VFTableBuilder { MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(), WhichVFPtr.NonVirtualOffset, MI.VFTableIndex); if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) { - // In Microsoft ABI vftable always references vector deleting dtor. - CXXDtorType DtorTy = Context.getTargetInfo().getCXXABI().isMicrosoft() - ? Dtor_VectorDeleting - : Dtor_Deleting; - MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc; + MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc; } else { MethodVFTableLocations[MD] = Loc; } @@ -3291,10 +3287,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) { const CXXDestructorDecl *DD = Component.getDestructorDecl(); DD->printQualifiedName(Out); - if (Context.getTargetInfo().getCXXABI().isMicrosoft()) - Out << "() [vector deleting]"; - else - Out << "() [scalar deleting]"; + Out << "() [scalar deleting]"; if (DD->isPureVirtual()) Out << " [pure]"; @@ -3764,7 +3757,7 @@ void MicrosoftVTableContext::dumpMethodLocations( PredefinedIdentKind::PrettyFunctionNoVirtual, MD); if (isa<CXXDestructorDecl>(MD)) { - IndicesMap[I.second] = MethodName + " [vector deleting]"; + IndicesMap[I.second] = MethodName + " [scalar deleting]"; } else { IndicesMap[I.second] = MethodName; } @@ -3880,7 +3873,7 @@ MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) { assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) && "Only use this method for virtual methods or dtors"); if (isa<CXXDestructorDecl>(GD.getDecl())) - assert(GD.getDtorType() == Dtor_VectorDeleting); + assert(GD.getDtorType() == Dtor_Deleting); GD = GD.getCanonicalDecl(); diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 6f47e24eed5b3..78a7b021855b7 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -175,6 +175,7 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { // requires explicit comdat support in the IL. if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) return true; + // Create the alias with no name. auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "", Aliasee, &getModule()); @@ -200,42 +201,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { return false; } -/// Emit a definition as a global alias for another definition, unconditionally. -void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl, - GlobalDecl TargetDecl) { - - llvm::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl); - - StringRef MangledName = getMangledName(AliasDecl); - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) - return; - auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl)); - - // Determine the linkage type for the alias. - llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl); - - // Create the alias with no name. - auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "", - Aliasee, &getModule()); - // Destructors are always unnamed_addr. - Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - - if (Entry) { - assert(Entry->getValueType() == AliasValueType && - Entry->getAddressSpace() == Alias->getAddressSpace() && - "declaration exists with different type"); - Alias->takeName(Entry); - Entry->replaceAllUsesWith(Alias); - Entry->eraseFromParent(); - } else { - Alias->setName(MangledName); - } - - // Set any additional necessary attributes for the alias. - SetCommonAttributes(AliasDecl, Alias); -} - llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) { const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD); auto *Fn = cast<llvm::Function>( diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 93dc17bac95e0..d42e0bb814a88 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -271,20 +271,6 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } -void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, - QualType eltTy, llvm::Value *&numElements, - llvm::Value *&allocPtr, CharUnits &cookieSize) { - assert(eltTy.isDestructedType()); - - // Derive a char* in the same address space as the pointer. - ptr = ptr.withElementType(CGF.Int8Ty); - - cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.emitRawPointer(CGF); - numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); -} - llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, Address ptr, CharUnits cookieSize) { diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index da2d367da7096..96fe04661944d 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -275,7 +275,6 @@ class CGCXXABI { virtual CatchTypeInfo getCatchAllTypeInfo(); virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy) = 0; - virtual bool hasVectorDeletingDtors() = 0; virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0; virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, @@ -576,12 +575,6 @@ class CGCXXABI { QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize); - /// Reads the array cookie associated with the given pointer, - /// that should have one. - void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, QualType ElementType, - llvm::Value *&NumElements, llvm::Value *&AllocPtr, - CharUnits &CookieSize); - /// Return whether the given global decl needs a VTT parameter. virtual bool NeedsVTTParameter(GlobalDecl GD); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 779888e6ac8bd..1c73a5bf75f37 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1429,70 +1429,6 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF, return true; } -static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD, - CodeGenFunction &CGF, - llvm::Value *ShouldDeleteCondition) { - Address ThisPtr = CGF.LoadCXXThisAddress(); - llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar"); - llvm::BasicBlock *callDeleteBB = - CGF.createBasicBlock("dtor.call_delete_after_array_destroy"); - llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector"); - auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType()); - llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2)); - llvm::Value *ShouldDestroyArray = - CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy); - CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB); - - CGF.EmitBlock(VectorBB); - - llvm::Value *numElements = nullptr; - llvm::Value *allocatedPtr = nullptr; - CharUnits cookieSize; - QualType EltTy = DD->getThisType()->getPointeeType(); - CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements, - allocatedPtr, cookieSize); - - // Destroy the elements. - QualType::DestructionKind dtorKind = EltTy.isDestructedType(); - - assert(dtorKind); - assert(numElements && "no element count for a type with a destructor!"); - - CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy); - CharUnits elementAlign = - ThisPtr.getAlignment().alignmentOfArrayElement(elementSize); - - llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF); - llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( - ThisPtr.getElementType(), arrayBegin, numElements, "delete.end"); - - // We already checked that the array is not 0-length before entering vector - // deleting dtor. - CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign, - CGF.getDestroyer(dtorKind), - /*checkZeroLength*/ false, CGF.needsEHCleanup(dtorKind)); - - llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont"); - CGF.EmitBlock(VectorBBCont); - - llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1)); - - llvm::Value *ShouldCallDelete = - CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall); - CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(), - callDeleteBB); - CGF.EmitBlock(callDeleteBB); - const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl); - const CXXRecordDecl *ClassDecl = Dtor->getParent(); - CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr, - CGF.getContext().getTagDeclType(ClassDecl)); - - CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); - CGF.EmitBlock(ScalarBB); -} - /// EmitDestructorBody - Emits the body of the current destructor. void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); @@ -1522,9 +1458,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // outside of the function-try-block, which means it's always // possible to delegate the destructor body to the complete // destructor. Do so. - if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) { - if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting) - EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue); + if (DtorType == Dtor_Deleting) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); if (HaveInsertPoint()) { @@ -1553,8 +1487,6 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { switch (DtorType) { case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT"); case Dtor_Deleting: llvm_unreachable("already handled deleting case"); - case Dtor_VectorDeleting: - llvm_unreachable("already handled vector deleting case"); case Dtor_Complete: assert((Body || getTarget().getCXXABI().isMicrosoft()) && @@ -1637,6 +1569,7 @@ namespace { return CGF.EmitScalarExpr(ThisArg); return CGF.LoadCXXThis(); } + /// Call the operator delete associated with the current destructor. struct CallDtorDelete final : EHScopeStack::Cleanup { CallDtorDelete() {} @@ -1655,10 +1588,8 @@ namespace { bool ReturnAfterDelete) { llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete"); llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue"); - auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType()); - llvm::Value *CheckTheBit = CGF.Builder.CreateAnd( - ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1)); - llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(CheckTheBit); + llvm::Value *ShouldCallDelete + = CGF.Builder.CreateIsNull(ShouldDeleteCondition); CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB); CGF.EmitBlock(callDeleteBB); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d659243d38d5f..367b51c069e3a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2119,8 +2119,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( // Emit MS ABI vftable information. There is only one entry for the // deleting dtor. const auto *DD = dyn_cast<CXXDestructorDecl>(Method); - GlobalDecl GD = - DD ? GlobalDecl(DD, Dtor_VectorDeleting) : GlobalDecl(Method); + GlobalDecl GD = DD ? GlobalDecl(DD, Dtor_Deleting) : GlobalDecl(Method); MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); VIndex = ML.Index; diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index a0d21a4de469f..3e8c42d5a6f4b 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1209,8 +1209,6 @@ void CodeGenFunction::EmitNewArrayInitializer( EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE, /*NewPointerIsChecked*/true, CCE->requiresZeroInitialization()); - if (CGM.getCXXABI().hasVectorDeletingDtors()) - CGM.requireVectorDestructorDefinition(Ctor->getParent()); return; } @@ -1957,8 +1955,10 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, /// Emit the code for deleting a single object. /// \return \c true if we started emitting UnconditionalDeleteBlock, \c false /// if not. -static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, - Address Ptr, QualType ElementType, +static bool EmitObjectDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + Address Ptr, + QualType ElementType, llvm::BasicBlock *UnconditionalDeleteBlock) { // C++11 [expr.delete]p3: // If the static type of the object to be deleted is different from its @@ -2174,40 +2174,6 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); - if (E->isArrayForm() && CGM.getCXXABI().hasVectorDeletingDtors()) { - if (auto *RD = DeleteTy->getAsCXXRecordDecl()) { - auto *Dtor = RD->getDestructor(); - if (Dtor && Dtor->isVirtual()) { - llvm::Value *NumElements = nullptr; - llvm::Value *AllocatedPtr = nullptr; - CharUnits CookieSize; - llvm::BasicBlock *bodyBB = createBasicBlock("vdtor.call"); - llvm::BasicBlock *doneBB = createBasicBlock("vdtor.nocall"); - // Check array cookie to see if the array has 0 length. Don't call - // the destructor in that case. - CGM.getCXXABI().ReadArrayCookie(*this, Ptr, E, DeleteTy, NumElements, - AllocatedPtr, CookieSize); - - auto *CondTy = cast<llvm::IntegerType>(NumElements->getType()); - llvm::Value *isEmpty = Builder.CreateICmpEQ( - NumElements, llvm::ConstantInt::get(CondTy, 0)); - Builder.CreateCondBr(isEmpty, doneBB, bodyBB); - - // Delete cookie for empty array. - const FunctionDecl *operatorDelete = E->getOperatorDelete(); - EmitBlock(doneBB); - EmitDeleteCall(operatorDelete, AllocatedPtr, DeleteTy, NumElements, - CookieSize); - EmitBranch(DeleteEnd); - - EmitBlock(bodyBB); - if (!EmitObjectDelete(*this, E, Ptr, DeleteTy, DeleteEnd)) - EmitBlock(DeleteEnd); - return; - } - } - } - if (E->isArrayForm()) { EmitArrayDelete(*this, E, Ptr, DeleteTy); EmitBlock(DeleteEnd); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 0a1cf24fbfa56..8d0e8d194f2c9 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -770,8 +770,7 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, case VTableComponent::CK_FunctionPointer: case VTableComponent::CK_CompleteDtorPointer: case VTableComponent::CK_DeletingDtorPointer: { - GlobalDecl GD = - component.getGlobalDecl(CGM.getCXXABI().hasVectorDeletingDtors()); + GlobalDecl GD = component.getGlobalDecl(); const bool IsThunk = nextVTableThunkIndex < layout.vtable_thunks().size() && diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 0154799498f5e..4a48c2f35ff23 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -7948,51 +7948,3 @@ void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) { NewBuilder->ABI->MangleCtx = std::move(ABI->MangleCtx); } - -bool CodeGenModule::classNeedsVectorDestructor(const CXXRecordDecl *RD) { - CXXDestructorDecl *Dtor = RD->getDestructor(); - // The compiler can't know if new[]/delete[] will be used outside of the DLL, - // so just force vector deleting destructor emission if dllexport is present. - // This matches MSVC behavior. - if (Dtor && Dtor->isVirtual() && Dtor->isDefined() && - Dtor->hasAttr<DLLExportAttr>()) - return true; - - assert(getCXXABI().hasVectorDeletingDtors()); - return RequireVectorDeletingDtor.count(RD); -} - -void CodeGenModule::requireVectorDestructorDefinition(const CXXRecordDecl *RD) { - assert(getCXXABI().hasVectorDeletingDtors()); - RequireVectorDeletingDtor.insert(RD); - - // To reduce code size in general case we lazily emit scalar deleting - // destructor definition and an alias from vector deleting destructor to - // scalar deleting destructor. It may happen that we first emitted the scalar - // deleting destructor definition and the alias and then discovered that the - // definition of the vector deleting destructor is required. Then we need to - // remove the alias and the scalar deleting destructor and queue vector - // deleting destructor body for emission. Check if that is the case. - CXXDestructorDecl *DtorD = RD->getDestructor(); - GlobalDecl ScalarDtorGD(DtorD, Dtor_Deleting); - StringRef MangledName = getMangledName(ScalarDtorGD); - llvm::GlobalValue *Entry = GetGlobalValue(MangledName); - if (Entry && !Entry->isDeclaration()) { - GlobalDecl VectorDtorGD(DtorD, Dtor_VectorDeleting); - StringRef VDName = getMangledName(VectorDtorGD); - llvm::GlobalValue *VDEntry = GetGlobalValue(VDName); - // It exists and it should be an alias. - assert(VDEntry && isa<llvm::GlobalAlias>(VDEntry)); - auto *NewFn = llvm::Function::Create( - cast<llvm::FunctionType>(VDEntry->getValueType()), - llvm::Function::ExternalLinkage, VDName, &getModule()); - SetFunctionAttributes(VectorDtorGD, NewFn, /*IsIncompleteFunction*/ false, - /*IsThunk*/ false); - NewFn->takeName(VDEntry); - VDEntry->replaceAllUsesWith(NewFn); - VDEntry->eraseFromParent(); - Entry->replaceAllUsesWith(NewFn); - Entry->eraseFromParent(); - addDeferredDeclToEmit(VectorDtorGD); - } -} diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 2cf15e24180b3..46de3d868f901 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -528,9 +528,6 @@ class CodeGenModule : public CodeGenTypeCache { /// that we don't re-emit the initializer. llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition; - /// To remember which types did require a vector deleting dtor. - llvm::SmallPtrSet<const CXXRecordDecl *, 16> RequireVectorDeletingDtor; - typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *> GlobalInitData; @@ -1545,7 +1542,6 @@ class CodeGenModule : public CodeGenTypeCache { void EmitGlobal(GlobalDecl D); bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D); - void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target); llvm::GlobalValue *GetGlobalValue(StringRef Ref); @@ -1813,8 +1809,6 @@ class CodeGenModule : public CodeGenTypeCache { // behavior. So projects like the Linux kernel can rely on it. return !getLangOpts().CPlusPlus; } - void requireVectorDestructorDefinition(const CXXRecordDecl *RD); - bool classNeedsVectorDestructor(const CXXRecordDecl *RD); private: bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const; diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 35485dc6d867f..70b53be7e77a3 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -91,8 +91,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { case Dtor_Comdat: llvm_unreachable("emitting dtor comdat as function?"); - case Dtor_VectorDeleting: - llvm_unreachable("unexpected dtor kind for this ABI"); } llvm_unreachable("bad dtor kind"); } @@ -181,7 +179,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { } bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override; - bool hasVectorDeletingDtors() override { return false; } void EmitBadTypeidCall(CodeGenFunction &CGF) override; llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, @@ -451,8 +448,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { if (!IsInlined) continue; - StringRef Name = CGM.getMangledName( - VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false)); + StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl()); auto *Entry = CGM.GetGlobalValue(Name); // This checks if virtual inline function has already been emitted. // Note that it is possible that this inline function would be emitted diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index a664f00ffc0f0..aa9a55ae05927 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -71,8 +71,8 @@ class MicrosoftCXXABI : public CGCXXABI { switch (GD.getDtorType()) { case Dtor_Complete: case Dtor_Deleting: - case Dtor_VectorDeleting: return true; + case Dtor_Base: return false; @@ -146,7 +146,6 @@ class MicrosoftCXXABI : public CGCXXABI { } bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override; - bool hasVectorDeletingDtors() override { return true; } void EmitBadTypeidCall(CodeGenFunction &CGF) override; llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, Address ThisPtr, @@ -262,7 +261,7 @@ class MicrosoftCXXABI : public CGCXXABI { // There's only Dtor_Deleting in vftable but it shares the this // adjustment with the base one, so look up the deleting one instead. - LookupGD = GlobalDecl(DD, Dtor_VectorDeleting); + LookupGD = GlobalDecl(DD, Dtor_Deleting); } MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); @@ -344,8 +343,8 @@ class MicrosoftCXXABI : public CGCXXABI { void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs) override { - assert(GD.getDtorType() == Dtor_VectorDeleting && - "Only vector deleting destructor thunks are available in this ABI"); + assert(GD.getDtorType() == Dtor_Deleting && + "Only deleting destructor thunks are available in this ABI"); CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)), getContext().IntTy); } @@ -1092,8 +1091,7 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { static bool isDeletingDtor(GlobalDecl GD) { return isa<CXXDestructorDecl>(GD.getDecl()) && - (GD.getDtorType() == Dtor_Deleting || - GD.getDtorType() == Dtor_VectorDeleting); + GD.getDtorType() == Dtor_Deleting; } bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const { @@ -1346,8 +1344,7 @@ MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD, AddedStructorArgCounts Added; // TODO: 'for base' flag if (isa<CXXDestructorDecl>(GD.getDecl()) && - (GD.getDtorType() == Dtor_Deleting || - GD.getDtorType() == Dtor_VectorDeleting)) { + GD.getDtorType() == Dtor_Deleting) { // The scalar deleting destructor takes an implicit int parameter. ArgTys.push_back(getContext().IntTy); ++Added.Suffix; @@ -1379,7 +1376,7 @@ void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV, CXXDtorType DT) const { // Deleting destructor variants are never imported or exported. Give them the // default storage class. - if (DT == Dtor_Deleting || DT == Dtor_VectorDeleting) { + if (DT == Dtor_Deleting) { GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); } else { const NamedDecl *ND = Dtor; @@ -1413,12 +1410,6 @@ llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( // and are emitted everywhere they are used. They are internal if the class // is internal. return llvm::GlobalValue::LinkOnceODRLinkage; - case Dtor_VectorDeleting: - // Use the weak, non-ODR linkage for vector deleting destructors to block - // inlining. This enables an MS ABI code-size saving optimization that - // allows us to avoid emitting array deletion code when arrays of a given - // type are not allocated within the final linkage unit. - return llvm::GlobalValue::WeakAnyLinkage; case Dtor_Comdat: llvm_unreachable("MS C++ ABI does not support comdat dtors"); } @@ -1450,7 +1441,7 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) { // There's no Dtor_Base in vftable but it shares the this adjustment with // the deleting one, so look it up instead. - GD = GlobalDecl(DD, Dtor_VectorDeleting); + GD = GlobalDecl(DD, Dtor_Deleting); } MethodVFTableLocation ML = @@ -1499,7 +1490,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( // There's only Dtor_Deleting in vftable but it shares the this adjustment // with the base one, so look up the deleting one instead. - LookupGD = GlobalDecl(DD, Dtor_VectorDeleting); + LookupGD = GlobalDecl(DD, Dtor_Deleting); } MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD); @@ -2012,20 +2003,20 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( auto *D = dyn_cast<const CXXDeleteExpr *>(E); assert((CE != nullptr) ^ (D != nullptr)); assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); - assert(DtorType == Dtor_VectorDeleting || DtorType == Dtor_Complete || - DtorType == Dtor_Deleting); + assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); // We have only one destructor in the vftable but can get both behaviors // by passing an implicit int parameter. - GlobalDecl GD(Dtor, Dtor_VectorDeleting); + GlobalDecl GD(Dtor, Dtor_Deleting); const CGFunctionInfo *FInfo = &CGM.getTypes().arrangeCXXStructorDeclaration(GD); llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); ASTContext &Context = getContext(); - uint32_t Flags = ((D && D->isArrayForm()) << 1) | (DtorType == Dtor_Deleting); - llvm::Value *ImplicitParam = CGF.Builder.getInt32(Flags); + llvm::Value *ImplicitParam = llvm::ConstantInt::get( + llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), + DtorType == Dtor_Deleting); QualType ThisTy; if (CE) { @@ -4067,18 +4058,6 @@ void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) { if (GD.getDtorType() == Dtor_Base && !CGM.TryEmitBaseDestructorAsAlias(dtor)) return; - if (GD.getDtorType() == Dtor_VectorDeleting && - !CGM.classNeedsVectorDestructor(dtor->getParent())) { - // Create GlobalDecl object with the correct type for the scalar - // deleting destructor. - GlobalDecl ScalarDtorGD(dtor, Dtor_Deleting); - - // Emit an alias from the vector deleting destructor to the scalar deleting - // destructor. - CGM.EmitDefinitionAsAlias(GD, ScalarDtorGD); - return; - } - llvm::Function *Fn = CGM.codegenCXXStructor(GD); if (Fn->isWeakForLinker()) Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName())); diff --git a/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp b/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp index ffef45b9f7d1b..beea56ce7368b 100644 --- a/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp +++ b/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp @@ -16,7 +16,7 @@ struct AB: A, B { template struct AB<int>; // CHECK: define {{.*}}@"??_E?$AB@H@@W3AEPAXI@Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]] -// CHECK: call {{.*}}@"??_E?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]] +// CHECK: call {{.*}}@"??_G?$AB@H@@UAEPAXI@Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]] // CHECK: define // CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index 16eaac75e702f..c8ac526f4cbe3 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -631,7 +631,7 @@ struct __declspec(dllexport) Y { struct __declspec(dllexport) Z { virtual ~Z() {} }; // The scalar deleting dtor does not get exported: -// M32-DAG: define weak dso_local x86_thiscallcc ptr @"??_EZ@@UAEPAXI@Z" +// M32-DAG: define linkonce_odr dso_local x86_thiscallcc ptr @"??_GZ@@UAEPAXI@Z" // The user-defined dtor does get exported: diff --git a/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp index 67df330bc3263..ea12aa64ae305 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp @@ -4,7 +4,7 @@ // own copy the vftable when emitting the available externally constructor. // CHECK: @"??_7?$Foo@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ -// CHECK-SAME: ptr @"??_E?$Foo@H@@UEAAPEAXI@Z" +// CHECK-SAME: ptr @"??_G?$Foo@H@@UEAAPEAXI@Z" // CHECK-SAME: ] }, comdat // CHECK-LABEL: define dso_local noundef ptr @"?f@@YAPEAU?$Foo@H@@XZ"() diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp index 2ff7391ec8c8f..07abc3d065e5e 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -52,8 +52,7 @@ struct C { // DTORS: store ptr %{{.*}}, ptr %[[RETVAL:retval]] // DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, ptr %[[SHOULD_DELETE_VAR]] // DTORS: call x86_thiscallcc void @"??1C@basic@@UAE@XZ"(ptr {{[^,]*}} %[[THIS:[0-9a-z]+]]) -// DTORS-NEXT: %[[AND:[0-9]+]] = and i32 %[[SHOULD_DELETE_VALUE]], 1 -// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[AND]], 0 +// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0 // DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]] // // DTORS: [[CALL_DELETE_LABEL]] @@ -167,7 +166,7 @@ void foo() { // DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc ptr @"??_EC@dtor_in_second_nvbase@@W3AEPAXI@Z"(ptr %this, i32 %should_call_delete) // Do an adjustment from B* to C*. // DTORS2: getelementptr i8, ptr %{{.*}}, i32 -4 -// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc ptr @"??_EC@dtor_in_second_nvbase@@UAEPAXI@Z" +// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc ptr @"??_GC@dtor_in_second_nvbase@@UAEPAXI@Z" // DTORS2: ret ptr %[[CALL]] } diff --git a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp index 83ec158ff7f51..38aa81253ccad 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -63,7 +63,8 @@ C::C() {} // Emits vftable and forces thunk generation. // CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_EC@@W3AEPAXI@Z"(ptr noundef %this, i32 noundef %should_call_delete) {{.*}} comdat // CODEGEN: getelementptr i8, ptr {{.*}}, i32 -4 -// CODEGEN: call x86_thiscallcc noundef ptr @"??_EC@@UAEPAXI@Z" +// FIXME: should actually call _EC, not _GC. +// CODEGEN: call x86_thiscallcc noundef ptr @"??_GC@@UAEPAXI@Z" // CODEGEN: ret // CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f@C@@W3AEXXZ"(ptr diff --git a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp index 7ceb15e40e582..bc278bdb847fc 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp @@ -8,38 +8,38 @@ struct S { virtual ~S(); } s; -// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4S@@6B@", ptr @"??_ES@@UAEPAXI@Z"] }, comdat($"??_7S@@6B@") +// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4S@@6B@", ptr @"??_GS@@UAEPAXI@Z"] }, comdat($"??_7S@@6B@") // RTTI-DAG: @"??_7S@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_S]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI@Z"] } +// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GS@@UAEPAXI@Z"] } struct __declspec(dllimport) U { virtual ~U(); } u; -// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4U@@6B@", ptr @"??_EU@@UAEPAXI@Z"] } +// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4U@@6B@", ptr @"??_GU@@UAEPAXI@Z"] } // RTTI-DAG: @"??_SU@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_U]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EU@@UAEPAXI@Z"] } +// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GU@@UAEPAXI@Z"] } struct __declspec(dllexport) V { virtual ~V(); } v; -// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4V@@6B@", ptr @"??_EV@@UAEPAXI@Z"] }, comdat($"??_7V@@6B@") +// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4V@@6B@", ptr @"??_GV@@UAEPAXI@Z"] }, comdat($"??_7V@@6B@") // RTTI-DAG: @"??_7V@@6B@" = dllexport unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_V]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EV@@UAEPAXI@Z"] } +// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GV@@UAEPAXI@Z"] } namespace { struct W { virtual ~W() {} } w; } -// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4W@?A0x{{[^@]*}}@@6B@", ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI@Z"] } +// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4W@?A0x{{[^@]*}}@@6B@", ptr @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z"] } // RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_W]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI@Z"] } +// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GW@?A0x{{[^@]*}}@@UAEPAXI@Z"] } struct X {}; template <class> struct Y : virtual X { @@ -49,7 +49,7 @@ template <class> struct Y : virtual X { extern template class Y<int>; template Y<int>::Y(); -// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4?$Y@H@@6B@", ptr @"??_E?$Y@H@@UAEPAXI@Z"] }, comdat($"??_7?$Y@H@@6B@") +// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4?$Y@H@@6B@", ptr @"??_G?$Y@H@@UAEPAXI@Z"] }, comdat($"??_7?$Y@H@@6B@") // RTTI-DAG: @"??_7?$Y@H@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_Y]], i32 0, i32 0, i32 1) -// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_E?$Y@H@@UAEPAXI@Z"] }, comdat +// NO-RTTI-DAG: @"??_7?$Y@H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_G?$Y@H@@UAEPAXI@Z"] }, comdat diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 7e9dce18b2797..b54775f6c5dd0 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -80,15 +80,6 @@ B::~B() { // CHECK2: call x86_thiscallcc void @"??1VBase@@UAE@XZ"(ptr {{[^,]*}} %[[VBASE_i8]]) // CHECK2: ret - // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0B@test2@@QAE@XZ" - // CHECK2: (ptr {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived) - // CHECK2: call x86_thiscallcc noundef ptr @"??0A@test2@@QAE@XZ"(ptr {{[^,]*}} %{{.*}}) - // CHECK2: ret - - // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GD@pr36921@@UAEPAXI@Z"( - // CHECK2: %[[THIS_RELOAD:.*]] = load ptr, ptr - // CHECK2: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4 - // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GB@@UAEPAXI@Z" // CHECK2: store ptr %{{.*}}, ptr %[[THIS_ADDR:.*]], align 4 // CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_PARAM_i8:.*]], i32 -8 @@ -302,6 +293,11 @@ void callC() { C x; } // CHECK: call x86_thiscallcc noundef ptr @"??0A@test2@@QAE@XZ"(ptr {{[^,]*}} %{{.*}}) // CHECK: ret +// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0B@test2@@QAE@XZ" +// CHECK2: (ptr {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived) +// CHECK2: call x86_thiscallcc noundef ptr @"??0A@test2@@QAE@XZ"(ptr {{[^,]*}} %{{.*}}) +// CHECK2: ret + } namespace test3 { @@ -484,6 +480,9 @@ struct B { struct C : virtual B {}; struct D : virtual A, C {}; D d; +// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GD@pr36921@@UAEPAXI@Z"( +// CHECK2: %[[THIS_RELOAD:.*]] = load ptr, ptr +// CHECK2: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4 } namespace issue_60465 { diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp index 74150b0ecb535..a407766f8ed9f 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp @@ -12,18 +12,18 @@ struct B { struct C : A, B { // CHECK-LABEL: VFTable for 'A' in 'C' (2 entries). - // CHECK-NEXT: 0 | C::~C() [vector deleting] + // CHECK-NEXT: 0 | C::~C() [scalar deleting] // CHECK-NEXT: 1 | void A::z1() // CHECK-LABEL: VFTable for 'B' in 'C' (1 entry). - // CHECK-NEXT: 0 | C::~C() [vector deleting] + // CHECK-NEXT: 0 | C::~C() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-LABEL: Thunks for 'C::~C()' (1 entry). // CHECK-NEXT: 0 | [this adjustment: -4 non-virtual] // CHECK-LABEL: VFTable indices for 'C' (1 entry). - // CHECK-NEXT: 0 | C::~C() [vector deleting] + // CHECK-NEXT: 0 | C::~C() [scalar deleting] virtual ~C(); }; @@ -41,7 +41,7 @@ struct E : D, B { // CHECK-NEXT: 0 | void D::z4() // CHECK-LABEL: VFTable for 'B' in 'E' (1 entry). - // CHECK-NEXT: 0 | E::~E() [vector deleting] + // CHECK-NEXT: 0 | E::~E() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-LABEL: Thunks for 'E::~E()' (1 entry). @@ -49,7 +49,7 @@ struct E : D, B { // CHECK-LABEL: VFTable indices for 'E' (1 entry). // CHECK-NEXT: -- accessible via vfptr at offset 4 -- - // CHECK-NEXT: 0 | E::~E() [vector deleting] + // CHECK-NEXT: 0 | E::~E() [scalar deleting] }; void build_vftable(E *obj) { delete obj; } @@ -61,7 +61,7 @@ struct F : D, B { // CHECK-NEXT: 0 | void D::z4() // CHECK-LABEL: VFTable for 'B' in 'F' (1 entry). - // CHECK-NEXT: 0 | F::~F() [vector deleting] + // CHECK-NEXT: 0 | F::~F() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-LABEL: Thunks for 'F::~F()' (1 entry). @@ -69,7 +69,7 @@ struct F : D, B { // CHECK-LABEL: VFTable indices for 'F' (1 entry). // CHECK-NEXT: -- accessible via vfptr at offset 4 -- - // CHECK-NEXT: 0 | F::~F() [vector deleting] + // CHECK-NEXT: 0 | F::~F() [scalar deleting] }; void build_vftable(F *obj) { delete obj; } @@ -79,7 +79,7 @@ struct G : F { // CHECK-NEXT: 0 | void D::z4() // CHECK-LABEL: VFTable for 'B' in 'F' in 'G' (1 entry). - // CHECK-NEXT: 0 | G::~G() [vector deleting] + // CHECK-NEXT: 0 | G::~G() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-LABEL: Thunks for 'G::~G()' (1 entry). @@ -87,7 +87,7 @@ struct G : F { // CHECK-LABEL: VFTable indices for 'G' (1 entry). // CHECK-NEXT: -- accessible via vfptr at offset 4 -- - // CHECK-NEXT: 0 | G::~G() [vector deleting] + // CHECK-NEXT: 0 | G::~G() [scalar deleting] virtual ~G(); }; diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp index 1a589370d3a74..5030a5dcd2a50 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp @@ -213,6 +213,6 @@ struct C : virtual B { C *f(); }; C c; // VFTABLES-LABEL: VFTable indices for 'pr34302::C' (2 entries). // VFTABLES-NEXT: -- accessible via vbtable index 1, vfptr at offset 0 -- -// VFTABLES-NEXT: 0 | pr34302::C::~C() [vector deleting] +// VFTABLES-NEXT: 0 | pr34302::C::~C() [scalar deleting] // VFTABLES-NEXT: 2 | C *pr34302::C::f() } diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp index c95202e8cc253..b0bf927d38f7c 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp @@ -44,10 +44,10 @@ void use(B *obj) { obj->f(); } struct C { // CHECK-LABEL: VFTable for 'C' (2 entries) - // CHECK-NEXT: 0 | C::~C() [vector deleting] + // CHECK-NEXT: 0 | C::~C() [scalar deleting] // CHECK-NEXT: 1 | void C::f() // CHECK-LABEL: VFTable indices for 'C' (2 entries). - // CHECK-NEXT: 0 | C::~C() [vector deleting] + // CHECK-NEXT: 0 | C::~C() [scalar deleting] // CHECK-NEXT: 1 | void C::f() virtual ~C(); @@ -60,10 +60,10 @@ void use(C *obj) { obj->f(); } struct D { // CHECK-LABEL: VFTable for 'D' (2 entries) // CHECK-NEXT: 0 | void D::f() - // CHECK-NEXT: 1 | D::~D() [vector deleting] + // CHECK-NEXT: 1 | D::~D() [scalar deleting] // CHECK-LABEL: VFTable indices for 'D' (2 entries) // CHECK-NEXT: 0 | void D::f() - // CHECK-NEXT: 1 | D::~D() [vector deleting] + // CHECK-NEXT: 1 | D::~D() [scalar deleting] virtual void f(); virtual ~D(); @@ -77,10 +77,10 @@ struct E : A { // CHECK-NEXT: 0 | void A::f() // CHECK-NEXT: 1 | void A::g() // CHECK-NEXT: 2 | void A::h() - // CHECK-NEXT: 3 | E::~E() [vector deleting] + // CHECK-NEXT: 3 | E::~E() [scalar deleting] // CHECK-NEXT: 4 | void E::i() // CHECK-LABEL: VFTable indices for 'E' (2 entries). - // CHECK-NEXT: 3 | E::~E() [vector deleting] + // CHECK-NEXT: 3 | E::~E() [scalar deleting] // CHECK-NEXT: 4 | void E::i() // ~E would be the key method, but it isn't used, and MS ABI has no key @@ -98,10 +98,10 @@ struct F : A { // CHECK-NEXT: 1 | void A::g() // CHECK-NEXT: 2 | void A::h() // CHECK-NEXT: 3 | void F::i() - // CHECK-NEXT: 4 | F::~F() [vector deleting] + // CHECK-NEXT: 4 | F::~F() [scalar deleting] // CHECK-LABEL: VFTable indices for 'F' (2 entries). // CHECK-NEXT: 3 | void F::i() - // CHECK-NEXT: 4 | F::~F() [vector deleting] + // CHECK-NEXT: 4 | F::~F() [scalar deleting] virtual void i(); virtual ~F(); @@ -115,12 +115,12 @@ struct G : E { // CHECK-NEXT: 0 | void G::f() // CHECK-NEXT: 1 | void A::g() // CHECK-NEXT: 2 | void A::h() - // CHECK-NEXT: 3 | G::~G() [vector deleting] + // CHECK-NEXT: 3 | G::~G() [scalar deleting] // CHECK-NEXT: 4 | void E::i() // CHECK-NEXT: 5 | void G::j() // CHECK-LABEL: VFTable indices for 'G' (3 entries). // CHECK-NEXT: 0 | void G::f() - // CHECK-NEXT: 3 | G::~G() [vector deleting] + // CHECK-NEXT: 3 | G::~G() [scalar deleting] // CHECK-NEXT: 5 | void G::j() virtual void f(); // overrides A::f() diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp index be9f281560dcf..c5ce69f5cbcac 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp @@ -57,7 +57,7 @@ struct A : virtual V1 { // CHECK-LABEL: VFTable for 'V1' in 'simple::A' (2 entries). // CHECK-NEXT: 0 | void simple::A::f() // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] - // CHECK-NEXT: 1 | simple::A::~A() [vector deleting] + // CHECK-NEXT: 1 | simple::A::~A() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'simple::A::~A()' (1 entry). @@ -79,7 +79,7 @@ void use(A *obj) { obj->f(); } struct B : virtual V3 { // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries). // CHECK-NEXT: 0 | void Z::g() - // CHECK-NEXT: 1 | simple::B::~B() [vector deleting] + // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry). @@ -88,7 +88,7 @@ struct B : virtual V3 { // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries). // CHECK-NEXT: 0 | void simple::B::f() // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] - // CHECK-NEXT: 1 | simple::B::~B() [vector deleting] + // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] // CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry). @@ -115,7 +115,7 @@ void use(B *obj) { obj->f(); } struct C : virtual V4 { // CHECK-LABEL: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries). // CHECK-NEXT: 0 | void Z::g() - // CHECK-NEXT: 1 | simple::C::~C() [vector deleting] + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). @@ -124,7 +124,7 @@ struct C : virtual V4 { // CHECK-LABEL: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries). // CHECK-NEXT: 0 | void simple::C::f() // CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual] - // CHECK-NEXT: 1 | simple::C::~C() [vector deleting] + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). @@ -136,7 +136,7 @@ struct C : virtual V4 { // CHECK-LABEL: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries). // CHECK-NEXT: 0 | void simple::C::f() // CHECK-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual] - // CHECK-NEXT: 1 | simple::C::~C() [vector deleting] + // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual] // CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry). @@ -162,7 +162,7 @@ class D : B { // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'simple::D' (2 entries). // CHECK-NEXT: 0 | void simple::B::f() // CHECK-NEXT: [this adjustment: vtordisp at -12, -4 non-virtual] - // CHECK-NEXT: 1 | simple::D::~D() [vector deleting] + // CHECK-NEXT: 1 | simple::D::~D() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] D(); int z; @@ -180,12 +180,12 @@ struct F : virtual E { // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' (2 entries). // CHECK-NEXT: 0 | void simple::F::g() // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] - // CHECK-NEXT: 1 | simple::F::~F() [vector deleting] + // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' (2 entries). // CHECK-NEXT: 0 | void simple::E::f() - // CHECK-NEXT: 1 | simple::F::~F() [vector deleting] + // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] F(); @@ -202,12 +202,12 @@ struct G : F { // CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries). // CHECK-NEXT: 0 | void simple::F::g() // CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual] - // CHECK-NEXT: 1 | simple::G::~G() [vector deleting] + // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries). // CHECK-NEXT: 0 | void simple::E::f() - // CHECK-NEXT: 1 | simple::G::~G() [vector deleting] + // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual] G(); @@ -240,7 +240,7 @@ struct A : virtual simple::A { // CHECK-NEXT: 0 | void simple::A::f() // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] - // CHECK-NEXT: 1 | extended::A::~A() [vector deleting] + // CHECK-NEXT: 1 | extended::A::~A() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). @@ -265,7 +265,7 @@ struct B : virtual simple::A { // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries). // ... - // CHECK: 1 | extended::B::~B() [vector deleting] + // CHECK: 1 | extended::B::~B() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). @@ -353,7 +353,7 @@ struct G : virtual simple::A { // CHECK-NEXT: 0 | void simple::A::f() // CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left, // CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual] - // CHECK-NEXT: 1 | extended::G::~G() [vector deleting] + // CHECK-NEXT: 1 | extended::G::~G() [scalar deleting] // CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual] // CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry). @@ -374,7 +374,7 @@ void use(G *obj) { obj->g(); } struct H : Z, A { // CHECK-LABEL: VFTable for 'Z' in 'extended::H' (2 entries). // CHECK-NEXT: 0 | void Z::g() - // CHECK-NEXT: 1 | extended::H::~H() [vector deleting] + // CHECK-NEXT: 1 | extended::H::~H() [scalar deleting] // CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries). // CHECK-NEXT: 0 | void simple::A::f() diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp index e5e6ea5f42c1c..257ba270291c8 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp @@ -492,7 +492,7 @@ struct X { struct Y : virtual X { // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries). - // CHECK-NEXT: 0 | vdtors::Y::~Y() [vector deleting] + // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting] // CHECK-NEXT: 1 | void vdtors::X::zzz() // CHECK-NOT: Thunks for 'vdtors::Y::~Y()' @@ -515,7 +515,7 @@ struct U : virtual W { // CHECK-NEXT: 0 | void vdtors::Z::z() // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries). - // CHECK-NEXT: 0 | vdtors::U::~U() [vector deleting] + // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-NEXT: 1 | void vdtors::X::zzz() @@ -524,7 +524,7 @@ struct U : virtual W { // CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry). // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- - // CHECK-NEXT: 0 | vdtors::U::~U() [vector deleting] + // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting] virtual ~U(); }; @@ -536,7 +536,7 @@ struct V : virtual W { // CHECK-NEXT: 0 | void vdtors::Z::z() // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries). - // CHECK-NEXT: 0 | vdtors::V::~V() [vector deleting] + // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting] // CHECK-NEXT: [this adjustment: -4 non-virtual] // CHECK-NEXT: 1 | void vdtors::X::zzz() @@ -545,7 +545,7 @@ struct V : virtual W { // CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry). // CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 -- - // CHECK-NEXT: 0 | vdtors::V::~V() [vector deleting] + // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting] }; V v; @@ -557,7 +557,7 @@ struct T : virtual X { struct P : T, Y { // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries). - // CHECK-NEXT: 0 | vdtors::P::~P() [vector deleting] + // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting] // CHECK-NEXT: 1 | void vdtors::X::zzz() // CHECK-NOT: Thunks for 'vdtors::P::~P()' @@ -574,18 +574,18 @@ struct Q { // PR19172: Yet another diamond we miscompiled. struct R : virtual Q, X { // CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry). - // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting] + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] // CHECK-NEXT: [this adjustment: -8 non-virtual] // CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry). // CHECK-NEXT: 0 | [this adjustment: -8 non-virtual] // CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries). - // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting] + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] // CHECK-NEXT: 1 | void vdtors::X::zzz() // CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry). - // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting] + // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting] virtual ~R(); }; diff --git a/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp index c8e374e51a031..069f0226ab948 100644 --- a/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp +++ b/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp @@ -2,7 +2,7 @@ // vftable shouldn't have RTTI data in it. // CHECK-NOT: @"??_R4S@@6B@" -// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI@Z"] }, comdat +// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GS@@UAEPAXI@Z"] }, comdat struct type_info; namespace std { using ::type_info; } diff --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp deleted file mode 100644 index ebff4f6a851b0..0000000000000 --- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm %s -triple=x86_64-pc-windows-msvc -o - | FileCheck --check-prefixes=X64,CHECK %s -// RUN: %clang_cc1 -emit-llvm %s -triple=i386-pc-windows-msvc -o - | FileCheck --check-prefixes=X86,CHECK %s - -struct Bird { - virtual ~Bird(); -}; - -struct Parrot : public Bird { -// X64: @[[ParrotVtable:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Parrot@@6B@", ptr @"??_EParrot@@UEAAPEAXI@Z"] }, comdat($"??_7Parrot@@6B@") -// X86: @[[ParrotVtable:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Parrot@@6B@", ptr @"??_EParrot@@UAEPAXI@Z"] }, comdat($"??_7Parrot@@6B@") -// X64: @[[Bird:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Bird@@6B@", ptr @"??_EBird@@UEAAPEAXI@Z"] }, comdat($"??_7Bird@@6B@") -// X86: @[[Bird:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Bird@@6B@", ptr @"??_EBird@@UAEPAXI@Z"] }, comdat($"??_7Bird@@6B@") - virtual ~Parrot() {} -}; - -Bird::~Bird() {} - -// For the weird bird we first emit scalar deleting destructor, then find out -// that we need vector deleting destructor and remove the alias. -struct JustAWeirdBird { - virtual ~JustAWeirdBird() {} - - bool doSmth(int n) { - JustAWeirdBird *c = new JustAWeirdBird[n]; - - delete[] c; - return true; - } -}; - -// Vector deleting dtor for Bird is an alias because no new Bird[] expressions -// in the TU. -// X64: @"??_EBird@@UEAAPEAXI@Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UEAAPEAXI@Z" -// X86: @"??_EBird@@UAEPAXI@Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UAEPAXI@Z" -// No scalar destructor for Parrot. -// CHECK-NOT: @"??_GParrot" -// No vector destructor definition for Bird. -// CHECK-NOT: define{{.*}}@"??_EBird" -// No scalar deleting dtor for JustAWeirdBird. -// CHECK-NOT: @"??_GJustAWeirdBird" - -void dealloc(Bird *p) { - delete[] p; -} - -Bird* alloc() { - Parrot* P = new Parrot[38]; - return P; -} - -void bar() { - dealloc(alloc()); - - JustAWeirdBird B; - B.doSmth(38); -} - -// CHECK-LABEL: define dso_local void @{{.*}}dealloc{{.*}}( -// CHECK-SAME: ptr noundef %[[PTR:.*]]) -// CHECK: entry: -// CHECK-NEXT: %[[PTRADDR:.*]] = alloca ptr -// CHECK-NEXT: store ptr %[[PTR]], ptr %[[PTRADDR]] -// CHECK-NEXT: %[[LPTR:.*]] = load ptr, ptr %[[PTRADDR]] -// CHECK-NEXT: %[[ISNULL:.*]] = icmp eq ptr %[[LPTR]], null -// CHECK-NEXT: br i1 %[[ISNULL]], label %delete.end, label %delete.notnull -// CHECK: delete.notnull: -// X64-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LPTR]], i64 -8 -// X86-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LPTR]], i32 -4 -// X64-NEXT: %[[HOWMANY:.*]] = load i64, ptr %[[COOKIEGEP]] -// X86-NEXT: %[[HOWMANY:.*]] = load i32, ptr %[[COOKIEGEP]] -// X64-NEXT: %[[ISNOELEM:.*]] = icmp eq i64 %2, 0 -// X86-NEXT: %[[ISNOELEM:.*]] = icmp eq i32 %2, 0 -// CHECK-NEXT: br i1 %[[ISNOELEM]], label %vdtor.nocall, label %vdtor.call -// CHECK: vdtor.nocall: -// X64-NEXT: %[[HOWMANYBYTES:.*]] = mul i64 8, %[[HOWMANY]] -// X86-NEXT: %[[HOWMANYBYTES:.*]] = mul i32 4, %[[HOWMANY]] -// X64-NEXT: %[[ADDCOOKIESIZE:.*]] = add i64 %[[HOWMANYBYTES]], 8 -// X86-NEXT: %[[ADDCOOKIESIZE:.*]] = add i32 %[[HOWMANYBYTES]], 4 -// X64-NEXT: call void @"??_V@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef %[[ADDCOOKIESIZE]]) -// X86-NEXT: call void @"??_V@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef %[[ADDCOOKIESIZE]]) -// CHECK-NEXT: br label %delete.end -// CHECK: vdtor.call: -// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[LPTR]] -// CHECK-NEXT: %[[FPGEP:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0 -// CHECK-NEXT: %[[FPLOAD:.*]] = load ptr, ptr %[[FPGEP]] -// X64-NEXT: %[[CALL:.*]] = call noundef ptr %[[FPLOAD]](ptr noundef nonnull align 8 dereferenceable(8) %[[LPTR]], i32 noundef 3) -// X86-NEXT: %[[CALL:.*]] = call x86_thiscallcc noundef ptr %[[FPLOAD]](ptr noundef nonnull align 4 dereferenceable(4) %[[LPTR]], i32 noundef 3) -// CHECK-NEXT: br label %delete.end -// CHECK: delete.end: -// CHECK-NEXT: ret void - -// Vector dtor definition for Parrot. -// X64-LABEL: define weak dso_local noundef ptr @"??_EParrot@@UEAAPEAXI@Z"( -// X64-SAME: ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[IMPLICIT_PARAM:.*]]) unnamed_addr -// X86-LABEL: define weak dso_local x86_thiscallcc noundef ptr @"??_EParrot@@UAEPAXI@Z"( -// X86-SAME: ptr noundef nonnull align 4 dereferenceable(4) %[[THIS:.*]], i32 noundef %[[IMPLICIT_PARAM:.*]]) unnamed_addr -// CHECK: entry: -// CHECK-NEXT: %[[RET:.*]] = alloca ptr -// CHECK-NEXT: %[[IPADDR:.*]] = alloca i32 -// CHECK-NEXT: %[[THISADDR:.*]] = alloca ptr -// CHECK-NEXT: store i32 %[[IMPLICIT_PARAM]], ptr %[[IPADDR]] -// CHECK-NEXT: store ptr %[[THIS]], ptr %[[THISADDR]] -// CHECK-NEXT: %[[LTHIS:.*]] = load ptr, ptr %[[THISADDR]] -// CHECK-NEXT: store ptr %[[LTHIS]], ptr %[[RET]] -// CHECK-NEXT: %[[LIP:.*]] = load i32, ptr %[[IPADDR]] -// CHECK-NEXT: %[[SECONDBIT:.*]] = and i32 %[[LIP]], 2 -// CHECK-NEXT: %[[ISSECONDBITZERO:.*]] = icmp eq i32 %[[SECONDBIT]], 0 -// CHECK-NEXT: br i1 %[[ISSECONDBITZERO:.*]], label %dtor.scalar, label %dtor.vector -// CHECK: dtor.vector: -// X64-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LTHIS]], i64 -8 -// X86-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LTHIS]], i32 -4 -// X64-NEXT: %[[HOWMANY:.*]] = load i64, ptr %[[COOKIEGEP]] -// X86-NEXT: %[[HOWMANY:.*]] = load i32, ptr %[[COOKIEGEP]] -// X64-NEXT: %[[END:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[LTHIS]], i64 %[[HOWMANY]] -// X86-NEXT: %[[END:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[LTHIS]], i32 %[[HOWMANY]] -// CHECK-NEXT: br label %arraydestroy.body -// CHECK: arraydestroy.body: -// CHECK-NEXT: %[[PASTELEM:.*]] = phi ptr [ %delete.end, %dtor.vector ], [ %arraydestroy.element, %arraydestroy.body ] -// X64-NEXT: %[[CURELEM:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[PASTELEM]], i64 -1 -// X86-NEXT: %[[CURELEM:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[PASTELEM]], i32 -1 -// X64-NEXT: call void @"??1Parrot@@UEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[CURELEM]]) -// X86-NEXT: call x86_thiscallcc void @"??1Parrot@@UAE@XZ"(ptr noundef nonnull align 4 dereferenceable(4) %[[CURELEM]]) -// CHECK-NEXT: %[[DONE:.*]] = icmp eq ptr %[[CURELEM]], %[[LTHIS]] -// CHECK-NEXT: br i1 %[[DONE]], label %arraydestroy.done3, label %arraydestroy.body -// CHECK: arraydestroy.done3: -// CHECK-NEXT: br label %dtor.vector.cont -// CHECK: dtor.vector.cont: -// CHECK-NEXT: %[[FIRSTBIT:.*]] = and i32 %[[LIP]], 1 -// CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0 -// CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete_after_array_destroy -// CHECK: dtor.call_delete_after_array_destroy: -// X64-NEXT: call void @"??3@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8) -// X86-NEXT: call void @"??3@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef 4) -// CHECK-NEXT: br label %dtor.continue -// CHECK: dtor.scalar: -// X64-NEXT: call void @"??1Parrot@@UEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[LTHIS]]) -// X86-NEXT: call x86_thiscallcc void @"??1Parrot@@UAE@XZ"(ptr noundef nonnull align 4 dereferenceable(4) %[[LTHIS]]) -// CHECK-NEXT: %[[FIRSTBIT:.*]] = and i32 %[[LIP]], 1 -// CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0 -// CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete -// CHECK: dtor.call_delete: -// X64-NEXT: call void @"??3@YAXPEAX_K@Z"(ptr noundef %[[LTHIS]], i64 noundef 8) -// X86-NEXT: call void @"??3@YAXPAXI@Z"(ptr noundef %[[LTHIS]], i32 noundef 4) -// CHECK-NEXT: br label %dtor.continue -// CHECK: dtor.continue: -// CHECK-NEXT: %[[LOADRET:.*]] = load ptr, ptr %[[RET]] -// CHECK-NEXT: ret ptr %[[LOADRET]] - -// X64: define weak dso_local noundef ptr @"??_EJustAWeirdBird@@UEAAPEAXI@Z"( -// X64-SAME: ptr noundef nonnull align 8 dereferenceable(8) %this, i32 noundef %should_call_delete) -// X86: define weak dso_local x86_thiscallcc noundef ptr @"??_EJustAWeirdBird@@UAEPAXI@Z"( -// X86-SAME: ptr noundef nonnull align 4 dereferenceable(4) %this, i32 noundef %should_call_delete) unnamed_addr diff --git a/clang/test/CodeGenCXX/vtable-consteval.cpp b/clang/test/CodeGenCXX/vtable-consteval.cpp index 220143465c574..1454f6fde357d 100644 --- a/clang/test/CodeGenCXX/vtable-consteval.cpp +++ b/clang/test/CodeGenCXX/vtable-consteval.cpp @@ -26,7 +26,7 @@ struct B { B b; // ITANIUM-DAG: @_ZTV1C = {{.*}} constant { [4 x ptr] } {{.*}} null, ptr @_ZTI1C, ptr @_ZN1CD1Ev, ptr @_ZN1CD0Ev -// MSABI-DAG: @[[C_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4C@@6B@", ptr @"??_EC@@UEAAPEAXI@Z" +// MSABI-DAG: @[[C_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4C@@6B@", ptr @"??_GC@@UEAAPEAXI@Z" struct C { virtual ~C() = default; virtual consteval C &operator=(const C&) = default; @@ -36,7 +36,7 @@ struct C { C c; // ITANIUM-DAG: @_ZTV1D = {{.*}} constant { [4 x ptr] } {{.*}} null, ptr @_ZTI1D, ptr @_ZN1DD1Ev, ptr @_ZN1DD0Ev -// MSABI-DAG: @[[D_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4D@@6B@", ptr @"??_ED@@UEAAPEAXI@Z" +// MSABI-DAG: @[[D_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4D@@6B@", ptr @"??_GD@@UEAAPEAXI@Z" struct D : C {}; // ITANIUM-DAG: @d = {{.*}}global { ptr } { {{.*}} @_ZTV1D, // MSABI-DAG: @"?d@@3UD@@A" = {{.*}}global { ptr } { ptr @"??_7D@@6B@" } diff --git a/clang/test/Modules/vtable-windows.cppm b/clang/test/Modules/vtable-windows.cppm index e45e32d6b4d60..dbde24c8a9bdd 100644 --- a/clang/test/Modules/vtable-windows.cppm +++ b/clang/test/Modules/vtable-windows.cppm @@ -23,4 +23,4 @@ void test() { // Check that the virtual table is an unnamed_addr constant in comdat that can // be merged with the virtual table with other TUs. -// CHECK: unnamed_addr constant {{.*}}[ptr @"??_R4Fruit@@6B@", ptr @"??_EFruit@@UAEPAXI@Z", ptr @"?eval@Fruit@@UAEXXZ"{{.*}}comdat($"??_7Fruit@@6B@") +// CHECK: unnamed_addr constant {{.*}}[ptr @"??_R4Fruit@@6B@", ptr @"??_GFruit@@UAEPAXI@Z", ptr @"?eval@Fruit@@UAEXXZ"{{.*}}comdat($"??_7Fruit@@6B@") diff --git a/clang/test/Profile/cxx-abc-deleting-dtor.cpp b/clang/test/Profile/cxx-abc-deleting-dtor.cpp index 7c2a5bbc93af3..c65a8e8013c35 100644 --- a/clang/test/Profile/cxx-abc-deleting-dtor.cpp +++ b/clang/test/Profile/cxx-abc-deleting-dtor.cpp @@ -24,15 +24,16 @@ DerivedABC *useABCVTable() { return new DerivedABC(); } // MSVC: @"__profn_??1ABC@@{{.*}}" = // MSVC-NOT: @"__profn_??_G{{.*}}" = +// MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GDerivedABC@@UEAAPEAXI@Z"(ptr {{[^,]*}} %this, {{.*}}) +// MSVC-NOT: call void @llvm.instrprof.increment({{.*}}) +// MSVC: call void @"??1DerivedABC@@UEAA@XZ"({{.*}}) +// MSVC: ret void + // MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GABC@@UEAAPEAXI@Z"(ptr {{[^,]*}} %this, {{.*}}) // MSVC-NOT: call void @llvm.instrprof.increment({{.*}}) // MSVC: call void @llvm.trap() // MSVC-NEXT: unreachable -// MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GDerivedABC@@UEAAPEAXI@Z"(ptr {{[^,]*}} %this, {{.*}}) -// MSVC-NOT: call void @llvm.instrprof.increment({{.*}}) -// MSVC: call void @"??1DerivedABC@@UEAA@XZ"({{.*}}) - // MSVC-LABEL: define linkonce_odr dso_local void @"??1DerivedABC@@UEAA@XZ"({{.*}}) // MSVC: call void @llvm.instrprof.increment({{.*}}) // MSVC: call void @"??1ABC@@UEAA@XZ"({{.*}}) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits