[clang] ea18a40 - [clang][Interp] Check for 'delete this' in dtors (#101792)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 22:16:25 PDT 2024
Author: Timm Baeder
Date: 2024-08-03T07:16:21+02:00
New Revision: ea18a40ed920b11ef35c3cfdd7e5f0b4bc796da4
URL: https://github.com/llvm/llvm-project/commit/ea18a40ed920b11ef35c3cfdd7e5f0b4bc796da4
DIFF: https://github.com/llvm/llvm-project/commit/ea18a40ed920b11ef35c3cfdd7e5f0b4bc796da4.diff
LOG: [clang][Interp] Check for 'delete this' in dtors (#101792)
Added:
Modified:
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/new-delete.cpp
Removed:
################################################################################
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