From: Peter Eisentraut Date: Fri, 6 Mar 2026 08:15:44 +0000 (+0100) Subject: Portable StaticAssertExpr X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa7c86852343dd18f5834f70e4caa50ae49326c9;p=thirdparty%2Fpostgresql.git Portable StaticAssertExpr Use a different way to write StaticAssertExpr() that does not require the GCC extension statement expressions. For C, we put the static_assert into a struct. This appears to be a common approach. We still need to keep the fallback implementation to support buggy MSVC < 19.33. For C++, we put it into a lambda expression. (The C approach doesn't work; it's not permitted to define a new type inside sizeof.) Reviewed-by: Jelte Fennema-Nio Discussion: https://www.postgresql.org/message-id/flat/5fa3a9f5-eb9a-4408-9baf-403d281f8b10%40eisentraut.org --- diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 5b3cbc7e8e8..5fd768b7332 100644 --- a/config/c-compiler.m4 +++ b/config/c-compiler.m4 @@ -150,22 +150,6 @@ fi])# PGAC_TYPE_128BIT_INT -# PGAC_C_STATEMENT_EXPRESSIONS -# ---------------------------- -# Check if the C compiler understands GCC statement expressions. -AC_DEFUN([PGAC_C_STATEMENT_EXPRESSIONS], -[AC_CACHE_CHECK(for statement expressions, pgac_cv_statement_expressions, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([], -[({ _Static_assert(1, "foo"); })])], -[pgac_cv_statement_expressions=yes], -[pgac_cv_statement_expressions=no])]) -if test x"$pgac_cv_statement_expressions" = xyes ; then -AC_DEFINE(HAVE_STATEMENT_EXPRESSIONS, 1, - [Define to 1 if your compiler supports statement expressions.]) -fi])# PGAC_C_STATEMENT_EXPRESSIONS - - - # PGAC_C_TYPEOF # ------------- # Check if the C compiler understands typeof or a variant. Define diff --git a/configure b/configure index b30b98a586e..4aaaf92ba0a 100755 --- a/configure +++ b/configure @@ -15005,37 +15005,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for statement expressions" >&5 -$as_echo_n "checking for statement expressions... " >&6; } -if ${pgac_cv_statement_expressions+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -({ _Static_assert(1, "foo"); }) - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - pgac_cv_statement_expressions=yes -else - pgac_cv_statement_expressions=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv_statement_expressions" >&5 -$as_echo "$pgac_cv_statement_expressions" >&6; } -if test x"$pgac_cv_statement_expressions" = xyes ; then - -$as_echo "#define HAVE_STATEMENT_EXPRESSIONS 1" >>confdefs.h - -fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof" >&5 $as_echo_n "checking for typeof... " >&6; } if ${pgac_cv_c_typeof+:} false; then : diff --git a/configure.ac b/configure.ac index f4e3bd307c8..9bc457bac87 100644 --- a/configure.ac +++ b/configure.ac @@ -1730,7 +1730,6 @@ m4_defun([AC_PROG_CC_STDC], []) dnl We don't want that. AC_C_BIGENDIAN PGAC_PRINTF_ARCHETYPE PGAC_CXX_PRINTF_ARCHETYPE -PGAC_C_STATEMENT_EXPRESSIONS PGAC_C_TYPEOF PGAC_CXX_TYPEOF PGAC_C_TYPES_COMPATIBLE diff --git a/meson.build b/meson.build index ddf5172982f..2df54409ca6 100644 --- a/meson.build +++ b/meson.build @@ -1990,19 +1990,6 @@ if cc.compiles(''' endif -# Check if the C compiler supports GCC-style statement expressions. -if cc.compiles(''' - int main(int arg, char **argv) - { - ({ _Static_assert(1, "foo"); }); - } - ''', - name: 'statement expressions', - args: test_c_args) - cdata.set('HAVE_STATEMENT_EXPRESSIONS', 1) -endif - - # Select the format archetype to be used to check printf-type functions. # # Need to check a call with %m because netbsd supports gnu_printf but emits a diff --git a/src/include/c.h b/src/include/c.h index a4fee84398d..c00a9ecf21d 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -981,18 +981,32 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName, /* * StaticAssertExpr() is for use in an expression. * - * For compilers without GCC statement expressions, we fall back on a kluge - * that assumes the compiler will complain about a negative width for a struct - * bit-field. This will not include a helpful error message, but it beats not - * getting an error at all. + * See for some + * rationale for the precise behavior of this implementation. See + * about the C++ + * implementation. + * + * For compilers that don't support this, we fall back on a kluge that assumes + * the compiler will complain about a negative width for a struct bit-field. + * This will not include a helpful error message, but it beats not getting an + * error at all. */ -#ifdef HAVE_STATEMENT_EXPRESSIONS +#ifndef __cplusplus +#if !defined(_MSC_VER) || _MSC_VER >= 1933 #define StaticAssertExpr(condition, errmessage) \ - ((void) ({ static_assert(condition, errmessage); true; })) -#else + ((void) sizeof(struct {static_assert(condition, errmessage); char a;})) +#else /* _MSC_VER < 1933 */ +/* + * This compiler is buggy and fails to compile the previous variant; use a + * fallback implementation. + */ #define StaticAssertExpr(condition, errmessage) \ ((void) sizeof(struct { int static_assert_failure : (condition) ? 1 : -1; })) -#endif /* HAVE_STATEMENT_EXPRESSIONS */ +#endif /* _MSC_VER < 1933 */ +#else /* __cplusplus */ +#define StaticAssertExpr(condition, errmessage) \ + ([]{static_assert(condition, errmessage);}) +#endif /* diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index f64b198738b..cb0f53fade4 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -374,9 +374,6 @@ /* Define to 1 if you have the `SSL_CTX_set_num_tickets' function. */ #undef HAVE_SSL_CTX_SET_NUM_TICKETS -/* Define to 1 if your compiler supports statement expressions. */ -#undef HAVE_STATEMENT_EXPRESSIONS - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H