bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

stddef: Define 'unreachable', for ISO C 23 compliance


From: Bruno Haible
Subject: stddef: Define 'unreachable', for ISO C 23 compliance
Date: Thu, 16 Mar 2023 13:48:50 +0100

ISO C 23 § 7.21.1 requires that <stddef.h> implements 'unreachable'.

This patch does it.


2023-03-16  Bruno Haible  <bruno@clisp.org>

        stddef: Define 'unreachable', for ISO C 23 compliance.
        * lib/verify.h (_GL_HAS_BUILTIN_UNREACHABLE): Don't define if already
        defined.
        * lib/stddef.in.h (_GL_HAS_BUILTIN_UNREACHABLE, unreachable): New
        macros.
        (abort): Declare if needed for unreachable.
        * m4/stddef_h.m4 (gl_STDDEF_H): Test for unreachable.
        * tests/test-stddef.c (test_unreachable_optimization,
        test_unreachable_noreturn): New functions, based on tests/test-verify.c.
        * doc/posix-headers/stddef.texi: Mention unreachable.

diff --git a/doc/posix-headers/stddef.texi b/doc/posix-headers/stddef.texi
index e240f93363..33ad48244c 100644
--- a/doc/posix-headers/stddef.texi
+++ b/doc/posix-headers/stddef.texi
@@ -7,6 +7,10 @@
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+Some platforms fail to provide @code{unreachable}, which was added in C23:
+GCC 13, clang 15, AIX with xlc 12.1, Solaris with Sun C 5.15, and others.
+
 @item
 Some platforms fail to provide @code{max_align_t}, which was added in C11:
 NetBSD 8.0, Solaris 11.0, and others.
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 6eadcc3d5a..9e9d4b7cc6 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -18,7 +18,7 @@
 /* Written by Eric Blake.  */
 
 /*
- * POSIX 2008 <stddef.h> for platforms that have issues.
+ * POSIX 2008 and ISO C 23 <stddef.h> for platforms that have issues.
  * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html>
  */
 
@@ -142,6 +142,43 @@ typedef union
 # endif
 #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__)
+#   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
+/* Declare abort(), without including <stdlib.h>.  */
+extern
+#  if defined __cplusplus
+"C"
+#  endif
+_Noreturn
+void abort (void)
+#  if defined __cplusplus && (__GLIBC__ >= 2)
+throw ()
+#  endif
+;
+#  define unreachable() abort ()
+# endif
+
+#endif
+
 #  endif /* _@GUARD_PREFIX@_STDDEF_H */
 # endif /* _@GUARD_PREFIX@_STDDEF_H */
 #endif /* __need_XXX */
diff --git a/lib/verify.h b/lib/verify.h
index f0b3fc5851..c700243209 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -285,14 +285,16 @@ template <int w>
 # define _GL_HAS_BUILTIN_TRAP 0
 #endif
 
-#if defined __clang_major__ && __clang_major__ < 5
-# define _GL_HAS_BUILTIN_UNREACHABLE 0
-#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
-# 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
+#ifndef _GL_HAS_BUILTIN_UNREACHABLE
+# if defined __clang_major__ && __clang_major__ < 5
+#  define _GL_HAS_BUILTIN_UNREACHABLE 0
+# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
+#  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
 
 /* Each of these macros verifies that its argument R is nonzero.  To
diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4
index a2322ebb7e..aa012219fc 100644
--- a/m4/stddef_h.m4
+++ b/m4/stddef_h.m4
@@ -1,4 +1,4 @@
-# stddef_h.m4 serial 13
+# stddef_h.m4 serial 14
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -68,6 +68,21 @@ AC_DEFUN_ONCE([gl_STDDEF_H]
     GL_GENERATE_STDDEF_H=true
   fi
 
+  AC_CACHE_CHECK([for unreachable],
+    [gl_cv_func_unreachable],
+    [AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+          [[#include <stddef.h>
+          ]],
+          [[unreachable ();
+          ]])],
+       [gl_cv_func_unreachable=yes],
+       [gl_cv_func_unreachable=no])
+    ])
+  if test $gl_cv_func_unreachable = no; then
+    GL_GENERATE_STDDEF_H=true
+  fi
+
   if $GL_GENERATE_STDDEF_H; then
     gl_NEXT_HEADERS([stddef.h])
   fi
diff --git a/tests/test-stddef.c b/tests/test-stddef.c
index 1d674b3cea..3ec00a8f25 100644
--- a/tests/test-stddef.c
+++ b/tests/test-stddef.c
@@ -68,6 +68,30 @@ static_assert (__alignof__ (wchar_t) <= __alignof__ 
(max_align_t));
 static_assert (__alignof__ (struct d) <= __alignof__ (max_align_t));
 #endif
 
+int test_unreachable_optimization (int x);
+_Noreturn void test_unreachable_noreturn (void);
+
+int
+test_unreachable_optimization (int x)
+{
+  /* Check that the compiler uses '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)
+    unreachable ();
+  return (x > 1 ? x + 3 : 2 * x + 10);
+}
+
+_Noreturn void
+test_unreachable_noreturn (void)
+{
+  /* Check that the compiler's data-flow analysis recognizes 'unreachable ()'.
+     This function should not elicit a warning.  */
+  unreachable ();
+}
+
 int
 main (void)
 {






reply via email to

[Prev in Thread] Current Thread [Next in Thread]