aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/docs/ReleaseNotes.rst4
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/AST/ExprConstant.cpp17
-rw-r--r--clang/test/SemaCXX/consteval-assert.cpp34
4 files changed, 55 insertions, 2 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 611758d..da8bc6e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -525,6 +525,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)
- A new off-by-default warning ``-Wms-bitfield-padding`` has been added to alert to cases where bit-field
packing may differ under the MS struct ABI (#GH117428).
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 87c2f57..6c74336 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 500d43a..c09afef9 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 0000000..b54a38f
--- /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}}
+}