mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
libstdc++: Add compile-time checks to__glibcxx_assert [PR 71960]
This change evaluates __glibcxx_assert checks unconditionally when a
function is being constant evaluated (when std::is_constant_evaluated()
is true). If the check fails, compilation will fail with an error.
If the function isn't being constant evaluated, the normal runtime check
will be done if enabled by _GLIBCXX_ASSERTIONS or _GLIBCXX_DEBUG, the
same as before.
Tangentially, the __glibcxx_assert and _GLIBCXX_PARALLEL_ASSERT macros
are changed to expand to 'do { } while (false)' when assertions are
disabled, instead of expanding to nothing. This avoids -Wempty-body
warnings when a disabled assertion is used in an 'if' or 'else'
statement e.g.
if constexpr (/* precondition is testable */)
__glibcxx_assert(precondition);
a.C:9:27: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body]
9 | __glibcxx_assert(precondition);
| ^
libstdc++-v3/ChangeLog:
PR libstdc++/71960
* include/bits/c++config (__glibcxx_assert_impl): Remove
do-while so that uses of the macro need to add it.
(__glibcxx_assert): Rename macro for runtime assertions
to __glibcxx_assert_2.
(__glibcxx_assert_1): Define macro for constexpr assertions.
(__glibcxx_assert): Define macro for constexpr and runtime
assertions.
* include/bits/range_access.h (ranges::advance): Remove
redundant precondition checks during constant evaluation.
* include/parallel/base.h (_GLIBCXX_PARALLEL_ASSERT): Always
use do-while in macro expansion.
* include/std/ranges (iota_view::iota_view(W, B)): Remove
redundant braces.
This commit is contained in:
@@ -477,19 +477,16 @@ namespace std
|
||||
__builtin_abort();
|
||||
}
|
||||
}
|
||||
#define __glibcxx_assert_impl(_Condition) \
|
||||
do \
|
||||
{ \
|
||||
if (! (_Condition)) \
|
||||
std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
|
||||
#_Condition); \
|
||||
} while (false)
|
||||
#define __glibcxx_assert_impl(_Condition) \
|
||||
if (!bool(_Condition)) \
|
||||
std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
|
||||
#_Condition)
|
||||
#endif
|
||||
|
||||
#if defined(_GLIBCXX_ASSERTIONS)
|
||||
# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition)
|
||||
# define __glibcxx_assert_2(_Condition) __glibcxx_assert_impl(_Condition)
|
||||
#else
|
||||
# define __glibcxx_assert(_Condition)
|
||||
# define __glibcxx_assert_2(_Condition)
|
||||
#endif
|
||||
|
||||
// Macros for race detectors.
|
||||
@@ -683,6 +680,26 @@ namespace std
|
||||
# endif
|
||||
#endif // GCC
|
||||
|
||||
#if _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
|
||||
# define __glibcxx_assert_1(_Condition) \
|
||||
if (__builtin_is_constant_evaluated()) \
|
||||
{ \
|
||||
void __failed_assertion(); \
|
||||
if (!bool(_Condition)) \
|
||||
__failed_assertion(); \
|
||||
} \
|
||||
else
|
||||
#else
|
||||
# define __glibcxx_assert_1(_Condition)
|
||||
#endif
|
||||
|
||||
# define __glibcxx_assert(_Condition) \
|
||||
do { \
|
||||
__glibcxx_assert_1(_Condition) \
|
||||
{ __glibcxx_assert_2(_Condition); } \
|
||||
} while (false)
|
||||
|
||||
|
||||
// PSTL configuration
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
|
||||
@@ -987,10 +987,7 @@ namespace ranges
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated() && __n < 0)
|
||||
throw "attempt to decrement a non-bidirectional iterator";
|
||||
#endif
|
||||
// cannot decrement a non-bidirectional iterator
|
||||
__glibcxx_assert(__n >= 0);
|
||||
while (__n-- > 0)
|
||||
++__it;
|
||||
@@ -1065,10 +1062,7 @@ namespace ranges
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated() && __n < 0)
|
||||
throw "attempt to decrement a non-bidirectional iterator";
|
||||
#endif
|
||||
// cannot decrement a non-bidirectional iterator
|
||||
__glibcxx_assert(__n >= 0);
|
||||
return __n;
|
||||
}
|
||||
|
||||
@@ -420,9 +420,10 @@ namespace __gnu_parallel
|
||||
}
|
||||
|
||||
#if _GLIBCXX_PARALLEL_ASSERTIONS && defined(__glibcxx_assert_impl)
|
||||
#define _GLIBCXX_PARALLEL_ASSERT(_Condition) __glibcxx_assert_impl(_Condition)
|
||||
# define _GLIBCXX_PARALLEL_ASSERT(_Condition) \
|
||||
do { __glibcxx_assert_impl(_Condition); } while (false)
|
||||
#else
|
||||
#define _GLIBCXX_PARALLEL_ASSERT(_Condition)
|
||||
# define _GLIBCXX_PARALLEL_ASSERT(_Condition) do { } while (false)
|
||||
#endif
|
||||
|
||||
} //namespace __gnu_parallel
|
||||
|
||||
@@ -860,9 +860,7 @@ namespace ranges
|
||||
: _M_value(__value), _M_bound(__bound)
|
||||
{
|
||||
if constexpr (totally_ordered_with<_Winc, _Bound>)
|
||||
{
|
||||
__glibcxx_assert( bool(__value <= __bound) );
|
||||
}
|
||||
__glibcxx_assert( bool(__value <= __bound) );
|
||||
}
|
||||
|
||||
constexpr _Iterator
|
||||
|
||||
Reference in New Issue
Block a user