[clang] [clang][Interp] Check for 'delete this' in dtors (PR #101792)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 21:47:32 PDT 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/101792
None
>From 08aaea88863ad000d68316391a8702cd777496af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 3 Aug 2024 06:37:24 +0200
Subject: [PATCH] [clang][Interp] Check for 'delete this' in dtors
---
clang/lib/AST/Interp/Interp.cpp | 6 ++++++
clang/lib/AST/Interp/Pointer.cpp | 6 ++++++
clang/lib/AST/Interp/Pointer.h | 2 ++
clang/test/AST/Interp/new-delete.cpp | 13 +++++++++++++
4 files changed, 27 insertions(+)
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 9009cf820244d..0252dd0d32699 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -836,6 +836,12 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
const Record *R = Desc->ElemRecord;
assert(R);
+ if (Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
+ const SourceInfo &Loc = S.Current->getSource(OpPC);
+ S.FFDiag(Loc, diag::note_constexpr_double_destroy);
+ return false;
+ }
+
// Fields.
for (const Record::Field &Field : llvm::reverse(R->fields())) {
const Descriptor *D = Field.Desc;
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index 79fe317a61dff..f86be1214826d 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -398,6 +398,12 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
return A.asBlockPointer().Pointee == B.asBlockPointer().Pointee;
}
+bool Pointer::pointToSameBlock(const Pointer &A, const Pointer &B) {
+ if (!A.isBlockPointer() || !B.isBlockPointer())
+ return false;
+ return A.block() == B.block();
+}
+
bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
return hasSameBase(A, B) &&
A.PointeeStorage.BS.Base == B.PointeeStorage.BS.Base &&
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 6b0c31358159c..6f6983458ab60 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -665,6 +665,8 @@ class Pointer {
static bool hasSameBase(const Pointer &A, const Pointer &B);
/// Checks if two pointers can be subtracted.
static bool hasSameArray(const Pointer &A, const Pointer &B);
+ /// Checks if both given pointers point to the same block.
+ static bool pointToSameBlock(const Pointer &A, const Pointer &B);
/// Prints the pointer.
void print(llvm::raw_ostream &OS) const;
diff --git a/clang/test/AST/Interp/new-delete.cpp b/clang/test/AST/Interp/new-delete.cpp
index 7a85def784920..ae76950f13731 100644
--- a/clang/test/AST/Interp/new-delete.cpp
+++ b/clang/test/AST/Interp/new-delete.cpp
@@ -551,6 +551,19 @@ namespace FaultyDtorCalledByDelete {
// both-note {{in call to 'abc()'}}
}
+namespace DeleteThis {
+ constexpr bool super_secret_double_delete() {
+ struct A {
+ constexpr ~A() { delete this; } // both-note {{destruction of object that is already being destroyed}} \
+ // ref-note {{in call to}}
+ };
+ delete new A; // both-note {{in call to}}
+ return true;
+ }
+ static_assert(super_secret_double_delete()); // both-error {{not an integral constant expression}} \
+ // both-note {{in call to 'super_secret_double_delete()'}}
+}
+
#else
/// Make sure we reject this prior to C++20
More information about the cfe-commits
mailing list