Skip to content

Commit ea18a40

Browse files
authored
[clang][Interp] Check for 'delete this' in dtors (#101792)
1 parent d631ebb commit ea18a40

File tree

4 files changed

+27
-0
lines changed

4 files changed

+27
-0
lines changed

clang/lib/AST/Interp/Interp.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,12 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
836836
const Record *R = Desc->ElemRecord;
837837
assert(R);
838838

839+
if (Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
840+
const SourceInfo &Loc = S.Current->getSource(OpPC);
841+
S.FFDiag(Loc, diag::note_constexpr_double_destroy);
842+
return false;
843+
}
844+
839845
// Fields.
840846
for (const Record::Field &Field : llvm::reverse(R->fields())) {
841847
const Descriptor *D = Field.Desc;

clang/lib/AST/Interp/Pointer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,12 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
398398
return A.asBlockPointer().Pointee == B.asBlockPointer().Pointee;
399399
}
400400

401+
bool Pointer::pointToSameBlock(const Pointer &A, const Pointer &B) {
402+
if (!A.isBlockPointer() || !B.isBlockPointer())
403+
return false;
404+
return A.block() == B.block();
405+
}
406+
401407
bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
402408
return hasSameBase(A, B) &&
403409
A.PointeeStorage.BS.Base == B.PointeeStorage.BS.Base &&

clang/lib/AST/Interp/Pointer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ class Pointer {
665665
static bool hasSameBase(const Pointer &A, const Pointer &B);
666666
/// Checks if two pointers can be subtracted.
667667
static bool hasSameArray(const Pointer &A, const Pointer &B);
668+
/// Checks if both given pointers point to the same block.
669+
static bool pointToSameBlock(const Pointer &A, const Pointer &B);
668670

669671
/// Prints the pointer.
670672
void print(llvm::raw_ostream &OS) const;

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,19 @@ namespace FaultyDtorCalledByDelete {
551551
// both-note {{in call to 'abc()'}}
552552
}
553553

554+
namespace DeleteThis {
555+
constexpr bool super_secret_double_delete() {
556+
struct A {
557+
constexpr ~A() { delete this; } // both-note {{destruction of object that is already being destroyed}} \
558+
// ref-note {{in call to}}
559+
};
560+
delete new A; // both-note {{in call to}}
561+
return true;
562+
}
563+
static_assert(super_secret_double_delete()); // both-error {{not an integral constant expression}} \
564+
// both-note {{in call to 'super_secret_double_delete()'}}
565+
}
566+
554567

555568
#else
556569
/// Make sure we reject this prior to C++20

0 commit comments

Comments
 (0)