From: Peter Eisentraut Date: Fri, 21 Nov 2025 08:57:06 +0000 (+0100) Subject: C11 alignas instead of unions X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;p=postgresql.git C11 alignas instead of unions This changes a few union members that only existed to ensure alignments and replaces them with the C11 alignas specifier. This change only uses fundamental alignments (meaning approximately alignments of basic types), which all C11 compilers must support. There are opportunities for similar changes using extended alignments, for example in PGIOAlignedBlock, but these are not necessarily supported by all compilers, so they are kept as a separate change. Reviewed-by: Chao Li Discussion: https://www.postgresql.org/message-id/flat/46f05236-d4d4-4b4e-84d4-faa500f14691%40eisentraut.org --- diff --git a/src/backend/access/common/toast_internals.c b/src/backend/access/common/toast_internals.c index 81dbd67c725..63b848473f8 100644 --- a/src/backend/access/common/toast_internals.c +++ b/src/backend/access/common/toast_internals.c @@ -287,11 +287,9 @@ toast_save_datum(Relation rel, Datum value, bool t_isnull[3] = {0}; union { - struct varlena hdr; + alignas(int32) struct varlena hdr; /* this is to make the union big enough for a chunk: */ char data[TOAST_MAX_CHUNK_SIZE + VARHDRSZ]; - /* ensure union is aligned well enough: */ - int32 align_it; } chunk_data; int32 chunk_size; diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index e1cf659485a..eb86402cae4 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -1987,14 +1987,10 @@ asyncQueueProcessPageEntries(QueuePosition *current, /* * We copy the entries into a local buffer to avoid holding the SLRU lock * while we transmit them to our frontend. The local buffer must be - * adequately aligned, so use a union. + * adequately aligned. */ - union - { - char buf[QUEUE_PAGESIZE]; - AsyncQueueEntry align; - } local_buf; - char *local_buf_end = local_buf.buf; + alignas(AsyncQueueEntry) char local_buf[QUEUE_PAGESIZE]; + char *local_buf_end = local_buf; slotno = SimpleLruReadPage_ReadOnly(NotifyCtl, curpage, InvalidTransactionId); @@ -2082,8 +2078,8 @@ asyncQueueProcessPageEntries(QueuePosition *current, * Now that we have let go of the SLRU bank lock, send the notifications * to our backend */ - Assert(local_buf_end - local_buf.buf <= BLCKSZ); - for (char *p = local_buf.buf; p < local_buf_end;) + Assert(local_buf_end - local_buf <= BLCKSZ); + for (char *p = local_buf; p < local_buf_end;) { AsyncQueueEntry *qe = (AsyncQueueEntry *) p; diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index f6d2f9dba13..2bd872d6581 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -556,11 +556,9 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) bool pfreeit; union { - bytea hdr; + alignas(int32) bytea hdr; /* this is to make the union big enough for a LO data chunk: */ char data[LOBLKSIZE + VARHDRSZ]; - /* ensure union is aligned well enough: */ - int32 align_it; } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; @@ -747,11 +745,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len) Form_pg_largeobject olddata; union { - bytea hdr; + alignas(int32) bytea hdr; /* this is to make the union big enough for a LO data chunk: */ char data[LOBLKSIZE + VARHDRSZ]; - /* ensure union is aligned well enough: */ - int32 align_it; } workbuf = {0}; char *workb = VARDATA(&workbuf.hdr); HeapTuple newtup; diff --git a/src/include/c.h b/src/include/c.h index 8e887bec0b2..729eb8a27de 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -1117,15 +1117,11 @@ pg_noreturn extern void ExceptionalCondition(const char *conditionName, * 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 * the variable might be under-aligned, causing problems on alignment-picky - * hardware. We include both "double" and "int64" in the union to ensure that - * the compiler knows the value must be MAXALIGN'ed (cf. configure's - * computation of MAXIMUM_ALIGNOF). + * hardware. */ -typedef union PGAlignedBlock +typedef struct PGAlignedBlock { - char data[BLCKSZ]; - double force_align_d; - int64 force_align_i64; + alignas(MAXIMUM_ALIGNOF) char data[BLCKSZ]; } PGAlignedBlock; /*