https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/137525

Destructors can't be called on global variables.

>From 6cae24d12cd68d9a4227dfbdb2566fe7a605e3f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com>
Date: Sun, 27 Apr 2025 17:51:57 +0200
Subject: [PATCH] [clang][bytecode] Check for global decls in destructors

---
 clang/lib/AST/ByteCode/Interp.cpp   | 13 +++++++++----
 clang/lib/AST/ByteCode/Interp.h     |  3 ++-
 clang/test/AST/ByteCode/records.cpp |  9 +++++++++
 3 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 37111343178dd..080f694e27da2 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1387,9 +1387,14 @@ static bool checkConstructor(InterpState &S, CodePtr 
OpPC, const Function *Func,
   return false;
 }
 
-static bool checkDestructor(InterpState &S, CodePtr OpPC, const Function *Func,
-                            const Pointer &ThisPtr) {
-  return CheckActive(S, OpPC, ThisPtr, AK_Destroy);
+bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+  // Can't call a dtor on a global variable.
+  if (Ptr.block()->isStatic()) {
+    const SourceInfo &E = S.Current->getSource(OpPC);
+    S.FFDiag(E, diag::note_constexpr_modify_global);
+    return false;
+  }
+  return CheckActive(S, OpPC, Ptr, AK_Destroy);
 }
 
 static void compileFunction(InterpState &S, const Function *Func) {
@@ -1486,7 +1491,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function 
*Func,
 
     if (Func->isConstructor() && !checkConstructor(S, OpPC, Func, ThisPtr))
       return false;
-    if (Func->isDestructor() && !checkDestructor(S, OpPC, Func, ThisPtr))
+    if (Func->isDestructor() && !CheckDestructor(S, OpPC, ThisPtr))
       return false;
   }
 
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 63a1f3e8033b7..27e73bb72fecb 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -162,6 +162,7 @@ bool InvalidShuffleVectorIndex(InterpState &S, CodePtr 
OpPC, uint32_t Index);
 bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
                   bool TargetIsUCharOrByte);
 bool CheckBCPResult(InterpState &S, const Pointer &Ptr);
+bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
 
 template <typename T>
 static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
@@ -3242,7 +3243,7 @@ bool DiagTypeid(InterpState &S, CodePtr OpPC);
 
 inline bool CheckDestruction(InterpState &S, CodePtr OpPC) {
   const auto &Ptr = S.Stk.peek<Pointer>();
-  return CheckActive(S, OpPC, Ptr, AK_Destroy);
+  return CheckDestructor(S, OpPC, Ptr);
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/test/AST/ByteCode/records.cpp 
b/clang/test/AST/ByteCode/records.cpp
index b4059f009b887..9abfe6b8a15e7 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1810,3 +1810,12 @@ namespace AccessMismatch {
   static_assert(B().cmp(), ""); // both-error {{constant expression}} \
                                 // both-note {{in call}}
 }
+
+namespace GlobalDtor {
+  struct A {
+  };
+  constexpr A a = {};
+  constexpr void destroy1() { // both-error {{constexpr}}
+    a.~A(); // both-note {{cannot modify an object that is visible outside}}
+  }
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to