* m4/stddef_h.m4 (gl_STDDEF_H): Set and substitute HAVE_C_UNREACHABLE.
Don't test for unreachable in <stddef.h> in C++. Set
GL_GENERATE_STDDEF_H to true always.
* lib/stddef.in.h (gl_unreachable): Renamed from _gl_unreachable. Test
HAVE_C_UNREACHABLE.
(unreachable): Don't define in C++ mode. Don't define if
HAVE_C_UNREACHABLE is 1.
* modules/stddef-h (Makefile.am): Substitute HAVE_C_UNREACHABLE.
* tests/test-stddef-h.c (test_unreachable_optimization,
test_unreachable_noreturn): Don't define in C++ mode.
(test_gl_unreachable_optimization, test_gl_unreachable_noreturn): New
functions.
* tests/test-stddef-h-c++3.cc (test_cxx_unreachable_1): Test
gl_unreachable instead of unreachable.
* lib/error.in.h (__gl_error_call1): Use gl_unreachable instead of
unreachable.
+2025-06-02 Bruno Haible <bruno@clisp.org>
+
+ stddef-h: Fix compilation errors in C++ mode (regression 2025-05-27).
+ * m4/stddef_h.m4 (gl_STDDEF_H): Set and substitute HAVE_C_UNREACHABLE.
+ Don't test for unreachable in <stddef.h> in C++. Set
+ GL_GENERATE_STDDEF_H to true always.
+ * lib/stddef.in.h (gl_unreachable): Renamed from _gl_unreachable. Test
+ HAVE_C_UNREACHABLE.
+ (unreachable): Don't define in C++ mode. Don't define if
+ HAVE_C_UNREACHABLE is 1.
+ * modules/stddef-h (Makefile.am): Substitute HAVE_C_UNREACHABLE.
+ * tests/test-stddef-h.c (test_unreachable_optimization,
+ test_unreachable_noreturn): Don't define in C++ mode.
+ (test_gl_unreachable_optimization, test_gl_unreachable_noreturn): New
+ functions.
+ * tests/test-stddef-h-c++3.cc (test_cxx_unreachable_1): Test
+ gl_unreachable instead of unreachable.
+ * lib/error.in.h (__gl_error_call1): Use gl_unreachable instead of
+ unreachable.
+
2025-06-02 Bruno Haible <bruno@clisp.org>
open, openat: Fix test failure on native Windows.
/* Get va_list. */
#include <stdarg.h>
-/* Get 'unreachable'. */
+/* Get 'gl_unreachable'. */
#include <stddef.h>
/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM. */
It evaluates its arguments only once.
Test case: Compile copy-file.c with "gcc -Wimplicit-fallthrough". */
#if defined __GNUC__ || defined __clang__
-/* Use 'unreachable' to tell the compiler when the function call does not
+/* Use 'gl_unreachable' to tell the compiler when the function call does not
return. */
# define __gl_error_call1(function, status, ...) \
((function) (status, __VA_ARGS__), \
- (status) != 0 ? unreachable () : (void) 0)
+ (status) != 0 ? gl_unreachable () : (void) 0)
/* If STATUS is a not a constant, the function call may or may not return;
therefore -Wimplicit-fallthrough will produce a warning. Use a compound
statement in order to evaluate STATUS only once.
#endif
/* ISO C 23 ยง 7.21.1 The unreachable macro */
+/* This macro is only usable in C, not in C++.
+ There is no way to define it as a macro in C++, because that would break code
+ that does
+ #include <utility>
+ ... std::unreachable() ...
+ Similarly, there is no way to define it as an inline function in C++, because
+ that would break code that does
+ #include <utility>
+ using std::unreachable;
+ As a workaround, we define a macro gl_unreachable, that is like unreachable,
+ but is usable in both C and C++. */
/* Code borrowed from verify.h. */
#ifndef _GL_HAS_BUILTIN_UNREACHABLE
#endif
#if _GL_HAS_BUILTIN_UNREACHABLE
-# define _gl_unreachable() __builtin_unreachable ()
+# define gl_unreachable() __builtin_unreachable ()
#elif 1200 <= _MSC_VER
-# define _gl_unreachable() __assume (0)
+# define gl_unreachable() __assume (0)
+#elif !defined __cplusplus && @HAVE_C_UNREACHABLE@
+# define gl_unreachable() unreachable ()
#else
/* Declare abort(), without including <stdlib.h>. */
extern
_GL_ATTRIBUTE_NOTHROW
# endif
;
-# define _gl_unreachable() abort ()
+# define gl_unreachable() abort ()
#endif
-#ifndef __cplusplus
+#if !defined __cplusplus && !@HAVE_C_UNREACHABLE@
/* 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 (); }
-
+# define unreachable() gl_unreachable ()
# endif
#endif
# stddef_h.m4
-# serial 22
+# serial 23
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,
])
if test $gl_cv_c_func_unreachable = no; then
GL_GENERATE_STDDEF_H=true
+ HAVE_C_UNREACHABLE=0
+ else
+ HAVE_C_UNREACHABLE=1
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
+ AC_SUBST([HAVE_C_UNREACHABLE])
+ dnl Provide gl_unreachable() unconditionally.
+ GL_GENERATE_STDDEF_H=true
dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114869
AC_CACHE_CHECK([whether nullptr_t needs <stddef.h>],
-e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \
-e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \
-e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \
+ -e 's|@''HAVE_C_UNREACHABLE''@|$(HAVE_C_UNREACHABLE)|g' \
$(srcdir)/stddef.in.h > $@-t
$(AM_V_at)mv $@-t $@
else
#include <config.h>
-/* Define unreachable. */
+/* Define gl_unreachable. */
#include <stddef.h>
/* Define std::unreachable (in C++23 or newer). */
#include <utility>
test_cxx_unreachable_1 ()
{
if (2 < 1)
- unreachable ();
+ gl_unreachable ();
#if defined __cpp_lib_unreachable
if (3 < 1)
std::unreachable ();
# endif
#endif
+
+#ifndef __cplusplus
+
+/* Test 'unreachable'. */
+
int test_unreachable_optimization (int x);
_Noreturn void test_unreachable_noreturn (void);
unreachable ();
}
+#endif
+
+
+/* Test 'gl_unreachable'. */
+
+int test_gl_unreachable_optimization (int x);
+_Noreturn void test_gl_unreachable_noreturn (void);
+
+int
+test_gl_unreachable_optimization (int x)
+{
+ /* Check that the compiler uses 'gl_unreachable' for optimization.
+ This function, when compiled with optimization, should have code
+ equivalent to
+ return x + 3;
+ Use 'objdump --disassemble test-stddef.o' to verify this. */
+ if (x < 4)
+ gl_unreachable ();
+ return (x > 1 ? x + 3 : 2 * x + 10);
+}
+
+_Noreturn void
+test_gl_unreachable_noreturn (void)
+{
+ /* Check that the compiler's data-flow analysis recognizes
+ 'gl_unreachable ()'. This function should not elicit a warning. */
+ gl_unreachable ();
+}
+
+
#include <limits.h> /* INT_MAX */
/* offsetof promotes to an unsigned integer if and only if sizes do