aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-07-10 07:33:33 +0200
committerGitHub <noreply@github.com>2025-07-10 07:33:33 +0200
commit36cbd43ae8d5a5274ae3193b6383fff2ba9671f4 (patch)
treeda81f8723356f411e8533539e63505cc53e91803 /clang/lib/AST/ByteCode
parent00a85e57049ee637a6089b2c696d5e37db8cd47b (diff)
downloadllvm-36cbd43ae8d5a5274ae3193b6383fff2ba9671f4.zip
llvm-36cbd43ae8d5a5274ae3193b6383fff2ba9671f4.tar.gz
llvm-36cbd43ae8d5a5274ae3193b6383fff2ba9671f4.tar.bz2
[clang][bytecode] Check new/delete mismatch earlier (#147732)
This fixes a mismatch in diagnostic output with the current intepreter.
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp32
1 files changed, 18 insertions, 14 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 51cf0c5..be77657 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1196,6 +1196,8 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
if (!CheckDynamicMemoryAllocation(S, OpPC))
return false;
+ DynamicAllocator &Allocator = S.getAllocator();
+
const Expr *Source = nullptr;
const Block *BlockToDelete = nullptr;
{
@@ -1212,6 +1214,21 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
while (Ptr.isBaseClass())
Ptr = Ptr.getBase();
+ Source = Ptr.getDeclDesc()->asExpr();
+ BlockToDelete = Ptr.block();
+
+ // Check that new[]/delete[] or new/delete were used, not a mixture.
+ const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
+ if (std::optional<DynamicAllocator::Form> AllocForm =
+ Allocator.getAllocationForm(Source)) {
+ DynamicAllocator::Form DeleteForm =
+ DeleteIsArrayForm ? DynamicAllocator::Form::Array
+ : DynamicAllocator::Form::NonArray;
+ if (!CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
+ Source))
+ return false;
+ }
+
// For the non-array case, the types must match if the static type
// does not have a virtual destructor.
if (!DeleteIsArrayForm && Ptr.getType() != InitialType &&
@@ -1230,9 +1247,6 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
return false;
}
- Source = Ptr.getDeclDesc()->asExpr();
- BlockToDelete = Ptr.block();
-
if (!CheckDeleteSource(S, OpPC, Source, Ptr))
return false;
@@ -1266,11 +1280,6 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
if (!RunDestructors(S, OpPC, BlockToDelete))
return false;
- DynamicAllocator &Allocator = S.getAllocator();
- const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
- std::optional<DynamicAllocator::Form> AllocForm =
- Allocator.getAllocationForm(Source);
-
if (!Allocator.deallocate(Source, BlockToDelete, S)) {
// Nothing has been deallocated, this must be a double-delete.
const SourceInfo &Loc = S.Current->getSource(OpPC);
@@ -1278,12 +1287,7 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
return false;
}
- assert(AllocForm);
- DynamicAllocator::Form DeleteForm = DeleteIsArrayForm
- ? DynamicAllocator::Form::Array
- : DynamicAllocator::Form::NonArray;
- return CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
- Source);
+ return true;
}
void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,