Author: Vincent
Date: 2025-06-05T23:50:20+02:00
New Revision: 49386f40dd66ababe9bfde64c14cf3bfba5774c1

URL: 
https://github.com/llvm/llvm-project/commit/49386f40dd66ababe9bfde64c14cf3bfba5774c1
DIFF: 
https://github.com/llvm/llvm-project/commit/49386f40dd66ababe9bfde64c14cf3bfba5774c1.diff

LOG: [Clang] Run destructors of variables declared in the second part of a 
`for` loop during constant evaluation (#140278)

Within the condition statement of the for block, the destructor doesn't
get called when evaluating compile time constants.

Resolves #139818

Added: 
    clang/test/SemaCXX/gh139818.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 747388fb985aa..e926d60589808 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -685,6 +685,8 @@ Bug Fixes in This Version
 - Fixed an assertion failure in serialization of constexpr structs containing 
unions. (#GH140130)
 - Fixed duplicate entries in TableGen that caused the wrong attribute to be 
selected. (GH#140701)
 - Fixed type mismatch error when 'builtin-elementwise-math' arguments have 
diff erent qualifiers, this should be well-formed. (#GH141397)
+- Constant evaluation now correctly runs the destructor of a variable declared 
in 
+  the second clause of a C-style ``for`` loop. (#GH139818)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 78dd9770f65f6..dd86eddecc682 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5761,8 +5761,12 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, 
EvalInfo &Info,
       if (FS->getCond() && !EvaluateCond(Info, FS->getConditionVariable(),
                                          FS->getCond(), Continue))
         return ESR_Failed;
-      if (!Continue)
+
+      if (!Continue) {
+        if (!IterScope.destroy())
+          return ESR_Failed;
         break;
+      }
 
       EvalStmtResult ESR = EvaluateLoopBody(Result, Info, FS->getBody());
       if (ESR != ESR_Continue) {

diff  --git a/clang/test/SemaCXX/gh139818.cpp b/clang/test/SemaCXX/gh139818.cpp
new file mode 100644
index 0000000000000..71a1e6e3b4547
--- /dev/null
+++ b/clang/test/SemaCXX/gh139818.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify -fcxx-exceptions
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify 
-fexperimental-new-constant-interpreter -fcxx-exceptions
+
+namespace GH139818{
+    struct A {
+      constexpr ~A() { ref = false; }
+      constexpr operator bool() {
+        return b;
+      }
+      bool b;
+      bool& ref;
+    };
+
+    constexpr bool f1() {
+      bool ret = true;
+      for (bool b = false; A x{b, ret}; b = true) {}
+      return ret;
+    }
+
+    static_assert(!f1());
+
+    struct Y {
+      constexpr ~Y() noexcept(false) { throw "oops"; }  // expected-note 
{{subexpression not valid in a constant expression}}
+                                                        
+      constexpr operator bool() {
+        return b;
+      }
+      bool b;
+    };
+    constexpr bool f2() {
+      for (bool b = false; Y x = {b}; b = true) {} // expected-note {{in call 
to 'x.~Y()'}}
+      return true;
+    }
+    static_assert(f2()); // expected-error {{static assertion expression is 
not an integral constant expression}}
+                         // expected-note@-1 {{in call to 'f2()'}}
+};


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

Reply via email to