]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Use __builtin_unreachable for constexpr assertions [PR 100676]
authorJonathan Wakely <jwakely@redhat.com>
Thu, 20 May 2021 15:39:06 +0000 (16:39 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 2 Jun 2021 13:43:20 +0000 (14:43 +0100)
The current implementation of compile-time precondition checks causes
compilation to fail by calling a non-constexpr function declared at
block scope. This breaks the CUDA compiler, which wraps some libstdc++
headers in a pragma that declares everything as a __host__ __device__
function, but others are not wrapped and so everything is a __host__
function. The local declaration thus gets redeclared as two different
types of function, which doesn't work.

Just use __builtin_unreachable to make constant evaluation fail, instead
of the local function declaration. Also simplify the assertion macros,
which has the side effect of giving simpler compilation errors when
using Clang.

libstdc++-v3/ChangeLog:

PR libstdc++/100676
* include/bits/c++config (__glibcxx_assert_1): Rename to ...
(__glibcxx_constexpr_assert): ... this.
(__glibcxx_assert_impl): Use __glibcxx_constexpr_assert.
(__glibcxx_assert): Define as either __glibcxx_constexpr_assert
or __glibcxx_assert_impl.
(__glibcxx_assert_2): Remove
* include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_AT_F): Use
__glibcxx_constexpr_assert instead of __glibcxx_assert_1.
* testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc:
Adjust expected error.
* testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc:
Likewise.
* testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc:
Likewise.
Likewise.
* testsuite/21_strings/basic_string_view/element_access/wchar_t/back_constexpr_neg.cc:
Likewise.
* testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc:
Likewise.
* testsuite/21_strings/basic_string_view/element_access/wchar_t/front_constexpr_neg.cc:
Likewise.
* testsuite/23_containers/span/back_neg.cc: Likewise.
* testsuite/23_containers/span/front_neg.cc: Likewise.
* testsuite/23_containers/span/index_op_neg.cc: Likewise.

(cherry picked from commit 6b42b5a8a207de5e021a2916281f46bcd60b20d2)

libstdc++-v3/include/bits/c++config
libstdc++-v3/include/debug/macros.h
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/back_constexpr_neg.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/constexpr_neg.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/front_constexpr_neg.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/back_constexpr_neg.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/constexpr_neg.cc
libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/front_constexpr_neg.cc
libstdc++-v3/testsuite/23_containers/span/back_neg.cc
libstdc++-v3/testsuite/23_containers/span/front_neg.cc
libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc

index 72ec91949de5510faeb7f205f00100ba8308f071..9314117aed8d8c068e0271decc0a19ccbc9536bc 100644 (file)
@@ -487,6 +487,16 @@ namespace std
 # define _GLIBCXX_EXTERN_TEMPLATE -1
 #endif
 
+
+#if __has_builtin(__builtin_is_constant_evaluated)
+# define __glibcxx_constexpr_assert(cond) \
+  if (__builtin_is_constant_evaluated() && !bool(cond))        \
+    __builtin_unreachable() /* precondition violation detected! */
+#else
+# define __glibcxx_constexpr_assert(unevaluated)
+#endif
+
+
 // Assert.
 #if defined(_GLIBCXX_ASSERTIONS) \
   || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS)
@@ -506,14 +516,19 @@ namespace std
 }
 #define __glibcxx_assert_impl(_Condition)                             \
   if (__builtin_expect(!bool(_Condition), false))                     \
+  {                                                                   \
+    __glibcxx_constexpr_assert(_Condition);                           \
     std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
-                             #_Condition)
+                             #_Condition);                            \
+  }
 #endif
 
 #if defined(_GLIBCXX_ASSERTIONS)
-# define __glibcxx_assert_2(_Condition) __glibcxx_assert_impl(_Condition)
+# define __glibcxx_assert(cond) \
+  do { __glibcxx_assert_impl(cond); } while (false)
 #else
-# define __glibcxx_assert_2(_Condition)
+# define __glibcxx_assert(cond) \
+  do { __glibcxx_constexpr_assert(cond); } while (false)
 #endif
 
 // Macros for race detectors.
@@ -736,25 +751,6 @@ namespace std
 
 #undef _GLIBCXX_HAS_BUILTIN
 
-#if _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED && __cplusplus >= 201402L
-# 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
 
index 9ac52ebd09d185373e0134c46188a3a185a92d3e..9e1288cf4d9252ce82094758724ac2f5679a8bac 100644 (file)
@@ -45,8 +45,8 @@
 
 #define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func)    \
   do {                                                                 \
-    __glibcxx_assert_1(_Cond)                                          \
-    { _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); } \
+    __glibcxx_constexpr_assert(_Cond);                                 \
+    _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func);    \
   } while (false)
 
 #define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line)            \
index 0f731c9a4856d16a9fc6604af8a1e0c5f9e4e9d1..2da90bd954e2ece64f7d3b829d10008d0f5775cc 100644 (file)
@@ -32,4 +32,4 @@ back()
 static_assert(back() != 'a'); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index 5dd206f1a2964308ab70c18d28230a0c84a03cd1..844b62277c5fff05d924ae351c785b8d471f5a8d 100644 (file)
@@ -31,4 +31,4 @@ test()
 static_assert(test() == 0); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index 9c846116bb92892c638a00cdf0c177c37e23a3fd..d6dceb61a34cf646c02cefdedaf107dce37f8e2c 100644 (file)
@@ -32,4 +32,4 @@ front()
 static_assert(front() != 'a'); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index 26d2d4da54b2f32aaee2657537a67532aeb1523b..798e1a4074de7d8b3d675f67403865fa90633ea2 100644 (file)
@@ -32,4 +32,4 @@ back()
 static_assert(back() != L'a'); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index c853dada7dc721495f18e75a7beda3e606febba6..0e22b766b3dea48ae08af42da44f87067c0024aa 100644 (file)
@@ -31,4 +31,4 @@ test()
 static_assert(test() == 0); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index fdcabd7363d26bf407c47a681d1564c5ff300333..f49774a0bdd47eecc7f2d2bd87c65f404c6125b5 100644 (file)
@@ -32,4 +32,4 @@ front()
 static_assert(front() != L'a'); // { dg-error "non-constant condition" }
 
 // { dg-prune-output "in 'constexpr' expansion" }
-// { dg-prune-output "failed_assertion" }
+// { dg-prune-output "unreachable" }
index 0289ece7a50a70e0407d7f055006b6540c58163f..ce00aa8868f0241f602793e6ae234bdc6076626d 100644 (file)
@@ -31,5 +31,5 @@ test01(bool b)
 
 static_assert(test01(false));
 static_assert(test01(true)); // { dg-error "non-constant" }
-// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-error "unreachable" "" { target *-*-* } 0 }
 // { dg-prune-output "in 'constexpr' expansion" }
index dfad9f8a5428fb0d924197835e790dea5a0c98b2..a6efc7dd83631f34748c34410c622e943dfd096f 100644 (file)
@@ -31,5 +31,5 @@ test01(bool b)
 
 static_assert(test01(false));
 static_assert(test01(true)); // { dg-error "non-constant" }
-// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-error "unreachable" "" { target *-*-* } 0 }
 // { dg-prune-output "in 'constexpr' expansion" }
index 378ae05e0ea23e26d46e17ce4ee3ae92bb7c4d90..2dce639819c782f225a2ce3b11e88e9bae454127 100644 (file)
@@ -31,5 +31,5 @@ test01(bool b)
 
 static_assert(test01(false));
 static_assert(test01(true)); // { dg-error "non-constant" }
-// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-error "unreachable" "" { target *-*-* } 0 }
 // { dg-prune-output "in 'constexpr' expansion" }