[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)
JJ Marr via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 29 21:49:27 PDT 2025
https://github.com/jj-marr updated https://github.com/llvm/llvm-project/pull/130458
>From d06c5ab5c30e535893335af798df339b0e9c6878 Mon Sep 17 00:00:00 2001
From: JJ Marr <jjmarr at gmail.com>
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/lib/AST/ExprConstant.cpp | 11 ++++++++++
clang/test/SemaCXX/consteval-assert.cpp | 20 +++++++++++++++++++
3 files changed, 33 insertions(+)
create mode 100644 clang/test/SemaCXX/consteval-assert.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4c96142e28134..58f32066f5da5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -162,6 +162,8 @@ def err_ice_too_large : Error<
"integer constant expression evaluates to value %0 that cannot be "
"represented in a %1-bit %select{signed|unsigned}2 integer type">;
def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+ "assertion failed in constant evaluation: '%0'">;
// Semantic analysis of constant literals.
def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f2e49b9ea669e..3467a4d71acd5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8409,6 +8409,17 @@ class ExprEvaluatorBase
return false;
}
+ // If an assertion fails during constant evaluation, give a specific note explaining that
+ if (FD->getName() == "__assert_fail") {
+ const Expr *AssertionExpr = E->getArg(0);
+ const StringLiteral *AssertionText = dyn_cast<StringLiteral>(AssertionExpr->IgnoreParens()->IgnoreParenImpCasts());
+
+ Info.FFDiag(E->getBeginLoc(), diag::note_constexpr_assert_failed)
+ << (AssertionText ? AssertionText->getString() : "<unknown assertion>");
+
+ return false;
+ }
+
SmallVector<QualType, 4> CovariantAdjustmentPath;
if (This) {
auto *NamedMember = dyn_cast<CXXMethodDecl>(FD);
diff --git a/clang/test/SemaCXX/consteval-assert.cpp b/clang/test/SemaCXX/consteval-assert.cpp
new file mode 100644
index 0000000000000..d253db2a3ddde
--- /dev/null
+++ b/clang/test/SemaCXX/consteval-assert.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+ ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+ int result = x * x;
+ assert(result == 42); // expected-note {{assertion failed in constant evaluation: 'result == 42'}}
+ return result;
+}
+
+void test() {
+ auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+ // expected-error {{call to consteval function 'square' is not a constant expression}}
+}
More information about the cfe-commits
mailing list