mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2025-08-08 17:22:05 +03:00
assert-h: static_assert is a keyword in C23
* m4/assert_h.m4 (gl_ASSERT_H): Also test for static_assert keyword a la C23, and define HAVE_C_STATIC_ASSERT if so. If not, arrange for config.h to #define static_assert by including <assert.h>, and then do "#undef assert" so that the assert macro still needs an explicit include. This should be safe even on very old hosts, as assert.h has been re-includable for decades. * tests/tests-assert.c: New test. * modules/assert-h-tests (Files, Makefile.am): Add it.
This commit is contained in:
11
ChangeLog
11
ChangeLog
@@ -7,6 +7,17 @@
|
||||
|
||||
2022-09-13 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
assert-h: static_assert is a keyword in C23
|
||||
* m4/assert_h.m4 (gl_ASSERT_H): Also test for static_assert
|
||||
keyword a la C23, and define HAVE_C_STATIC_ASSERT if so.
|
||||
If not, arrange for config.h to #define static_assert
|
||||
by including <assert.h>, and then do "#undef assert"
|
||||
so that the assert macro still needs an explicit include.
|
||||
This should be safe even on very old hosts, as assert.h
|
||||
has been re-includable for decades.
|
||||
* tests/tests-assert.c: New test.
|
||||
* modules/assert-h-tests (Files, Makefile.am): Add it.
|
||||
|
||||
stdalign-tests: port to C23
|
||||
* tests/test-stdalign.c: Do not test __alignas_is_defined,
|
||||
_Alignof, or _Alignas as they are obsolescent.
|
||||
|
@@ -866,6 +866,7 @@ substituted by Gnulib.
|
||||
|
||||
@menu
|
||||
* bool:: @code{bool}, @code{false}, and @code{true}
|
||||
* static_assert:: @code{static_assert}
|
||||
@end menu
|
||||
|
||||
@node bool
|
||||
@@ -889,6 +890,30 @@ On pre-C23 platforms, the keyword substitutes are macros.
|
||||
On pre-C23 platforms, the keyword substitutes assume C99 or later.
|
||||
@end itemize
|
||||
|
||||
@node static_assert
|
||||
@section @code{static_assert}
|
||||
|
||||
Gnulib module: assert-h
|
||||
|
||||
The @code{assert-h} module arranges for both @code{static_assert} and
|
||||
@code{<assert.h>} to be like standard C@. @xref{assert.h}.
|
||||
|
||||
Portability problems fixed by Gnulib:
|
||||
@itemize
|
||||
@item
|
||||
Pre-C11 platforms lack @code{static_assert}.
|
||||
|
||||
@item
|
||||
On pre-C23 platforms, @code{<assert.h>} must be included before
|
||||
using @code{static_assert}.
|
||||
@end itemize
|
||||
|
||||
Portability problems not fixed by Gnulib:
|
||||
@itemize
|
||||
@item
|
||||
On pre-C23 platforms, @code{static_assert} is a macro.
|
||||
@end itemize
|
||||
|
||||
@node Header File Substitutes
|
||||
@chapter ISO C and POSIX Header File Substitutes
|
||||
|
||||
|
@@ -10,28 +10,37 @@ See also the Gnulib modules @code{assert} and @code{verify}.
|
||||
Portability problems fixed by Gnulib:
|
||||
@itemize
|
||||
@item
|
||||
On older platforms @code{static_assert} and @code{_Static_assert} do
|
||||
not allow the second string-literal argument to be omitted. For
|
||||
example, GCC versions before 9.1 do not support the single-argument
|
||||
@code{static_assert} that was standardized by C2x and C++17.
|
||||
On older C platforms @code{<assert.h>} must be included before using
|
||||
@code{static_assert}. For example, GCC versions before 13 do not
|
||||
support the @code{static_assert} keyword that was standardized by C23.
|
||||
@item
|
||||
Even-older platforms do not support @code{static_assert} or
|
||||
@code{_Static_assert} at all. For example, GCC versions before 4.6 do
|
||||
not support @code{_Static_assert}, and G++ versions before 4.3 do not
|
||||
support @code{static_assert}, which was standardized by C11 and C++11.
|
||||
On older platforms @code{static_assert} does not allow the second
|
||||
string-literal argument to be omitted. For example, GCC versions
|
||||
before 9.1 do not support the single-argument @code{static_assert}
|
||||
that was standardized by C23 and C++17.
|
||||
@item
|
||||
Even-older platforms do not support @code{static_assert} at all.
|
||||
For example, GCC versions before 4.6 and G++ versions before 4.3
|
||||
do not support the two-argument form, which was standardized
|
||||
by C11 and C++11.
|
||||
@item
|
||||
Older C platforms might not support the obsolescent
|
||||
@code{_Static_assert} keyword or macro.
|
||||
This portability problem should not matter with code using this
|
||||
module, as such code should use @code{static_assert} instead.
|
||||
@end itemize
|
||||
|
||||
Portability problems not fixed by Gnulib:
|
||||
@itemize
|
||||
@item
|
||||
C @code{_Static_assert} and C++ @code{static_assert}
|
||||
are keywords that can be used without including @code{<assert.h>}.
|
||||
The Gnulib substitutes are macros that require including @code{<assert.h>}.
|
||||
@item
|
||||
The C @code{static_assert} and @code{_Static_assert} can also
|
||||
A @code{static_assert} can also
|
||||
be used within a @code{struct} or @code{union} specifier, in place of
|
||||
an ordinary declaration of a member of the struct or union. The
|
||||
Gnulib substitute can be used only as an ordinary declaration.
|
||||
Gnulib substitute can be used only as an ordinary declaration
|
||||
in code intended to be portable to C99 or earlier.
|
||||
@item
|
||||
In C23 and C++11 and later, @code{static_assert} is a keyword.
|
||||
In C11 and C17 it is a macro. Any Gnulib substitute is also a macro.
|
||||
@item
|
||||
In C99 and later, @code{assert} can be applied to any scalar expression.
|
||||
In C89, the argument to @code{assert} is of type @code{int}.
|
||||
|
@@ -8,22 +8,47 @@ dnl From Paul Eggert.
|
||||
|
||||
AC_DEFUN([gl_ASSERT_H],
|
||||
[
|
||||
GL_GENERATE_ASSERT_H=false
|
||||
AC_CACHE_CHECK([for static_assert], [gl_cv_static_assert],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[gl_save_CFLAGS=$CFLAGS
|
||||
for gl_working in "yes, a keyword" "yes, an <assert.h> macro"; do
|
||||
AS_CASE([$gl_working],
|
||||
[*assert.h*], [CFLAGS="$gl_save_CFLAGS -DINCLUDE_ASSERT_H"])
|
||||
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <assert.h>
|
||||
static_assert (2 + 2 == 4, "arithmetic doesn't work");
|
||||
[[#ifdef INCLUDE_ASSERT_H
|
||||
#include <assert.h>
|
||||
#endif
|
||||
static_assert (2 + 2 == 4, "arithmetic does not work");
|
||||
static_assert (2 + 2 == 4);
|
||||
]],
|
||||
[[
|
||||
static_assert (sizeof (char) == 1, "sizeof doesn't work");
|
||||
static_assert (sizeof (char) == 1, "sizeof does not work");
|
||||
static_assert (sizeof (char) == 1);
|
||||
]])],
|
||||
[gl_cv_static_assert=yes],
|
||||
[gl_cv_static_assert=no])])
|
||||
if test $gl_cv_static_assert = no; then
|
||||
GL_GENERATE_ASSERT_H=true
|
||||
gl_NEXT_HEADERS([assert.h])
|
||||
fi
|
||||
[gl_cv_static_assert=$gl_working],
|
||||
[gl_cv_static_assert=no])
|
||||
CFLAGS=$gl_save_CFLAGS
|
||||
test "$gl_cv_static_assert" != no && break
|
||||
done])
|
||||
|
||||
GL_GENERATE_ASSERT_H=false
|
||||
AS_CASE([$gl_cv_static_assert],
|
||||
[yes*keyword*],
|
||||
[AC_DEFINE([HAVE_C_STATIC_ASSERT], [1],
|
||||
[Define to 1 if the static_assert keyword works.])],
|
||||
[no],
|
||||
[GL_GENERATE_ASSERT_H=true
|
||||
gl_NEXT_HEADERS([assert.h])])
|
||||
|
||||
dnl The "zz" puts this toward config.h's end, to avoid potential
|
||||
dnl collisions with other definitions. #undef assert so that
|
||||
dnl programs are not tempted to use it without specifically
|
||||
dnl including assert.h. Break the #undef apart with a comment
|
||||
dnl so that 'configure' does not comment it out.
|
||||
AH_VERBATIM([zzstatic_assert],
|
||||
[#if !defined HAVE_C_STATIC_ASSERT && __cpp_static_assert < 201411
|
||||
#include <assert.h>
|
||||
#undef/**/assert
|
||||
#endif])
|
||||
])
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Description:
|
||||
An <assert.h> that conforms to C11.
|
||||
An <assert.h> and static_assert that are like C23.
|
||||
|
||||
Files:
|
||||
lib/assert.in.h
|
||||
|
@@ -1,7 +1,10 @@
|
||||
Files:
|
||||
tests/test-assert.c
|
||||
|
||||
Depends-on:
|
||||
|
||||
configure.ac:
|
||||
|
||||
Makefile.am:
|
||||
TESTS += test-assert
|
||||
check_PROGRAMS += test-assert
|
||||
|
71
tests/test-assert.c
Normal file
71
tests/test-assert.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/* Test assert.h and static_assert.
|
||||
Copyright 2022 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define STATIC_ASSERT_TESTS \
|
||||
static_assert (2 + 2 == 4, "arithmetic does not work"); \
|
||||
static_assert (2 + 2 == 4); \
|
||||
static_assert (sizeof (char) == 1, "sizeof does not work"); \
|
||||
static_assert (sizeof (char) == 1)
|
||||
|
||||
STATIC_ASSERT_TESTS;
|
||||
|
||||
static char const *
|
||||
assert (char const *p, int i)
|
||||
{
|
||||
return p + i;
|
||||
}
|
||||
|
||||
static char const *
|
||||
f (char const *p)
|
||||
{
|
||||
return assert (p, 0);
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
STATIC_ASSERT_TESTS;
|
||||
|
||||
static int
|
||||
g (void)
|
||||
{
|
||||
assert (f ("this should work"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define NDEBUG 1
|
||||
#include <assert.h>
|
||||
|
||||
STATIC_ASSERT_TESTS;
|
||||
|
||||
static int
|
||||
h (void)
|
||||
{
|
||||
assert (f ("this should work"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
STATIC_ASSERT_TESTS;
|
||||
g ();
|
||||
h ();
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user