On Tue, 9 Dec 2025 at 13:43, Jelte Fennema-Nio <[email protected]> wrote:
You mean use const_cast in c++ instead of a C-style cast? Would you
still want to keep the static asserts.

I now understand that you meant to not remove these lines:
-#if defined(__cplusplus)
-#define unconstify(underlying_type, expr) const_cast<underlying_type>(expr)
-#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)

So like the attached. I think that makes sense.
From b77214510b9c5cdf2b0d0130526f98d3ab8a7864 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Fri, 31 Oct 2025 06:07:15 +1300
Subject: [PATCH v2] Add pg_expr_has_type_p() for type check assertions.

Remove use of GCC builtins, so our existing type check macros can work
on Visual Studio too.  This relies on new features in C11/C++11.

XXX works on Visual Studio 2022, crashes on Visual Studio 2019:

[23:39:47.176] ../src/common/file_utils.c(712): fatal error C1001: Internal compiler error.
[23:39:47.176] (compiler file 'msc1.cpp', line 1603)
[23:39:47.176]  To work around this problem, try simplifying or changing the program near the locations listed above.
---
 config/c-compiler.m4       | 19 ------------------
 configure                  | 30 ----------------------------
 configure.ac               |  1 -
 meson.build                | 15 --------------
 src/include/c.h            | 41 +++++++++++++++++---------------------
 src/include/pg_config.h.in |  3 ---
 src/include/utils/relptr.h | 16 ++++-----------
 7 files changed, 22 insertions(+), 103 deletions(-)

diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 236a59e8536..26d5269e58a 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -161,25 +161,6 @@ fi])# PGAC_C_TYPEOF
 
 
 
-# PGAC_C_TYPES_COMPATIBLE
-# -----------------------
-# Check if the C compiler understands __builtin_types_compatible_p,
-# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
-#
-# We check usage with __typeof__, though it's unlikely any compiler would
-# have the former and not the latter.
-AC_DEFUN([PGAC_C_TYPES_COMPATIBLE],
-[AC_CACHE_CHECK(for __builtin_types_compatible_p, pgac_cv__types_compatible,
-[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
-[[ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; ]])],
-[pgac_cv__types_compatible=yes],
-[pgac_cv__types_compatible=no])])
-if test x"$pgac_cv__types_compatible" = xyes ; then
-AC_DEFINE(HAVE__BUILTIN_TYPES_COMPATIBLE_P, 1,
-          [Define to 1 if your compiler understands __builtin_types_compatible_p.])
-fi])# PGAC_C_TYPES_COMPATIBLE
-
-
 # PGAC_C_BUILTIN_CONSTANT_P
 # -------------------------
 # Check if the C compiler understands __builtin_constant_p(),
diff --git a/configure b/configure
index ec35de5ba65..48c3799af46 100755
--- a/configure
+++ b/configure
@@ -14828,36 +14828,6 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
   fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_types_compatible_p" >&5
-$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
-if ${pgac_cv__types_compatible+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
- int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)];
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  pgac_cv__types_compatible=yes
-else
-  pgac_cv__types_compatible=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pgac_cv__types_compatible" >&5
-$as_echo "$pgac_cv__types_compatible" >&6; }
-if test x"$pgac_cv__types_compatible" = xyes ; then
-
-$as_echo "#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1" >>confdefs.h
-
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_constant_p" >&5
 $as_echo_n "checking for __builtin_constant_p... " >&6; }
diff --git a/configure.ac b/configure.ac
index 7284f1ff622..fe7e2610f70 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1678,7 +1678,6 @@ AC_C_INLINE
 PGAC_PRINTF_ARCHETYPE
 PGAC_C_STATIC_ASSERT
 PGAC_C_TYPEOF
-PGAC_C_TYPES_COMPATIBLE
 PGAC_C_BUILTIN_CONSTANT_P
 PGAC_C_BUILTIN_OP_OVERFLOW
 PGAC_C_BUILTIN_UNREACHABLE
diff --git a/meson.build b/meson.build
index 622598546ae..2b67500af8b 100644
--- a/meson.build
+++ b/meson.build
@@ -1950,21 +1950,6 @@ foreach builtin : builtins
 endforeach
 
 
-# Check if the C compiler understands __builtin_types_compatible_p,
-# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
-#
-# We check usage with __typeof__, though it's unlikely any compiler would
-# have the former and not the latter.
-if cc.compiles('''
-    static int x;
-    static int y[__builtin_types_compatible_p(__typeof__(x), int)];
-    ''',
-    name: '__builtin_types_compatible_p',
-    args: test_c_args)
-  cdata.set('HAVE__BUILTIN_TYPES_COMPATIBLE_P', 1)
-endif
-
-
 # Check if the C compiler understands __builtin_$op_overflow(),
 # and define HAVE__BUILTIN_OP_OVERFLOW if so.
 #
diff --git a/src/include/c.h b/src/include/c.h
index 62cbf7a2eec..2ccdfd10fa7 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -81,6 +81,13 @@
 #endif
 #ifdef ENABLE_NLS
 #include <libintl.h>
+#endif
+
+#ifdef __cplusplus
+extern "C++"
+{
+#include <type_traits>
+}
 #endif
 
  /* Pull in fundamental symbols that we also expose to applications */
@@ -967,26 +974,19 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName,
  * AssertVariableIsOfType() can be used as a statement.
  * AssertVariableIsOfTypeMacro() is intended for use in macros, eg
  *		#define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
- *
- * If we don't have __builtin_types_compatible_p, we can still assert that
- * the types have the same size.  This is far from ideal (especially on 32-bit
- * platforms) but it provides at least some coverage.
  */
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
-#define AssertVariableIsOfType(varname, typename) \
-	StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
-	CppAsString(varname) " does not have type " CppAsString(typename))
-#define AssertVariableIsOfTypeMacro(varname, typename) \
-	(StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
-	 CppAsString(varname) " does not have type " CppAsString(typename)))
-#else							/* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+#ifdef __cplusplus
+#define pg_expr_has_type_p(expr, typename) \
+	std::is_same<std::remove_reference<decltype(expr)>::type, typename>::value
+#else
+#define pg_expr_has_type_p(expr, typename) _Generic((expr), typename: 1, default: 0)
+#endif
 #define AssertVariableIsOfType(varname, typename) \
-	StaticAssertStmt(sizeof(varname) == sizeof(typename), \
+	StaticAssertStmt(pg_expr_has_type_p(varname, typename), \
 	CppAsString(varname) " does not have type " CppAsString(typename))
 #define AssertVariableIsOfTypeMacro(varname, typename) \
-	(StaticAssertExpr(sizeof(varname) == sizeof(typename), \
+	(StaticAssertExpr(pg_expr_has_type_p(varname, typename), \
 	 CppAsString(varname) " does not have type " CppAsString(typename)))
-#endif							/* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
 
 
 /* ----------------------------------------------------------------
@@ -1223,20 +1223,15 @@ typedef struct PGAlignedXLogBlock
 #if defined(__cplusplus)
 #define unconstify(underlying_type, expr) const_cast<underlying_type>(expr)
 #define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
-#elif defined(HAVE__BUILTIN_TYPES_COMPATIBLE_P)
+#else
 #define unconstify(underlying_type, expr) \
-	(StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), const underlying_type), \
+	(StaticAssertExpr(pg_expr_has_type_p((expr), const underlying_type), \
 					  "wrong cast"), \
 	 (underlying_type) (expr))
 #define unvolatize(underlying_type, expr) \
-	(StaticAssertExpr(__builtin_types_compatible_p(__typeof(expr), volatile underlying_type), \
+	(StaticAssertExpr(pg_expr_has_type_p((expr), volatile underlying_type), \
 					  "wrong cast"), \
 	 (underlying_type) (expr))
-#else
-#define unconstify(underlying_type, expr) \
-	((underlying_type) (expr))
-#define unvolatize(underlying_type, expr) \
-	((underlying_type) (expr))
 #endif
 
 /* ----------------------------------------------------------------
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b0b0cfdaf79..4a25155239e 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -547,9 +547,6 @@
 /* Define to 1 if your compiler understands __builtin_popcount. */
 #undef HAVE__BUILTIN_POPCOUNT
 
-/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
-#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
-
 /* Define to 1 if your compiler understands __builtin_unreachable. */
 #undef HAVE__BUILTIN_UNREACHABLE
 
diff --git a/src/include/utils/relptr.h b/src/include/utils/relptr.h
index ea340fee657..48e394dba71 100644
--- a/src/include/utils/relptr.h
+++ b/src/include/utils/relptr.h
@@ -38,16 +38,12 @@
 #define relptr_declare(type, relptrtype) \
 	typedef relptr(type) relptrtype
 
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#ifdef HAVE_TYPEOF
 #define relptr_access(base, rp) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
-	 (__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
+	 (typeof((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
 		(base) + (rp).relptr_off - 1))
 #else
-/*
- * If we don't have __builtin_types_compatible_p, assume we might not have
- * __typeof__ either.
- */
 #define relptr_access(base, rp) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
 	 (void *) ((rp).relptr_off == 0 ? NULL : (base) + (rp).relptr_off - 1))
@@ -72,16 +68,12 @@ relptr_store_eval(char *base, char *val)
 	}
 }
 
-#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#ifdef HAVE_TYPEOF
 #define relptr_store(base, rp, val) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
-	 AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
+	 AssertVariableIsOfTypeMacro(val, typeof((rp).relptr_type)), \
 	 (rp).relptr_off = relptr_store_eval((base), (char *) (val)))
 #else
-/*
- * If we don't have __builtin_types_compatible_p, assume we might not have
- * __typeof__ either.
- */
 #define relptr_store(base, rp, val) \
 	(AssertVariableIsOfTypeMacro(base, char *), \
 	 (rp).relptr_off = relptr_store_eval((base), (char *) (val)))

base-commit: f231a4e8c7f2ce93203cedea7a02ef3eeb744647
-- 
2.52.0

Reply via email to