]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Add compile-time checks to__glibcxx_assert [PR 71960]
authorJonathan Wakely <jwakely@redhat.com>
Tue, 1 Sep 2020 19:52:26 +0000 (20:52 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Tue, 1 Sep 2020 19:52:26 +0000 (20:52 +0100)
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.

libstdc++-v3/include/bits/c++config
libstdc++-v3/include/bits/range_access.h
libstdc++-v3/include/parallel/base.h
libstdc++-v3/include/std/ranges

index de28acea6b7a985448e950dc461f64cbc61b336a..badf9d01a04c336938352295bc3182813a8324be 100644 (file)
@@ -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
index bafced31ea81de7c4d8483ca5b0090d04c8a7c45..5c5b2fe0c6c820fb234c71e47e2fdaf56418556f 100644 (file)
@@ -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;
        }
index 0d1c2644e8fb7a75a34b66d97d4636bb31dfdd33..973a2dcd514ee08a85f45db1d79a88b821600d95 100644 (file)
@@ -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
index 2d0017f17506676855e50cb0e330eb7c944baf95..054ffe85d0f627b1a4cd164578d518fd5d1c218d 100644 (file)
@@ -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