Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,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 different 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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5756,8 +5756,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) {
Expand Down
36 changes: 36 additions & 0 deletions clang/test/SemaCXX/gh139818.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify
// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify -fexperimental-new-constant-interpreter

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-error {{cannot use 'throw' with exceptions disabled}}
// expected-note@-1 {{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()'}}
};
Loading