Skip to content

Commit 8a691cc

Browse files
authored
[MS][clang] Make sure vector deleting dtor calls correct operator delete (llvm#133950)
During additional testing I spotted that vector deleting dtor calls operator delete, not operator delete[] when performing array deletion. This patch fixes that.
1 parent 5d36448 commit 8a691cc

File tree

7 files changed

+52
-10
lines changed

7 files changed

+52
-10
lines changed

clang/include/clang/AST/DeclCXX.h

+6
Original file line numberDiff line numberDiff line change
@@ -2852,6 +2852,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
28522852
// FIXME: Don't allocate storage for these except in the first declaration
28532853
// of a virtual destructor.
28542854
FunctionDecl *OperatorDelete = nullptr;
2855+
FunctionDecl *OperatorArrayDelete = nullptr;
28552856
Expr *OperatorDeleteThisArg = nullptr;
28562857

28572858
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2877,11 +2878,16 @@ class CXXDestructorDecl : public CXXMethodDecl {
28772878
static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
28782879

28792880
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
2881+
void setOperatorArrayDelete(FunctionDecl *OD, Expr *ThisArg);
28802882

28812883
const FunctionDecl *getOperatorDelete() const {
28822884
return getCanonicalDecl()->OperatorDelete;
28832885
}
28842886

2887+
const FunctionDecl *getArrayOperatorDelete() const {
2888+
return getCanonicalDecl()->OperatorArrayDelete;
2889+
}
2890+
28852891
Expr *getOperatorDeleteThisArg() const {
28862892
return getCanonicalDecl()->OperatorDeleteThisArg;
28872893
}

clang/include/clang/Sema/Sema.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -8335,7 +8335,8 @@ class Sema final : public SemaBase {
83358335
bool Overaligned,
83368336
DeclarationName Name);
83378337
FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
8338-
CXXRecordDecl *RD);
8338+
CXXRecordDecl *RD,
8339+
DeclarationName Name);
83398340

83408341
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
83418342
/// @code ::delete ptr; @endcode

clang/lib/AST/DeclCXX.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -3026,6 +3026,13 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
30263026
}
30273027
}
30283028

3029+
void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD,
3030+
Expr *ThisArg) {
3031+
auto *First = cast<CXXDestructorDecl>(getFirstDecl());
3032+
if (OD && !First->OperatorArrayDelete)
3033+
First->OperatorArrayDelete = OD;
3034+
}
3035+
30293036
bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
30303037
// C++20 [expr.delete]p6: If the value of the operand of the delete-
30313038
// expression is not a null pointer value and the selected deallocation

clang/lib/CodeGen/CGClass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
14891489
CGF.EmitBlock(callDeleteBB);
14901490
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
14911491
const CXXRecordDecl *ClassDecl = Dtor->getParent();
1492-
CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr,
1492+
CGF.EmitDeleteCall(Dtor->getArrayOperatorDelete(), allocatedPtr,
14931493
CGF.getContext().getTagDeclType(ClassDecl));
14941494

14951495
CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);

clang/lib/Sema/SemaDeclCXX.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -11042,9 +11042,11 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
1104211042
else
1104311043
Loc = RD->getLocation();
1104411044

11045+
DeclarationName Name =
11046+
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
1104511047
// If we have a virtual destructor, look up the deallocation function
1104611048
if (FunctionDecl *OperatorDelete =
11047-
FindDeallocationFunctionForDestructor(Loc, RD)) {
11049+
FindDeallocationFunctionForDestructor(Loc, RD, Name)) {
1104811050
Expr *ThisArg = nullptr;
1104911051

1105011052
// If the notional 'delete this' expression requires a non-trivial
@@ -11075,6 +11077,15 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
1107511077
DiagnoseUseOfDecl(OperatorDelete, Loc);
1107611078
MarkFunctionReferenced(Loc, OperatorDelete);
1107711079
Destructor->setOperatorDelete(OperatorDelete, ThisArg);
11080+
// Lookup delete[] too in case we have to emit a vector deleting dtor;
11081+
DeclarationName VDeleteName =
11082+
Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
11083+
FunctionDecl *ArrOperatorDelete =
11084+
FindDeallocationFunctionForDestructor(Loc, RD, VDeleteName);
11085+
// delete[] in the TU will make sure the operator is referenced and its
11086+
// uses diagnosed, otherwise vector deleting dtor won't be called anyway,
11087+
// so just record it in the destructor.
11088+
Destructor->setOperatorArrayDelete(ArrOperatorDelete, ThisArg);
1107811089
}
1107911090
}
1108011091

clang/lib/Sema/SemaExprCXX.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -3265,18 +3265,16 @@ FunctionDecl *Sema::FindUsualDeallocationFunction(SourceLocation StartLoc,
32653265
return Result.FD;
32663266
}
32673267

3268-
FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc,
3269-
CXXRecordDecl *RD) {
3270-
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete);
3268+
FunctionDecl *Sema::FindDeallocationFunctionForDestructor(
3269+
SourceLocation Loc, CXXRecordDecl *RD, DeclarationName Name) {
32713270

32723271
FunctionDecl *OperatorDelete = nullptr;
32733272
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
32743273
return nullptr;
32753274
if (OperatorDelete)
32763275
return OperatorDelete;
32773276

3278-
// If there's no class-specific operator delete, look up the global
3279-
// non-array delete.
3277+
// If there's no class-specific operator delete, look up the global delete.
32803278
return FindUsualDeallocationFunction(
32813279
Loc, true, hasNewExtendedAlignment(*this, Context.getRecordType(RD)),
32823280
Name);

clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ struct JustAWeirdBird {
2828
}
2929
};
3030

31+
int i = 0;
32+
struct HasOperatorDelete : public Bird{
33+
~HasOperatorDelete() { }
34+
void operator delete(void *p) { i-=2; }
35+
void operator delete[](void *p) { i--; }
36+
};
37+
3138
// Vector deleting dtor for Bird is an alias because no new Bird[] expressions
3239
// in the TU.
3340
// X64: @"??_EBird@@UEAAPEAXI@Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UEAAPEAXI@Z"
@@ -53,6 +60,9 @@ void bar() {
5360

5461
JustAWeirdBird B;
5562
B.doSmth(38);
63+
64+
Bird *p = new HasOperatorDelete[2];
65+
dealloc(p);
5666
}
5767

5868
// CHECK-LABEL: define dso_local void @{{.*}}dealloc{{.*}}(
@@ -129,8 +139,8 @@ void bar() {
129139
// CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0
130140
// CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete_after_array_destroy
131141
// CHECK: dtor.call_delete_after_array_destroy:
132-
// X64-NEXT: call void @"??3@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8)
133-
// X86-NEXT: call void @"??3@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef 4)
142+
// X64-NEXT: call void @"??_V@YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8)
143+
// X86-NEXT: call void @"??_V@YAXPAXI@Z"(ptr noundef %[[COOKIEGEP]], i32 noundef 4)
134144
// CHECK-NEXT: br label %dtor.continue
135145
// CHECK: dtor.scalar:
136146
// X64-NEXT: call void @"??1Parrot@@UEAA@XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[LTHIS]])
@@ -150,3 +160,12 @@ void bar() {
150160
// X64-SAME: ptr noundef nonnull align 8 dereferenceable(8) %this, i32 noundef %should_call_delete)
151161
// X86: define weak dso_local x86_thiscallcc noundef ptr @"??_EJustAWeirdBird@@UAEPAXI@Z"(
152162
// X86-SAME: ptr noundef nonnull align 4 dereferenceable(4) %this, i32 noundef %should_call_delete) unnamed_addr
163+
164+
// X64-LABEL: define weak dso_local noundef ptr @"??_EHasOperatorDelete@@UEAAPEAXI@Z"
165+
// X86-LABEL: define weak dso_local x86_thiscallcc noundef ptr @"??_EHasOperatorDelete@@UAEPAXI@Z"
166+
// CHECK: dtor.call_delete_after_array_destroy:
167+
// X64-NEXT: call void @"??_VHasOperatorDelete@@SAXPEAX@Z"
168+
// X86-NEXT: call void @"??_VHasOperatorDelete@@SAXPAX@Z"
169+
// CHECK: dtor.call_delete:
170+
// X64-NEXT: call void @"??3HasOperatorDelete@@SAXPEAX@Z"
171+
// X86-NEXT: call void @"??3HasOperatorDelete@@SAXPAX@Z"

0 commit comments

Comments
 (0)