https://github.com/tbaederr created
https://github.com/llvm/llvm-project/pull/212091
1) Mention the limit in the "constexpr evaluation hit maximum step limit"
diagnostic as well
2) Move the "use -fconstexpr-steps" instruction to its own note so we can
reuse it for two different diagnostics
For
`c++
struct S {
constexpr S() {}
};
constexpr S foo[1'500'000] = {};
```
we used to emit
```console
array.cpp:1028:13: error: constexpr variable 'foo' must be initialized by a
constant expression
1028 | constexpr S foo[1'500'000] = {};
| ^ ~~
array.cpp:1026:17: note: constexpr evaluation hit maximum step limit; possible
infinite loop?
1026 | constexpr S() {}
| ^
array.cpp:1028:31: note: in call to 'S()'
1028 | constexpr S foo[1'500'000] = {};
| ^
```
and now we emit
```
array.cpp:1028:13: error: constexpr variable 'foo' must be initialized by a
constant expression
1028 | constexpr S foo[1'500'000] = {};
| ^ ~~
array.cpp:1026:17: note: constexpr evaluation hit maximum step limit of
1048576; possible infinite loop?
1026 | constexpr S() {}
| ^
array.cpp:1028:31: note: in call to 'S()'
1028 | constexpr S foo[1'500'000] = {};
| ^
array.cpp:1026:17: note: use -fconstexpr-steps= to increase this limit (=0 will
remove the limit)
1026 | constexpr S() {}
```
>From 40fba4d3c0b109e29e60f494f211799fa31d81be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Sun, 26 Jul 2026 07:15:52 +0200
Subject: [PATCH] diags
---
clang/include/clang/Basic/DiagnosticASTKinds.td | 7 ++++---
clang/lib/AST/ByteCode/InterpHelpers.h | 3 ++-
clang/lib/AST/ByteCode/InterpState.cpp | 4 +++-
clang/lib/AST/ByteCode/State.cpp | 6 ++++++
clang/lib/AST/ByteCode/State.h | 1 +
clang/lib/AST/ExprConstant.cpp | 10 +++++++---
clang/test/AST/ByteCode/constexpr-steps.cpp | 6 ++++--
clang/test/AST/ByteCode/dynalloc-limits.cpp | 6 ++++--
.../SemaCXX/constexpr-function-recovery-crash.cpp | 15 ++++++++++-----
.../SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp | 9 ++++++---
clang/test/SemaCXX/cxx2c-expansion-stmts.cpp | 1 +
11 files changed, 48 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index f86f0157b2b1f..c4582a3a9d641 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -170,7 +170,7 @@ def note_constexpr_depth_limit_exceeded : Note<
def note_constexpr_call_limit_exceeded : Note<
"constexpr evaluation hit maximum call limit">;
def note_constexpr_step_limit_exceeded : Note<
- "constexpr evaluation hit maximum step limit; possible infinite loop?">;
+ "constexpr evaluation hit maximum step limit of %0; possible infinite
loop?">;
def note_constexpr_heap_alloc_limit_exceeded : Note<
"constexpr evaluation hit maximum heap allocation limit">;
def note_constexpr_this : Note<
@@ -355,8 +355,9 @@ def note_constexpr_new_negative : Note<
def note_constexpr_new_too_large : Note<
"cannot allocate array; evaluated array bound %0 is too large">;
def note_constexpr_new_exceeds_limits : Note<
- "cannot allocate array; evaluated array bound %0 exceeds the limit (%1); "
- "use '-fconstexpr-steps' to increase this limit">;
+ "cannot allocate array; evaluated array bound %0 exceeds the limit (%1)">;
+def note_constexpr_steps : Note<
+ "use -fconstexpr-steps= to increase this limit (=0 will remove the limit)">;
def note_constexpr_new_too_small : Note<
"cannot allocate array; evaluated array bound %0 is too small to hold "
"%1 explicitly initialized elements">;
diff --git a/clang/lib/AST/ByteCode/InterpHelpers.h
b/clang/lib/AST/ByteCode/InterpHelpers.h
index 4d908d1e44546..1df570ac971c4 100644
--- a/clang/lib/AST/ByteCode/InterpHelpers.h
+++ b/clang/lib/AST/ByteCode/InterpHelpers.h
@@ -94,8 +94,9 @@ inline bool CheckArraySize(InterpState &S, CodePtr OpPC,
uint64_t NumElems) {
uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
if (Limit != 0 && NumElems > Limit) {
S.FFDiag(S.Current->getSource(OpPC),
- diag::note_constexpr_new_exceeds_limits)
+ diag::note_constexpr_new_exceeds_limits, 1)
<< NumElems << Limit;
+ S.Note(S.Current->getSource(OpPC), diag::note_constexpr_steps);
return false;
}
return true;
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp
b/clang/lib/AST/ByteCode/InterpState.cpp
index f6338cda56e34..6ac1b2610dd09 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -165,6 +165,8 @@ bool InterpState::noteStep(CodePtr OpPC) {
if (StepsLeft != 0)
return true;
- FFDiag(Current->getSource(OpPC), diag::note_constexpr_step_limit_exceeded);
+ FFDiag(Current->getSource(OpPC), diag::note_constexpr_step_limit_exceeded, 1)
+ << getLangOpts().ConstexprStepLimit;
+ Note(Current->getSource(OpPC), diag::note_constexpr_steps);
return false;
}
diff --git a/clang/lib/AST/ByteCode/State.cpp b/clang/lib/AST/ByteCode/State.cpp
index e62b77272046c..38384bae23f57 100644
--- a/clang/lib/AST/ByteCode/State.cpp
+++ b/clang/lib/AST/ByteCode/State.cpp
@@ -69,6 +69,12 @@ OptionalDiagnostic State::Note(SourceLocation Loc,
diag::kind DiagId) {
return OptionalDiagnostic(&addDiag(Loc, DiagId));
}
+OptionalDiagnostic State::Note(SourceInfo SI, diag::kind DiagId) {
+ if (!hasActiveDiagnostic())
+ return OptionalDiagnostic();
+ return OptionalDiagnostic(&addDiag(SI.getLoc(), DiagId));
+}
+
void State::addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
if (hasActiveDiagnostic())
llvm::append_range(*EvalStatus.Diag, Diags);
diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h
index df3afdf8cbc24..df91132c48472 100644
--- a/clang/lib/AST/ByteCode/State.h
+++ b/clang/lib/AST/ByteCode/State.h
@@ -162,6 +162,7 @@ class State {
/// Add a note to a prior diagnostic.
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId);
+ OptionalDiagnostic Note(SourceInfo Loc, diag::kind DiagId);
/// Add a stack of notes to a prior diagnostic.
void addNotes(ArrayRef<PartialDiagnosticAt> Diags);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 574dd8b04e779..3c715d80bb691 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -974,9 +974,11 @@ namespace {
// of each element is likely to take some number of steps anyway.
uint64_t Limit = getLangOpts().ConstexprStepLimit;
if (Limit != 0 && ElemCount > Limit) {
- if (Diag)
- FFDiag(Loc, diag::note_constexpr_new_exceeds_limits)
+ if (Diag) {
+ FFDiag(Loc, diag::note_constexpr_new_exceeds_limits, 1)
<< ElemCount << Limit;
+ Note(Loc, diag::note_constexpr_steps);
+ }
return false;
}
return true;
@@ -1003,7 +1005,9 @@ namespace {
return true;
if (!StepsLeft) {
- FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded);
+ FFDiag(S->getBeginLoc(), diag::note_constexpr_step_limit_exceeded, 1)
+ << getLangOpts().ConstexprStepLimit;
+ Note(S->getBeginLoc(), diag::note_constexpr_steps);
return false;
}
--StepsLeft;
diff --git a/clang/test/AST/ByteCode/constexpr-steps.cpp
b/clang/test/AST/ByteCode/constexpr-steps.cpp
index bd461547032a9..3ba6b1cb3adcd 100644
--- a/clang/test/AST/ByteCode/constexpr-steps.cpp
+++ b/clang/test/AST/ByteCode/constexpr-steps.cpp
@@ -2,14 +2,16 @@
constexpr int foo() { // expected-error {{never produces a constant
expression}}
- while (1) {} // expected-note 2{{constexpr evaluation hit maximum step
limit}}
+ while (1) {} // expected-note 2{{constexpr evaluation hit maximum step
limit}} \
+ // expected-note 2{{use -fconstexpr-steps}}
return 0;
}
static_assert (foo() == 0, ""); // expected-error {{not an integral constant
expression}} \
// expected-note {{in call to}}
constexpr void addr() { // expected-error {{never produces a constant
expression}}
- for (;;) // expected-note 2{{constexpr evaluation hit maximum step limit}}
+ for (;;) // expected-note 2{{constexpr evaluation hit maximum step limit}} \
+ // expected-note 2{{use -fconstexpr-steps}}
;
}
static_assert((addr(), 1) == 1); // expected-error {{not an integral constant
expression}} \
diff --git a/clang/test/AST/ByteCode/dynalloc-limits.cpp
b/clang/test/AST/ByteCode/dynalloc-limits.cpp
index ed2d4faf974b1..85d66ac88ee2c 100644
--- a/clang/test/AST/ByteCode/dynalloc-limits.cpp
+++ b/clang/test/AST/ByteCode/dynalloc-limits.cpp
@@ -54,7 +54,8 @@ constexpr std::size_t s = S<std::size_t>(~0UL)[42]; //
both-error {{constexpr va
constexpr std::size_t ssmall = S<std::size_t>(100)[42];
constexpr std::size_t s5 = S<std::size_t>(1025)[42]; // both-error {{constexpr
variable 's5' must be initialized by a constant expression}} \
- // both-note@#alloc {{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024); use
'-fconstexpr-steps' to increase this limit}} \
+ // both-note@#alloc {{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024)}} \
+ // both-note@#alloc {{use
-fconstexpr-steps}} \
// both-note@#call {{in call to
'this->alloc.allocate(1025)'}} \
// both-note {{in call}}
@@ -62,7 +63,8 @@ constexpr std::size_t s5 = S<std::size_t>(1025)[42]; //
both-error {{constexpr v
template <auto N>
constexpr int stack_array() {
- [[maybe_unused]] char BIG[N] = {1}; // both-note {{cannot allocate array;
evaluated array bound 1025 exceeds the limit (1024)}}
+ [[maybe_unused]] char BIG[N] = {1}; // both-note {{cannot allocate array;
evaluated array bound 1025 exceeds the limit (1024)}} \
+ // both-note {{use -fconstexpr-steps}}
return BIG[N-1];
}
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index de8fe057893d5..016bd188ac9f7 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -36,7 +36,8 @@ constexpr int test4() {
constexpr int test5() { // expected-error {{constexpr function never produce}}
for (;; a++); // expected-error {{use of undeclared identifier}} \
- expected-note {{constexpr evaluation hit maximum step
limit; possible infinite loop?}}
+ expected-note {{constexpr evaluation hit maximum step limit
of 1048576; possible infinite loop?}} \
+ expected-note {{use -fconstexpr-steps}}
return 1;
}
@@ -44,7 +45,8 @@ constexpr int test6() { // expected-error {{constexpr
function never produce}}
int n = 0;
switch (n) {
for (;; a++) { // expected-error {{use of undeclared identifier}}
- case 0:; // expected-note {{constexpr evaluation hit maximum step limit;
possible infinite loop?}}
+ case 0:; // expected-note {{constexpr evaluation hit maximum step limit of
1048576; possible infinite loop?}} \
+ // expected-note {{use -fconstexpr-steps}}
}
}
return 0;
@@ -91,7 +93,8 @@ TEST_EVALUATE(SwitchCondValDep, switch (invalid_value) {
default: break; });
TEST_EVALUATE(For, for (!!){}); // expected-error + {{}}
// FIXME: should bail out instead of looping.
// expected-note@-2 + {{infinite loop}}
- // expected-note@-3 {{in call}}
+ // expected-note@-3 + {{use -fconstexpr-steps}}
+ // expected-note@-4 {{in call}}
TEST_EVALUATE(ForRange, for (auto x : !!){}); // expected-error + {{}}
TEST_EVALUATE(While, while (!!){}); // expected-error + {{}}
TEST_EVALUATE(DoWhile, do {} while (!!);); // expected-error + {{}}
@@ -101,9 +104,11 @@ TEST_EVALUATE(If, if (!!){};); //
expected-error + {{}}
TEST_EVALUATE(IfInit, if (auto x = !!; 1){};);// expected-error + {{}}
TEST_EVALUATE(ForInit, for (!!;;){};);// expected-error + {{}}
// expected-note@-1 + {{infinite loop}}
- // expected-note@-2 {{in call}}
+ // expected-note@-2 + {{use
-fconstexpr-steps}}
+ // expected-note@-3 {{in call}}
TEST_EVALUATE(ForCond, for (; !!;){};);// expected-error + {{}}
TEST_EVALUATE(ForInc, for (;; !!){};);// expected-error + {{}}
// expected-note@-1 + {{infinite loop}}
- // expected-note@-2 {{in call}}
+ // expected-note@-2 + {{use
-fconstexpr-steps}}
+ // expected-note@-3 {{in call}}
TEST_EVALUATE(ForCondUnDef, for (;some_cond;){};); // expected-error +
{{}}
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
index 8bcb4d45d4af8..7537b47780aeb 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
@@ -58,14 +58,16 @@ constexpr std::size_t ssmall = S<std::size_t>(100)[42];
// We can allocate this array but we hikt the number of steps
constexpr std::size_t s4 = S<std::size_t>(1024)[42]; // expected-error
{{constexpr variable 's4' must be initialized by a constant expression}} \
- // expected-note@#construct {{constexpr
evaluation hit maximum step limit; possible infinite loop?}} \
+ // expected-note@#construct {{constexpr
evaluation hit maximum step limit of 1024; possible infinite loop?}} \
+ // expected-note@#construct {{use
-fconstexpr-steps}} \
// expected-note@#construct_call {{in
call}} \
// expected-note {{in call}}
constexpr std::size_t s5 = S<std::size_t>(1025)[42]; //
expected-error{{constexpr variable 's5' must be initialized by a constant
expression}} \
- // expected-note@#alloc {{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024); use
'-fconstexpr-steps' to increase this limit}} \
+ // expected-note@#alloc {{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024)}} \
+ // expected-note@#alloc {{use
-fconstexpr-steps}} \
// expected-note@#call {{in call to
'this->alloc.allocate(1025)'}} \
// expected-note {{in call}}
@@ -75,7 +77,8 @@ constexpr std::size_t s5 = S<std::size_t>(1025)[42]; //
expected-error{{constexp
template <auto N>
constexpr int stack_array() {
- [[maybe_unused]] char BIG[N] = {1}; // expected-note 3{{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024); use
'-fconstexpr-steps' to increase this limit}}
+ [[maybe_unused]] char BIG[N] = {1}; // expected-note 3{{cannot allocate
array; evaluated array bound 1025 exceeds the limit (1024)}} \
+ // expected-note 3{{use
-fconstexpr-steps}}
return BIG[N-1];
}
diff --git a/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
index fb93cdf588f6c..dd450a8f1b76c 100644
--- a/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
+++ b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
@@ -177,6 +177,7 @@ void negative_size() {
static constexpr NegativeSize n;
template for (auto x : n) g(x); // expected-error {{expansion statement size
is not a constant expression}} \
old-interp-note {{constexpr evaluation
hit maximum step limit}} \
+ old-interp-note {{use -fconstexpr-steps}}
\
new-interp-note {{cannot refer to element
5 of array of 4 elements in a constant expression}} \
expected-note {{in call to}}
template for (constexpr auto x : n) g(x); // expected-error {{expansion
statement size is not a constant expression}} \
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits