@@ -1196,6 +1196,8 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
11961196 if (!CheckDynamicMemoryAllocation (S, OpPC))
11971197 return false ;
11981198
1199+ DynamicAllocator &Allocator = S.getAllocator ();
1200+
11991201 const Expr *Source = nullptr ;
12001202 const Block *BlockToDelete = nullptr ;
12011203 {
@@ -1212,6 +1214,21 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
12121214 while (Ptr.isBaseClass ())
12131215 Ptr = Ptr.getBase ();
12141216
1217+ Source = Ptr.getDeclDesc ()->asExpr ();
1218+ BlockToDelete = Ptr.block ();
1219+
1220+ // Check that new[]/delete[] or new/delete were used, not a mixture.
1221+ const Descriptor *BlockDesc = BlockToDelete->getDescriptor ();
1222+ if (std::optional<DynamicAllocator::Form> AllocForm =
1223+ Allocator.getAllocationForm (Source)) {
1224+ DynamicAllocator::Form DeleteForm =
1225+ DeleteIsArrayForm ? DynamicAllocator::Form::Array
1226+ : DynamicAllocator::Form::NonArray;
1227+ if (!CheckNewDeleteForms (S, OpPC, *AllocForm, DeleteForm, BlockDesc,
1228+ Source))
1229+ return false ;
1230+ }
1231+
12151232 // For the non-array case, the types must match if the static type
12161233 // does not have a virtual destructor.
12171234 if (!DeleteIsArrayForm && Ptr.getType () != InitialType &&
@@ -1230,9 +1247,6 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
12301247 return false ;
12311248 }
12321249
1233- Source = Ptr.getDeclDesc ()->asExpr ();
1234- BlockToDelete = Ptr.block ();
1235-
12361250 if (!CheckDeleteSource (S, OpPC, Source, Ptr))
12371251 return false ;
12381252
@@ -1266,24 +1280,14 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
12661280 if (!RunDestructors (S, OpPC, BlockToDelete))
12671281 return false ;
12681282
1269- DynamicAllocator &Allocator = S.getAllocator ();
1270- const Descriptor *BlockDesc = BlockToDelete->getDescriptor ();
1271- std::optional<DynamicAllocator::Form> AllocForm =
1272- Allocator.getAllocationForm (Source);
1273-
12741283 if (!Allocator.deallocate (Source, BlockToDelete, S)) {
12751284 // Nothing has been deallocated, this must be a double-delete.
12761285 const SourceInfo &Loc = S.Current ->getSource (OpPC);
12771286 S.FFDiag (Loc, diag::note_constexpr_double_delete);
12781287 return false ;
12791288 }
12801289
1281- assert (AllocForm);
1282- DynamicAllocator::Form DeleteForm = DeleteIsArrayForm
1283- ? DynamicAllocator::Form::Array
1284- : DynamicAllocator::Form::NonArray;
1285- return CheckNewDeleteForms (S, OpPC, *AllocForm, DeleteForm, BlockDesc,
1286- Source);
1290+ return true ;
12871291}
12881292
12891293void diagnoseEnumValue (InterpState &S, CodePtr OpPC, const EnumDecl *ED,
0 commit comments