mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
C++26 changes assert into a variadic macro to support using
assignment-expressions that would be interpreted as multiple macro
arguments, in particular one containing:
* template parameter lists: func<int, float>()
* calls to overloaded operator[] that accepts multiple arguments: arr[1, 2]
this is C++23 feature, see libstdc++ PR/119855 [1]
* lambdas with explicit captures: [x, y] { ... }
The new expansion in form:
(__VA_ARGS__) ? void (1 ? 1 : bool (__VA_ARGS__))
: __assert_fail (...)
Has the following properties:
* Use of (__VA_ARGS__) ? ... : ..., requires that __VA_ARGS__
is contextually convertible to bool. This means that enumerators
of scoped enumeration are no longer accepted (they are only
explicitly convertible). Thus this patch address the glibc PR/27276 [2].
* Nested ternary 1 ? 1 : bool (__VA_ARGS__) guarantees that
expression expanded from __VA_ARGS__ is not evaluated twice.
This is used instead of unevaluated context (like sizeof...)
to support C++ expressions that are not allowed in unevaluated
context (lambdas until C++20, co_await, co_yield).
* bool (__VA_ARGS__) is ill-formed if __VA_ARGS__ expands to
multiple arguments: assert(1, 2)
* bool (__VA_ARGS__) also triggers warnings when __VA_ARGS__
expands to x = 1: assert(x = 1)
To guarantee that the code snippets from assert/test-assert-c++-variadic.cc,
are actually checked for validity, we need to compile this test in C++26
(-std=c++26) mode. To achieve that, this patch compiles the file with
test-config-cxxflags-stdcxx26 variable as additional flag, that is set to
-std=c++26 if $(TEST_CXX) executable supports that flag, and empty otherwise.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119855
[2] https://sourceware.org/bugzilla/show_bug.cgi?id=27276
Co-authored-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
116 lines
2.1 KiB
C++
116 lines
2.1 KiB
C++
/* Test assert as a variadic macro for C++ code snippets.
|
|
Copyright The GNU Toolchain Authors.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
/* This test requires C++26, and is compiled with -std=c++26
|
|
if GCC version supports that, and no additional options
|
|
otherwise. */
|
|
#if defined __cplusplus && __cplusplus > 202302L
|
|
|
|
#undef NDEBUG
|
|
#include <assert.h>
|
|
|
|
template <typename T1, typename T2>
|
|
bool
|
|
foo ()
|
|
{ return true; }
|
|
|
|
struct C
|
|
{
|
|
C (int p, int r) : x (p + r) {}
|
|
|
|
int x;
|
|
};
|
|
|
|
int
|
|
func ()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
test_enabled ()
|
|
{
|
|
{
|
|
assert (foo <int, float> ());
|
|
}
|
|
|
|
{
|
|
assert (C {1, 2}.x > 0);
|
|
}
|
|
|
|
{
|
|
int x = 10, y = 20;
|
|
assert ([x, y] { return x < y; } ());
|
|
}
|
|
|
|
{
|
|
/* Ill-formed, not an assigment expression. */
|
|
// assert (func (), func ());
|
|
assert ((func (), func ()));
|
|
}
|
|
}
|
|
|
|
template <typename Ts>
|
|
constexpr bool
|
|
assert_works ()
|
|
{
|
|
return requires (Ts ts) {
|
|
assert (ts);
|
|
};
|
|
}
|
|
|
|
enum OE { oe };
|
|
enum TE : int { te };
|
|
enum class SE : int { se };
|
|
|
|
static_assert ( assert_works <OE> ());
|
|
static_assert ( assert_works <TE> ());
|
|
static_assert (!assert_works <SE> ());
|
|
|
|
#define NDEBUG
|
|
#include <assert.h>
|
|
|
|
static void
|
|
test_disabled ()
|
|
{
|
|
/* Assert is variadic, but ignores arguments */
|
|
assert(1, 2);
|
|
assert(+, 1, -, 2, *, 30);
|
|
}
|
|
|
|
static int
|
|
do_test ()
|
|
{
|
|
test_enabled ();
|
|
test_disabled ();
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
#include <support/test-driver.h>
|
|
|
|
static int
|
|
do_test ()
|
|
{
|
|
return EXIT_UNSUPPORTED;
|
|
}
|
|
|
|
#endif
|
|
|
|
#include <support/test-driver.c>
|