As suggested at [0], we can move the computation of MAXIMUM_ALIGNOF from configure.ac and meson.build to c.h. This eliminates code duplication. (For example, the AIX patch contemplates some changes, so it would be good to make those in only one place.) Also, it used to be more complicated, but now it's not really a computation anymore, it's just a #define and two static assertions, so it's just much easier and natural this way. (For example, doing a symbol lookup on MAXIMUM_ALIGNOF will take you to a place with useful context, instead of to pg_config.h.)

The only trick is that the there are some ordering problems in c.h. MAXIMUM_ALIGNOF is used in the definition of the int128, which comes very early, before the alignment handling. I moved the int128 stuff to later in the file, near other types with alignment dependencies. (If you look closer, you will find other opportunities for a more comprehensive reshuffling in c.h, but maybe that should be a separate project.)

[0]: https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.gmail.com
From 6f7bcca6fc2736af6ba582aaa4233599f8185756 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 20 Jan 2026 07:20:30 +0100
Subject: [PATCH] Move MAXIMUM_ALIGNOF definition to c.h

This combines duplicate code from configure.in and meson.build.

Discussion: 
https://www.postgresql.org/message-id/CA%2BhUKGLQUivg-NC7dHdbRAPmG0Hapg1gGnygM5KgDfDM2a_TMg%40mail.gmail.com
---
 configure                  | 30 --------------
 configure.ac               | 26 ------------
 meson.build                | 25 +-----------
 src/include/c.h            | 81 +++++++++++++++++++++++++-------------
 src/include/pg_config.h.in |  3 --
 5 files changed, 56 insertions(+), 109 deletions(-)

diff --git a/configure b/configure
index fb6a4914b06..5f6f79c9516 100755
--- a/configure
+++ b/configure
@@ -17110,36 +17110,6 @@ _ACEOF
 
 
 
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types.  That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple.  We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that long's alignment is at least as strong as
-# char, short, or int.  Note that we intentionally do not consider any types
-# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too
-# much of a penalty for disk and memory space.
-
-MAX_ALIGNOF=$ac_cv_alignof_double
-
-if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'long' is greater than the alignment of 
'double'" "$LINENO" 5
-fi
-if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
-  as_fn_error $? "alignment of 'int64_t' is greater than the alignment of 
'double'" "$LINENO" 5
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define MAXIMUM_ALIGNOF $MAX_ALIGNOF
-_ACEOF
-
-
 # Some compilers offer a 128-bit integer scalar type.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
 $as_echo_n "checking for __int128... " >&6; }
diff --git a/configure.ac b/configure.ac
index d3febfe58f1..dde7dcfa35f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1995,32 +1995,6 @@ AC_CHECK_ALIGNOF(long)
 AC_CHECK_ALIGNOF(int64_t)
 AC_CHECK_ALIGNOF(double)
 
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types.  That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple.  We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that long's alignment is at least as strong as
-# char, short, or int.  Note that we intentionally do not consider any types
-# wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8 would be too
-# much of a penalty for disk and memory space.
-
-MAX_ALIGNOF=$ac_cv_alignof_double
-
-if test $ac_cv_alignof_long -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'long' is greater than the alignment of 'double'])
-fi
-if test $ac_cv_alignof_int64_t -gt $MAX_ALIGNOF ; then
-  AC_MSG_ERROR([alignment of 'int64_t' is greater than the alignment of 
'double'])
-fi
-AC_DEFINE_UNQUOTED(MAXIMUM_ALIGNOF, $MAX_ALIGNOF, [Define as the maximum 
alignment requirement of any C data type.])
-
 # Some compilers offer a 128-bit integer scalar type.
 PGAC_TYPE_128BIT_INT
 
diff --git a/meson.build b/meson.build
index 6d304f32fb0..c5fc29ed681 100644
--- a/meson.build
+++ b/meson.build
@@ -1771,33 +1771,12 @@ endif
 
 # Determine memory alignment requirements for the basic C data types.
 
-alignof_types = ['short', 'int', 'long', 'double']
+alignof_types = ['short', 'int', 'long', 'int64_t', 'double']
 foreach t : alignof_types
-  align = cc.alignment(t, args: test_c_args)
+  align = cc.alignment(t, args: test_c_args, prefix: '#include <stdint.h>')
   cdata.set('ALIGNOF_@0@'.format(t.to_upper()), align)
 endforeach
 
-# Compute maximum alignment of any basic type.
-#
-# We require 'double' to have the strictest alignment among the basic types,
-# because otherwise the C ABI might impose 8-byte alignment on some of the
-# other C types that correspond to TYPALIGN_DOUBLE SQL types.  That could
-# cause a mismatch between the tuple layout and the C struct layout of a
-# catalog tuple.  We used to carefully order catalog columns such that any
-# fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
-# of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
-# where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
-#
-# We assume without checking that int64_t's alignment is at least as strong
-# as long, char, short, or int.  Note that we intentionally do not consider
-# any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to exceed 8
-# would be too much of a penalty for disk and memory space.
-alignof_double = cdata.get('ALIGNOF_DOUBLE')
-if cc.alignment('int64_t', args: test_c_args, prefix: '#include <stdint.h>') > 
alignof_double
-  error('alignment of int64_t is greater than the alignment of double')
-endif
-cdata.set('MAXIMUM_ALIGNOF', alignof_double)
-
 cdata.set('SIZEOF_LONG', cc.sizeof('long', args: test_c_args))
 cdata.set('SIZEOF_LONG_LONG', cc.sizeof('long long', args: test_c_args))
 cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: test_c_args))
diff --git a/src/include/c.h b/src/include/c.h
index 7136102e5ff..b6a7330c88f 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -565,33 +565,6 @@ typedef uint32 bits32;                     /* >= 32 bits */
 #define UINT64_FORMAT "%" PRIu64
 #define OID8_FORMAT "%" PRIu64
 
-/*
- * 128-bit signed and unsigned integers
- *             There currently is only limited support for such types.
- *             E.g. 128bit literals and snprintf are not supported; but math 
is.
- *             Also, because we exclude such types when choosing 
MAXIMUM_ALIGNOF,
- *             it must be possible to coerce the compiler to allocate them on 
no
- *             more than MAXALIGN boundaries.
- */
-#if defined(PG_INT128_TYPE)
-#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
-#define HAVE_INT128 1
-
-typedef PG_INT128_TYPE int128
-#if defined(pg_attribute_aligned)
-                       pg_attribute_aligned(MAXIMUM_ALIGNOF)
-#endif
-                  ;
-
-typedef unsigned PG_INT128_TYPE uint128
-#if defined(pg_attribute_aligned)
-                       pg_attribute_aligned(MAXIMUM_ALIGNOF)
-#endif
-                  ;
-
-#endif
-#endif
-
 /* Historical names for limits in <stdint.h>. */
 #define PG_INT8_MIN            INT8_MIN
 #define PG_INT8_MAX            INT8_MAX
@@ -802,6 +775,33 @@ typedef NameData *Name;
  */
 #define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
 
+/*
+ * Compute maximum alignment of any basic type.
+ *
+ * We require 'double' to have the strictest alignment among the basic types,
+ * because otherwise the C ABI might impose 8-byte alignment on some of the
+ * other C types that correspond to TYPALIGN_DOUBLE SQL types.  That could
+ * cause a mismatch between the tuple layout and the C struct layout of a
+ * catalog tuple.  We used to carefully order catalog columns such that any
+ * fixed-width, attalign=4 columns were at offsets divisible by 8 regardless
+ * of MAXIMUM_ALIGNOF to avoid that, but we no longer support any platforms
+ * where TYPALIGN_DOUBLE != MAXIMUM_ALIGNOF.
+ *
+ * We assume without checking that the alignments of int64_t and long are at
+ * least as strong as char, short, or int.  Note that we intentionally do not
+ * consider any types wider than 64 bits, as allowing MAXIMUM_ALIGNOF to
+ * exceed 8 would be too much of a penalty for disk and memory space.
+ */
+
+static_assert(ALIGNOF_LONG <= ALIGNOF_DOUBLE,
+                         "alignment of 'long' is greater than the alignment of 
'double'");
+
+static_assert(ALIGNOF_INT64_T <= ALIGNOF_DOUBLE,
+                         "alignment of 'int64_t' is greater than the alignment 
of 'double'");
+
+/* The maximum alignment requirement of any C data type */
+#define MAXIMUM_ALIGNOF ALIGNOF_DOUBLE
+
 /* ----------------
  * Alignment macros: align a length or address appropriately for a given type.
  * The fooALIGN() macros round up to a multiple of the required alignment,
@@ -1102,6 +1102,33 @@ pg_noreturn extern void ExceptionalCondition(const char 
*conditionName,
 #define INVERT_COMPARE_RESULT(var) \
        ((var) = ((var) < 0) ? 1 : -(var))
 
+/*
+ * 128-bit signed and unsigned integers
+ *             There currently is only limited support for such types.
+ *             E.g. 128bit literals and snprintf are not supported; but math 
is.
+ *             Also, because we exclude such types when choosing 
MAXIMUM_ALIGNOF,
+ *             it must be possible to coerce the compiler to allocate them on 
no
+ *             more than MAXALIGN boundaries.
+ */
+#if defined(PG_INT128_TYPE)
+#if defined(pg_attribute_aligned) || ALIGNOF_PG_INT128_TYPE <= MAXIMUM_ALIGNOF
+#define HAVE_INT128 1
+
+typedef PG_INT128_TYPE int128
+#if defined(pg_attribute_aligned)
+                       pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+                  ;
+
+typedef unsigned PG_INT128_TYPE uint128
+#if defined(pg_attribute_aligned)
+                       pg_attribute_aligned(MAXIMUM_ALIGNOF)
+#endif
+                  ;
+
+#endif
+#endif
+
 /*
  * Use this, not "char buf[BLCKSZ]", to declare a field or local variable
  * holding a page buffer, if that page might be accessed as a page.  Otherwise
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 339268dc8ef..b42cf0df5cc 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -547,9 +547,6 @@
 /* Define to 1 if you have __get_cpuid_count. */
 #undef HAVE__GET_CPUID_COUNT
 
-/* Define as the maximum alignment requirement of any C data type. */
-#undef MAXIMUM_ALIGNOF
-
 /* Define bytes to use libc memset(). */
 #undef MEMSET_LOOP_LIMIT
 

base-commit: 7ebb64c557570647e3fcf6f5f1549e882ed26489
-- 
2.52.0

Reply via email to