[Bug 279443] LIBCPP assertions are enabled in optimized builds when -DNDEBUG is given to clang

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 17 May 2026 23:14:47 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=279443

--- Comment #20 from Mark Millard <marklmi26-fbsd@yahoo.com> ---
(In reply to Mark Linimon from comment #19)

It is still true that nothing in the C++ language
standards requires likes of the C++ standard library
to make any use of the assert() macro that comes from
the <cassert> header --or that it can not also have a
mix of other forms of assertion that have different
rules. NDEBUG only has to make the assert() macro
from <cassert> or <assert.h> translate to nothing.
It has no implications on any other the checking.

llvm has such a mix deliberately. The _LIBCPP_ASSERT
macros are not based on using the assert() macro from
<cassert> or <assert.h> (and, so, not based on NDEBUG
at all):

#define _LIBCPP_ASSERT(expression, message)                                    
                                       \
  (__builtin_expect(static_cast<bool>(expression), 1)                          
                                       \
       ? (void)0                                                               
                                       \
       : _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(              
                                       \
             __LINE__) ": libc++ Hardening assertion "
_LIBCPP_TOSTRING(expression) " failed: " message "\n"))
. . .
#if __has_builtin(__builtin_assume)
#  define _LIBCPP_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)
#endif

There are more such uses of those, but I'll show the one Yuri referenced:

# grep -r 'define.*_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS' /usr/include/c++/
/usr/include/c++/v1/__cxx03/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__cxx03/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__cxx03/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__cxx03/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSUME(expression)
/usr/include/c++/v1/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)   
_LIBCPP_ASSERT(expression, message)
/usr/include/c++/v1/__assert:#  define
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(expression, message)    ((void)0)

This is not any violation of the C++ language
standards in any way, including for NDEBUG.

That _LIBCPP_ASSERT is not based on NDEBUG is okay,
even if it has properties Yuri does not like.

LLVM defines other means of control of _LIBCPP_ASSERT
related macro usage that do not involve any use of
<cassert> or <assert.h> content.

In other words: not a bug.

-- 
You are receiving this mail because:
You are the assignee for the bug.