[clang][bytecode] Check new/delete mismatch earlier (#147732)
This fixes a mismatch in diagnostic output with the current intepreter.
This commit is contained in:
parent
00a85e5704
commit
36cbd43ae8
@ -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,
|
||||
|
@ -171,6 +171,20 @@ namespace Arrays {
|
||||
}
|
||||
static_assert(mismatch2() == 6); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to 'mismatch2()'}}
|
||||
|
||||
constexpr int mismatch3() { // both-error {{never produces a constant expression}}
|
||||
int a = 0;
|
||||
struct S {};
|
||||
struct T : S {};
|
||||
T *p = new T[3]{}; // both-note 2{{heap allocation performed here}}
|
||||
delete (S*)p; // both-note 2{{non-array delete used to delete pointer to array object of type 'T[3]'}}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
static_assert(mismatch3() == 0); // both-error {{not an integral constant expression}} \
|
||||
// both-note {{in call to}}
|
||||
|
||||
/// Array of composite elements.
|
||||
constexpr int foo() {
|
||||
S *ss = new S[12];
|
||||
|
Loading…
x
Reference in New Issue
Block a user