From 90c94dddfd57b7d744bfad64c54e10d15778144b Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Fri, 8 Sep 2023 18:19:26 +0300 Subject: [PATCH] tuklib: Update tuklib_attr_noreturn for C11/C17 and C23. This makes no difference for GCC or Clang as they support GNU C's __attribute__((__noreturn__)) but this helps with MSVC: - VS 2019 version 16.7 and later support _Noreturn if the options /std:c11 or /std:c17 are used. This gets handled with the check for __STDC_VERSION__ >= 201112. - When MSVC isn't in C11/C17 mode, __declspec(noreturn) is used. C23 will deprecate _Noreturn (and ) for [[noreturn]]. This commit anticipates that but the final __STDC_VERSION__ value isn't known yet. --- src/common/tuklib_common.h | 22 +++++++++++++++++++++- src/common/tuklib_exit.h | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/common/tuklib_common.h b/src/common/tuklib_common.h index b1f531ea..724b8c0e 100644 --- a/src/common/tuklib_common.h +++ b/src/common/tuklib_common.h @@ -57,8 +57,28 @@ # define TUKLIB_GNUC_REQ(major, minor) 0 #endif -#if TUKLIB_GNUC_REQ(2, 5) +// tuklib_attr_noreturn attribute is used to mark functions as non-returning. +// We cannot use "noreturn" as the macro name because then C23 code that +// uses [[noreturn]] would break as it would expand to [[ [[noreturn]] ]]. +// +// tuklib_attr_noreturn must be used at the beginning of function declaration +// to work in all cases. The [[noreturn]] syntax is the most limiting, it +// must be even before any GNU C's __attribute__ keywords: +// +// tuklib_attr_noreturn +// __attribute__((nonnull(1))) +// extern void foo(const char *s); +// +// FIXME: Update __STDC_VERSION__ for the final C23 version. 202000 is used +// by GCC 13 and Clang 15 with -std=c2x. +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000 +# define tuklib_attr_noreturn [[noreturn]] +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 +# define tuklib_attr_noreturn _Noreturn +#elif TUKLIB_GNUC_REQ(2, 5) # define tuklib_attr_noreturn __attribute__((__noreturn__)) +#elif defined(_MSC_VER) +# define tuklib_attr_noreturn __declspec(noreturn) #else # define tuklib_attr_noreturn #endif diff --git a/src/common/tuklib_exit.h b/src/common/tuklib_exit.h index b11776f0..f8f35a6b 100644 --- a/src/common/tuklib_exit.h +++ b/src/common/tuklib_exit.h @@ -18,8 +18,8 @@ TUKLIB_DECLS_BEGIN #define tuklib_exit TUKLIB_SYMBOL(tuklib_exit) -extern void tuklib_exit(int status, int err_status, int show_error) - tuklib_attr_noreturn; +tuklib_attr_noreturn +extern void tuklib_exit(int status, int err_status, int show_error); TUKLIB_DECLS_END #endif