]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Portable StaticAssertExpr
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 6 Mar 2026 08:15:44 +0000 (09:15 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 6 Mar 2026 08:27:54 +0000 (09:27 +0100)
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 <postgres@jeltef.nl>
Discussion: https://www.postgresql.org/message-id/flat/5fa3a9f5-eb9a-4408-9baf-403d281f8b10%40eisentraut.org

config/c-compiler.m4
configure
configure.ac
meson.build
src/include/c.h
src/include/pg_config.h.in

index 5b3cbc7e8e8eefc2d1a1d02db90a658d141c474b..5fd768b7332f1e93fdbe25200c5072929cd429b5 100644 (file)
@@ -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
index b30b98a586e72d7f6135c20c484d22f7380eaaae..4aaaf92ba0a12301281a8dcaeccc76f093afab68 100755 (executable)
--- 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 :
index f4e3bd307c8425e923a20aded4f3cb19af147e76..9bc457bac87a2ace2ebcd67818949332b9c5ca70 100644 (file)
@@ -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
index ddf5172982fb6e78b8bfd108c33458b94ed40941..2df54409ca6b1956ff97644a797852cd9d02187f 100644 (file)
@@ -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
index a4fee84398d040a584d6d254a5069da52f8b3ae6..c00a9ecf21dfb17f99e9316824ea2e72955fe3a3 100644 (file)
@@ -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 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3715.pdf> for some
+ * rationale for the precise behavior of this implementation.  See
+ * <https://stackoverflow.com/questions/31311748> 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
 
 
 /*
index f64b198738bc949e21cb861ab475b2b87f4c13df..cb0f53fade435c9ca63678b9be7b76b9bfe39d93 100644 (file)
 /* 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 <stdint.h> header file. */
 #undef HAVE_STDINT_H