1
0
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:
Paul Eggert
2022-09-13 17:29:35 -05:00
parent c34d193387
commit c504bec035
7 changed files with 171 additions and 27 deletions

View File

@@ -7,6 +7,17 @@
2022-09-13 Paul Eggert <eggert@cs.ucla.edu> 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 stdalign-tests: port to C23
* tests/test-stdalign.c: Do not test __alignas_is_defined, * tests/test-stdalign.c: Do not test __alignas_is_defined,
_Alignof, or _Alignas as they are obsolescent. _Alignof, or _Alignas as they are obsolescent.

View File

@@ -866,6 +866,7 @@ substituted by Gnulib.
@menu @menu
* bool:: @code{bool}, @code{false}, and @code{true} * bool:: @code{bool}, @code{false}, and @code{true}
* static_assert:: @code{static_assert}
@end menu @end menu
@node bool @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. On pre-C23 platforms, the keyword substitutes assume C99 or later.
@end itemize @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 @node Header File Substitutes
@chapter ISO C and POSIX Header File Substitutes @chapter ISO C and POSIX Header File Substitutes

View File

@@ -10,28 +10,37 @@ See also the Gnulib modules @code{assert} and @code{verify}.
Portability problems fixed by Gnulib: Portability problems fixed by Gnulib:
@itemize @itemize
@item @item
On older platforms @code{static_assert} and @code{_Static_assert} do On older C platforms @code{<assert.h>} must be included before using
not allow the second string-literal argument to be omitted. For @code{static_assert}. For example, GCC versions before 13 do not
example, GCC versions before 9.1 do not support the single-argument support the @code{static_assert} keyword that was standardized by C23.
@code{static_assert} that was standardized by C2x and C++17.
@item @item
Even-older platforms do not support @code{static_assert} or On older platforms @code{static_assert} does not allow the second
@code{_Static_assert} at all. For example, GCC versions before 4.6 do string-literal argument to be omitted. For example, GCC versions
not support @code{_Static_assert}, and G++ versions before 4.3 do not before 9.1 do not support the single-argument @code{static_assert}
support @code{static_assert}, which was standardized by C11 and C++11. 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 @end itemize
Portability problems not fixed by Gnulib: Portability problems not fixed by Gnulib:
@itemize @itemize
@item @item
C @code{_Static_assert} and C++ @code{static_assert} A @code{static_assert} can also
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
be used within a @code{struct} or @code{union} specifier, in place of 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 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 @item
In C99 and later, @code{assert} can be applied to any scalar expression. 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}. In C89, the argument to @code{assert} is of type @code{int}.

View File

@@ -8,22 +8,47 @@ dnl From Paul Eggert.
AC_DEFUN([gl_ASSERT_H], AC_DEFUN([gl_ASSERT_H],
[ [
GL_GENERATE_ASSERT_H=false
AC_CACHE_CHECK([for static_assert], [gl_cv_static_assert], 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( [AC_LANG_PROGRAM(
[[#include <assert.h> [[#ifdef INCLUDE_ASSERT_H
static_assert (2 + 2 == 4, "arithmetic doesn't work"); #include <assert.h>
#endif
static_assert (2 + 2 == 4, "arithmetic does not work");
static_assert (2 + 2 == 4); 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); static_assert (sizeof (char) == 1);
]])], ]])],
[gl_cv_static_assert=yes], [gl_cv_static_assert=$gl_working],
[gl_cv_static_assert=no])]) [gl_cv_static_assert=no])
if test $gl_cv_static_assert = no; then CFLAGS=$gl_save_CFLAGS
GL_GENERATE_ASSERT_H=true test "$gl_cv_static_assert" != no && break
gl_NEXT_HEADERS([assert.h]) done])
fi
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])
]) ])

View File

@@ -1,5 +1,5 @@
Description: Description:
An <assert.h> that conforms to C11. An <assert.h> and static_assert that are like C23.
Files: Files:
lib/assert.in.h lib/assert.in.h

View File

@@ -1,7 +1,10 @@
Files: Files:
tests/test-assert.c
Depends-on: Depends-on:
configure.ac: configure.ac:
Makefile.am: Makefile.am:
TESTS += test-assert
check_PROGRAMS += test-assert

71
tests/test-assert.c Normal file
View 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;
}