https://github.com/jj-marr updated https://github.com/llvm/llvm-project/pull/130458
>From 64eb62576dc1ecf0e696f2448e410c2fd77575de Mon Sep 17 00:00:00 2001 From: JJ Marr <jjm...@gmail.com> Date: Sat, 8 Mar 2025 22:00:45 -0500 Subject: [PATCH] Explain which assertion failed during consteval --- clang/docs/ReleaseNotes.rst | 4 +++ .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/AST/ExprConstant.cpp | 17 ++++++++-- clang/test/SemaCXX/consteval-assert.cpp | 34 +++++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 clang/test/SemaCXX/consteval-assert.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2c3c75b88a9fe..01a4f96404681 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -523,6 +523,10 @@ Improvements to Clang's diagnostics - An error is now emitted when OpenMP ``collapse`` and ``ordered`` clauses have an argument larger than what can fit within a 64-bit integer. + +- Explanatory note is printed when ``assert`` fails during evaluation of a + constant expression. Prior to this, the error inaccurately implied that assert + could not be used at all in a constant expression (#GH130458) Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3efe9593b8633..a84f84b4653de 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -164,6 +164,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 during evaluation of constant expression">; // 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 500d43accb082..c09afef9c4bf9 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5975,9 +5975,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc, Definition->hasAttr<MSConstexprAttr>()))) return true; - if (Info.getLangOpts().CPlusPlus11) { - const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; + const FunctionDecl *DiagDecl = Definition ? Definition : Declaration; + // Special note for the assert() macro, as the normal error message falsely + // implies we cannot use an assertion during constant evaluation. + if (CallLoc.isMacroID() && DiagDecl->getIdentifier()) { + // FIXME: Instead of checking for an implementation-defined function, + // check and evaluate the assert() macro. + StringRef Name = DiagDecl->getName(); + bool AssertFailed = + Name == "__assert_rtn" || Name == "__assert_fail" || Name == "_wassert"; + if (AssertFailed) { + Info.FFDiag(CallLoc, diag::note_constexpr_assert_failed); + return false; + } + } + if (Info.getLangOpts().CPlusPlus11) { // If this function is not constexpr because it is an inherited // non-constexpr constructor, diagnose that directly. auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); diff --git a/clang/test/SemaCXX/consteval-assert.cpp b/clang/test/SemaCXX/consteval-assert.cpp new file mode 100644 index 0000000000000..b54a38ff26105 --- /dev/null +++ b/clang/test/SemaCXX/consteval-assert.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_LINUX %s +// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_WINDOWS %s +// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_DARWIN %s + +#ifdef __ASSERT_FUNCTION +#undef __ASSERT_FUNCTION +#endif + +#if defined(TEST_LINUX) + extern "C" void __assert_fail(const char*, const char*, unsigned, const char*); + #define assert(cond) \ + ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__)) +#elif defined(TEST_DARWIN) + void __assert_rtn(const char *, const char *, int, const char *); + #define assert(cond) \ + (__builtin_expect(!(cond), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, #cond) : (void)0) +#elif defined(TEST_WINDOWS) + void /*__cdecl*/ _wassert(const wchar_t*, const wchar_t*, unsigned); + #define _CRT_WIDE_(s) L ## s + #define _CRT_WIDE(s) _CRT_WIDE_(s) + #define assert(cond) \ + (void)((!!(cond)) || (_wassert(_CRT_WIDE(#cond), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0)) +#endif + +consteval int square(int x) { + int result = x * x; + assert(result == 42); // expected-note {{assertion failed during evaluation of constant expression}} + 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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits