+2025-05-27 Bruno Haible <bruno@clisp.org>
+
+ stddef-h: Make 'unreachable' usable in C++ mode.
+ Reported by Pierre Ossman <ossman@cendio.se>
+ at <https://savannah.gnu.org/bugs/?67152>.
+ * m4/stddef_h.m4 (gl_STDDEF_H): Also test whether unreachable is defined
+ by <stddef.h> in C++ mode.
+ * lib/stddef.in.h: In C++ mode, include <utility> and either import
+ 'unreachable' from the std namespace or define it as an inline function.
+ * tests/test-stddef-h.c: Disable some tests in C++ mode.
+ * tests/test-stddef-h-c++.cc: Perform nearly the same tests in C++ mode
+ as in C mode.
+ * tests/test-stddef-h-c++2.cc: Rename some variables. Disable the NULL
+ test with clang on Windows.
+ * tests/test-stddef-h-c++3.cc: New file.
+ * modules/stddef-h-c++-tests (Files): Include it.
+ (Makefile.am): Link test-stddef-h-c++ with test-stddef-h-c++3.o.
+
2025-05-27 Bruno Haible <bruno@clisp.org>
strchrnul: Fix for users of the current macOS SDK.
#endif
/* ISO C 23 ยง 7.21.1 The unreachable macro */
-#ifndef unreachable
/* Code borrowed from verify.h. */
-# ifndef _GL_HAS_BUILTIN_UNREACHABLE
-# if defined __clang_major__ && __clang_major__ < 5
-# define _GL_HAS_BUILTIN_UNREACHABLE 0
-# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__
-# define _GL_HAS_BUILTIN_UNREACHABLE 1
-# elif defined __has_builtin
-# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable)
-# else
-# define _GL_HAS_BUILTIN_UNREACHABLE 0
-# endif
+#ifndef _GL_HAS_BUILTIN_UNREACHABLE
+# if defined __clang_major__ && __clang_major__ < 5
+# define _GL_HAS_BUILTIN_UNREACHABLE 0
+# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__
+# define _GL_HAS_BUILTIN_UNREACHABLE 1
+# elif defined __has_builtin
+# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable)
+# else
+# define _GL_HAS_BUILTIN_UNREACHABLE 0
# endif
+#endif
-# if _GL_HAS_BUILTIN_UNREACHABLE
-# define unreachable() __builtin_unreachable ()
-# elif 1200 <= _MSC_VER
-# define unreachable() __assume (0)
-# else
+#if _GL_HAS_BUILTIN_UNREACHABLE
+# define _gl_unreachable() __builtin_unreachable ()
+#elif 1200 <= _MSC_VER
+# define _gl_unreachable() __assume (0)
+#else
/* Declare abort(), without including <stdlib.h>. */
extern
-# if defined __cplusplus
+# if defined __cplusplus
"C"
-# endif
+# endif
_Noreturn
void abort (void)
-# if defined __cplusplus && (__GLIBC__ >= 2)
+# if defined __cplusplus && (__GLIBC__ >= 2)
_GL_ATTRIBUTE_NOTHROW
-# endif
+# endif
;
-# define unreachable() abort ()
+# define _gl_unreachable() abort ()
+#endif
+
+#ifndef __cplusplus
+/* In C, define unreachable as a macro. */
+
+# ifndef unreachable
+# define unreachable() _gl_unreachable ()
+# endif
+
+#else
+/* In C++, define unreachable as an inline function. */
+
+/* With some versions of MSVC, the inclusion of <utility> here causes errors
+ when <cstddef> gets included:
+ type_traits(1164): error C2065: 'max_align_t': undeclared identifier */
+# if !defined _MSC_VER
+extern "C++" { /* needed for Cygwin */
+# include <utility>
+}
+# endif
+
+# if defined __cpp_lib_unreachable /* C++23 or newer */
+
+using std::unreachable;
+
+# else
+
+inline void unreachable () { _gl_unreachable (); }
+
# endif
#endif
# stddef_h.m4
-# serial 21
+# serial 22
dnl Copyright (C) 2009-2025 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
GL_GENERATE_STDDEF_H=true
fi
- AC_CACHE_CHECK([for unreachable],
- [gl_cv_func_unreachable],
+ AC_CACHE_CHECK([for unreachable in C],
+ [gl_cv_c_func_unreachable],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[#include <stddef.h>
]],
[[unreachable ();
]])],
- [gl_cv_func_unreachable=yes],
- [gl_cv_func_unreachable=no])
+ [gl_cv_c_func_unreachable=yes],
+ [gl_cv_c_func_unreachable=no])
])
- if test $gl_cv_func_unreachable = no; then
+ if test $gl_cv_c_func_unreachable = no; then
GL_GENERATE_STDDEF_H=true
fi
+ if test "$CXX" != no; then
+ dnl C++ <utility> has std::unreachable,
+ dnl see <https://en.cppreference.com/w/cpp/utility/unreachable>,
+ dnl but we want an unreachable() that is available from <stddef.h>,
+ dnl like in ISO C 23.
+ AC_CACHE_CHECK([for unreachable in <stddef.h> in C++],
+ [gl_cv_cxx_func_unreachable],
+ [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to
+ dnl an autoconf bug <https://savannah.gnu.org/support/?110294>.
+ cat > conftest.cpp <<\EOF
+#include <stddef.h>
+int main (void) { unreachable (); }
+EOF
+ gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp"
+ if AC_TRY_EVAL([gl_command]); then
+ gl_cv_cxx_func_unreachable=yes
+ else
+ gl_cv_cxx_func_unreachable=no
+ fi
+ rm -fr conftest*
+ ])
+ if test $gl_cv_cxx_func_unreachable = no; then
+ GL_GENERATE_STDDEF_H=true
+ fi
+ fi
dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114869
AC_CACHE_CHECK([whether nullptr_t needs <stddef.h>],
Files:
tests/test-stddef-h-c++.cc
tests/test-stddef-h-c++2.cc
+tests/test-stddef-h-c++3.cc
Status:
c++-test
if ANSICXX
TESTS += test-stddef-h-c++
check_PROGRAMS += test-stddef-h-c++
-test_stddef_h_c___SOURCES = test-stddef-h-c++.cc test-stddef-h-c++2.cc
+test_stddef_h_c___SOURCES = test-stddef-h-c++.cc test-stddef-h-c++2.cc test-stddef-h-c++3.cc
endif
/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
#define GNULIB_NAMESPACE gnulib
-#include <config.h>
-
-#include <stddef.h>
-
-
-int
-main ()
-{
-}
+#include "test-stddef-h.c"
<https://en.cppreference.com/w/cpp/header/cstddef>. */
/* Check that appropriate types are defined. */
-ptrdiff_t b = 1;
-size_t c = 2;
+ptrdiff_t b2 = 1;
+size_t c2 = 2;
-#if !defined __cplusplus || defined __GNUC__ || defined __clang__
+#if !(defined __cplusplus && defined _MSC_VER)
/* Check that NULL can be passed through varargs as a pointer type,
per POSIX 2008. */
static_assert (sizeof NULL == sizeof (void *));
--- /dev/null
+/* Test of <stddef.h> substitute in C++ mode.
+ Copyright (C) 2019-2025 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/>. */
+
+#include <config.h>
+
+/* Define unreachable. */
+#include <stddef.h>
+/* Define std::unreachable (in C++23 or newer). */
+#include <utility>
+
+void
+test_cxx_unreachable_1 ()
+{
+ if (2 < 1)
+ unreachable ();
+#if defined __cpp_lib_unreachable
+ if (3 < 1)
+ std::unreachable ();
+#endif
+}
+
+#if defined __cpp_lib_unreachable
+using std::unreachable;
+
+void
+test_cxx_unreachable_2 ()
+{
+ if (3 < 1)
+ unreachable ();
+}
+#endif
wchar_t a = 'c';
ptrdiff_t b = 1;
size_t c = 2;
+#if !defined __cplusplus || __cplusplus >= 201103
max_align_t mat;
+#endif
+#if !(defined __cplusplus && defined _MSC_VER)
/* Check that NULL can be passed through varargs as a pointer type,
per POSIX 2008. */
static_assert (sizeof NULL == sizeof (void *));
+#endif
/* Check that offsetof produces integer constants with correct type. */
struct d
static_assert (sizeof (offsetof (struct d, e)) == sizeof (size_t));
static_assert (offsetof (struct d, f) == 1);
+#if !defined __cplusplus || __cplusplus >= 201103
/* Check max_align_t's alignment. */
static_assert (alignof (double) <= alignof (max_align_t));
static_assert (alignof (int) <= alignof (max_align_t));
static_assert (alignof (size_t) <= alignof (max_align_t));
static_assert (alignof (wchar_t) <= alignof (max_align_t));
static_assert (alignof (struct d) <= alignof (max_align_t));
-#if defined __GNUC__ || defined __clang__ || defined __IBM__ALIGNOF__
+# if defined __GNUC__ || defined __clang__ || defined __IBM__ALIGNOF__
static_assert (__alignof__ (double) <= __alignof__ (max_align_t));
static_assert (__alignof__ (int) <= __alignof__ (max_align_t));
static_assert (__alignof__ (long double) <= __alignof__ (max_align_t));
static_assert (__alignof__ (size_t) <= __alignof__ (max_align_t));
static_assert (__alignof__ (wchar_t) <= __alignof__ (max_align_t));
static_assert (__alignof__ (struct d) <= __alignof__ (max_align_t));
+# endif
#endif
int test_unreachable_optimization (int x);