From 58b18135fca550b6de4892bdb8a66e0ea0aca2b1 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 23 Feb 2026 07:57:16 +0100 Subject: [PATCH] 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.) --- config/c-compiler.m4 | 16 ---------------- configure | 31 ------------------------------- configure.ac | 1 - meson.build | 13 ------------- src/include/c.h | 30 ++++++++++++++++++++++-------- 5 files changed, 22 insertions(+), 69 deletions(-) diff --git a/config/c-compiler.m4 b/config/c-compiler.m4 index 1509dbfa2ab..f9e86bcf0f5 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 e1a08129974..5128e60803d 100755 --- a/configure +++ b/configure @@ -14895,37 +14895,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 cc85c233c03..2ea629a2172 100644 --- a/configure.ac +++ b/configure.ac @@ -1714,7 +1714,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_C_TYPES_COMPATIBLE PGAC_C_BUILTIN_CONSTANT_P diff --git a/meson.build b/meson.build index 055e96315d0..9ce9ec7dcd1 100644 --- a/meson.build +++ b/meson.build @@ -1935,19 +1935,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 7ee4751992f..788249c9dec 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -960,18 +960,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 /* -- 2.53.0