[libcxx-commits] [libcxx] [libc++][hardening] Always enable all checks during constant evaluation (PR #107713)

Mital Ashok via libcxx-commits libcxx-commits at lists.llvm.org
Sat Sep 7 13:04:40 PDT 2024


https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/107713

>From 6c091b7c68766325eac9912f32d0bd0b3226dbfa Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Sat, 7 Sep 2024 18:58:00 +0100
Subject: [PATCH 1/3] [libc++][hardening] Always enable all checks during
 constant evaluation

---
 libcxx/docs/ReleaseNotes/20.rst               |  2 +
 libcxx/include/__assert                       | 82 ++++++++++++-------
 .../assertions/constant_expression.verify.cpp | 61 ++++++++++++++
 3 files changed, 115 insertions(+), 30 deletions(-)
 create mode 100644 libcxx/test/libcxx/assertions/constant_expression.verify.cpp

diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 93d6027291ad95..875b0a361576a9 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -51,6 +51,8 @@ Improvements and New Features
 
 - The ``_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION`` macro has been added to make ``std::uncaught_exception`` available in C++20 and later modes.
 
+- ``_LIBCPP_ASSUME(expression)`` now checks the expression is ``true`` during constant evaluation.
+  This means that all assertions are now checked regardless of hardening mode in constant expressions.
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__assert b/libcxx/include/__assert
index 49769fb4d44978..53663b73769330 100644
--- a/libcxx/include/__assert
+++ b/libcxx/include/__assert
@@ -17,23 +17,45 @@
 #  pragma GCC system_header
 #endif
 
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int
+__assertion_failed_during_constant_evaluation(bool __value, const char*) _NOEXCEPT {
+  return __value ? 0 : (__builtin_unreachable(), 0);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#define _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                           \
+  (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wconstant-evaluated") __builtin_is_constant_evaluated()  \
+       _LIBCPP_DIAGNOSTIC_POP)
+
+#define _LIBCPP_ASSERTTION_MESSAGE(__message)                                                                          \
+  __FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING(expression) " failed: " __message "\n"
+
 #define _LIBCPP_ASSERT(expression, message)                                                                            \
-  (__builtin_expect(static_cast<bool>(expression), 1)                                                                  \
-       ? (void)0                                                                                                       \
-       : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING(            \
-             expression) " failed: " message "\n"))
+  (__builtin_expect(static_cast<bool>(expression), 1) ? (void)0                                                        \
+   : _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                              \
+       ? (void)__assertion_failed_during_constant_evaluation(false, _LIBCPP_ASSERTTION_MESSAGE(message))               \
+       : _LIBCPP_ASSERTION_HANDLER(_LIBCPP_ASSERTTION_MESSAGE(message)))
 
 // TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add
 //       assumptions without a clear optimization intent, disable that to avoid worsening the code generation.
 //       See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion.
 #if 0 && __has_builtin(__builtin_assume)
-#  define _LIBCPP_ASSUME(expression)                                                                                   \
+#  define _LIBCPP_RUNTIME_ASSUME(expression)                                                                           \
     (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume")                                              \
          __builtin_assume(static_cast<bool>(expression)) _LIBCPP_DIAGNOSTIC_POP)
 #else
-#  define _LIBCPP_ASSUME(expression) ((void)0)
+#  define _LIBCPP_RUNTIME_ASSUME(expression) ((void)0)
 #endif
 
+#define _LIBCPP_ASSUME(expression, message)                                                                            \
+  (_LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                                \
+       ? (void)__assertion_failed_during_constant_evaluation(                                                          \
+             static_cast<bool>(expression), _LIBCPP_ASSERTTION_MESSAGE(message))                                       \
+       : _LIBCPP_RUNTIME_ASSUME(expression))
+
 // clang-format off
 // Fast hardening mode checks.
 
@@ -44,18 +66,18 @@
 #  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSERT(expression, message)
 // Disabled checks.
 // On most modern platforms, dereferencing a null pointer does not lead to an actual memory access.
-#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression, message)
 // Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security
 // vulnerability.
-#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression, message)
 
 // Extensive hardening mode checks.
 
@@ -73,8 +95,8 @@
 #  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSERT(expression, message)
 #  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSERT(expression, message)
 // Disabled checks.
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
 
 // Debug hardening mode checks.
 
@@ -99,18 +121,18 @@
 #else
 
 // All checks disabled.
-#  define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
-#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression, message)
 
 #endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
 // clang-format on
diff --git a/libcxx/test/libcxx/assertions/constant_expression.verify.cpp b/libcxx/test/libcxx/assertions/constant_expression.verify.cpp
new file mode 100644
index 00000000000000..93ed0b595de57f
--- /dev/null
+++ b/libcxx/test/libcxx/assertions/constant_expression.verify.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure that both `_LIBCPP_ASSERT(false, ...)` and `_LIBCPP_ASSUME(false)`
+// mean that a constant expression cannot be formed.
+
+#include <__assert>
+#include "test_macros.h"
+
+// expected-note@*:* 0+ {{expanded from macro}}
+
+static_assert((_LIBCPP_ASSERT(false, "message"), true), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+
+static_assert((_LIBCPP_ASSUME(false), true), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+
+const int i = (_LIBCPP_ASSERT(false, "message"), 1);
+const int j = (_LIBCPP_ASSUME(false), 1);
+
+static_assert(i, "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+static_assert(j, "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+
+#if TEST_STD_VER >= 11
+constexpr bool f() {
+  return (_LIBCPP_ASSERT(false, "message"), true);
+  // expected-note at -1 {{subexpression not valid in a constant expression}}
+}
+constexpr bool g() {
+  return (_LIBCPP_ASSUME(false), true);
+  // expected-note at -1 {{subexpression not valid in a constant expression}}
+}
+static_assert(f(), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+static_assert(g(), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+#endif
+
+#if TEST_STD_VER >= 14
+constexpr bool ff() {
+  _LIBCPP_ASSERT(false, "message");
+  // expected-note at -1 {{subexpression not valid in a constant expression}}
+  return true;
+}
+constexpr bool gg() {
+  _LIBCPP_ASSUME(false);
+  // expected-note at -1 {{subexpression not valid in a constant expression}}
+  return true;
+}
+static_assert(ff(), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+static_assert(gg(), "");
+// expected-error at -1 {{static assertion expression is not an integral constant expression}}
+#endif

>From d283857fa1cf695f190e40b94c2e4b3e0cb3942b Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Sat, 7 Sep 2024 19:27:33 +0100
Subject: [PATCH 2/3] Cut out function call

It was originally added so that the assertion message would be in the
constexpr call stack but Clang just shows the source location,
including the line number, expression and message anyways
---
 libcxx/include/__assert | 70 +++++++++++++++++------------------------
 1 file changed, 29 insertions(+), 41 deletions(-)

diff --git a/libcxx/include/__assert b/libcxx/include/__assert
index 53663b73769330..d422a1ce7ae800 100644
--- a/libcxx/include/__assert
+++ b/libcxx/include/__assert
@@ -17,27 +17,16 @@
 #  pragma GCC system_header
 #endif
 
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR int
-__assertion_failed_during_constant_evaluation(bool __value, const char*) _NOEXCEPT {
-  return __value ? 0 : (__builtin_unreachable(), 0);
-}
-
-_LIBCPP_END_NAMESPACE_STD
-
 #define _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                           \
   (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wconstant-evaluated") __builtin_is_constant_evaluated()  \
        _LIBCPP_DIAGNOSTIC_POP)
 
-#define _LIBCPP_ASSERTTION_MESSAGE(__message)                                                                          \
-  __FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING(expression) " failed: " __message "\n"
-
 #define _LIBCPP_ASSERT(expression, message)                                                                            \
   (__builtin_expect(static_cast<bool>(expression), 1) ? (void)0                                                        \
    : _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                              \
-       ? (void)__assertion_failed_during_constant_evaluation(false, _LIBCPP_ASSERTTION_MESSAGE(message))               \
-       : _LIBCPP_ASSERTION_HANDLER(_LIBCPP_ASSERTTION_MESSAGE(message)))
+       ? __builtin_unreachable()                                                                                       \
+       : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING(            \
+             expression) " failed: " message "\n"))
 
 // TODO: __builtin_assume can currently inhibit optimizations. Until this has been fixed and we can add
 //       assumptions without a clear optimization intent, disable that to avoid worsening the code generation.
@@ -50,10 +39,9 @@ _LIBCPP_END_NAMESPACE_STD
 #  define _LIBCPP_RUNTIME_ASSUME(expression) ((void)0)
 #endif
 
-#define _LIBCPP_ASSUME(expression, message)                                                                            \
+#define _LIBCPP_ASSUME(expression)                                                                                     \
   (_LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                                \
-       ? (void)__assertion_failed_during_constant_evaluation(                                                          \
-             static_cast<bool>(expression), _LIBCPP_ASSERTTION_MESSAGE(message))                                       \
+       ? static_cast<bool>(expression) ? (void)0 : __builtin_unreachable()                                             \
        : _LIBCPP_RUNTIME_ASSUME(expression))
 
 // clang-format off
@@ -66,18 +54,18 @@ _LIBCPP_END_NAMESPACE_STD
 #  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSERT(expression, message)
 // Disabled checks.
 // On most modern platforms, dereferencing a null pointer does not lead to an actual memory access.
-#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression)
 // Overlapping ranges will make algorithms produce incorrect results but don't directly lead to a security
 // vulnerability.
-#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression)
 
 // Extensive hardening mode checks.
 
@@ -95,8 +83,8 @@ _LIBCPP_END_NAMESPACE_STD
 #  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSERT(expression, message)
 #  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSERT(expression, message)
 // Disabled checks.
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
 
 // Debug hardening mode checks.
 
@@ -121,18 +109,18 @@ _LIBCPP_END_NAMESPACE_STD
 #else
 
 // All checks disabled.
-#  define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression, message)
-#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression, message)
+#  define _LIBCPP_ASSERT_VALID_INPUT_RANGE(expression, message)       _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_NON_NULL(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(expression, message)  _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_DEALLOCATION(expression, message)      _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(expression, message) _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(expression, message)  _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_PEDANTIC(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(expression, message)    _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_INTERNAL(expression, message)                _LIBCPP_ASSUME(expression)
+#  define _LIBCPP_ASSERT_UNCATEGORIZED(expression, message)           _LIBCPP_ASSUME(expression)
 
 #endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
 // clang-format on

>From aa603e49fb51c9984b318d678278bc7b64a991e4 Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Sat, 7 Sep 2024 21:03:33 +0100
Subject: [PATCH 3/3] Fix test failures

---
 libcxx/include/__assert                               | 11 ++++++++---
 .../alg.sorting/alg.clamp/ranges.clamp.pass.cpp       |  4 +++-
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__assert b/libcxx/include/__assert
index d422a1ce7ae800..59cfeea2190be1 100644
--- a/libcxx/include/__assert
+++ b/libcxx/include/__assert
@@ -17,9 +17,14 @@
 #  pragma GCC system_header
 #endif
 
-#define _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                           \
-  (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wconstant-evaluated") __builtin_is_constant_evaluated()  \
-       _LIBCPP_DIAGNOSTIC_POP)
+#ifdef _LIBCPP_COMPILER_CLANG_BASED
+// TODO: use `_LIBCPP_DIAGNOSTIC_*` macros after #107715 is fixed in all supported clang compilers
+#  define _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED                                                                         \
+    (_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wconstant-evaluated\"")                     \
+         __builtin_is_constant_evaluated() _Pragma("clang diagnostic pop"))
+#else
+#  define _LIBCPP_ASSERT_IS_CONSTANT_EVALUATED (__builtin_is_constant_evaluated())
+#endif
 
 #define _LIBCPP_ASSERT(expression, message)                                                                            \
   (__builtin_expect(static_cast<bool>(expression), 1) ? (void)0                                                        \
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp
index d59864eb87023d..33e73d1a4ffa72 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.clamp/ranges.clamp.pass.cpp
@@ -108,10 +108,12 @@ constexpr bool test() {
       return value;
     };
     assert(std::ranges::clamp(3, 2, 4, std::ranges::less{}, projection_function) == 3);
+    // When assertions are enabled, we call the projection more times
 #if defined(_LIBCPP_HARDENING_MODE) && \
       _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \
       _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
-    assert(counter <= 3);
+    if (!std::__libcpp_is_constant_evaluated())
+      assert(counter <= 3);
 #endif
   }
 



More information about the libcxx-commits mailing list