libstdc++: Use __builtin_unreachable for constexpr assertions [PR 100676]

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.
This commit is contained in:
Jonathan Wakely 2021-05-20 16:39:06 +01:00
parent ee336ecb2a
commit 6b42b5a8a2
11 changed files with 29 additions and 33 deletions

View 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

View 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) \

View 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" }

View 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" }

View 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" }

View 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" }

View 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" }

View 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" }

View 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" }

View 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" }

View 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" }