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>
|
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.
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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}.
|
||||||
|
@@ -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])
|
||||||
])
|
])
|
||||||
|
@@ -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
|
||||||
|
@@ -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
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