Skip to content

Commit c38befd

Browse files
authored
[clang][bytecode] Fix delete[] dtor order (#128411)
As always, call array dtors in reverse order.
1 parent 2071ea2 commit c38befd

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,11 +1015,14 @@ static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
10151015
assert(Desc->isRecord() || Desc->isCompositeArray());
10161016

10171017
if (Desc->isCompositeArray()) {
1018+
unsigned N = Desc->getNumElems();
1019+
if (N == 0)
1020+
return true;
10181021
const Descriptor *ElemDesc = Desc->ElemDesc;
10191022
assert(ElemDesc->isRecord());
10201023

10211024
Pointer RP(const_cast<Block *>(B));
1022-
for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
1025+
for (int I = static_cast<int>(N) - 1; I >= 0; --I) {
10231026
if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
10241027
return false;
10251028
}

clang/test/AST/ByteCode/new-delete.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,26 @@ namespace ArrayBaseCast {
942942
static_assert(test());
943943
}
944944

945+
namespace PR45350 {
946+
int q;
947+
struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }};
948+
constexpr int f(int n) {
949+
int k = 0;
950+
V *p = new V[n];
951+
for (int i = 0; i != n; ++i) {
952+
if (p[i].p != &p[i].n) return -1;
953+
p[i].n = i;
954+
p[i].p = &k;
955+
}
956+
delete[] p;
957+
return k;
958+
}
959+
// [expr.delete]p6:
960+
// In the case of an array, the elements will be destroyed in order of
961+
// decreasing address
962+
static_assert(f(6) == 543210);
963+
}
964+
945965
#else
946966
/// Make sure we reject this prior to C++20
947967
constexpr int a() { // both-error {{never produces a constant expression}}

0 commit comments

Comments
 (0)