From 1eac365ea644f3374c6e7ea5ccb46abceb47e80e Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 3 Nov 2026 15:39:36 +0100 Subject: [PATCH 08/10] Fix -Wcast-qual warnings in read/write accessor macros Some macros compute pointers into structs and are used for both reading and writing that struct. For example, ARR_DIMS() can be used for both reading: if (ARR_DIMS(arr)[0] != mcv_length) and writing: ARR_DIMS(r)[0] = num; This makes it difficult to qualify the internal casts of those macros: If we const-qualify the casts, then the writing case will complain about writing through a const pointer. If we don't qualify the casts, then read uses of the macro on a const object will complain with -Wcast-qual. To make this work under -Wcast-qual for now, we const-qualify the casts and then remove the qualifier with unconstify(). Note that this doesn't add or remove any const-safety. Alternative solutions are writing separate write macros (e.g., ARR_SET_DIMS()) or writing type-generic macros (with _Generic, but that would need a separate C++ solution for exported interfaces). This could be future work. --- contrib/ltree/ltree.h | 4 ++-- src/backend/utils/adt/multirangetypes.c | 6 +++--- src/include/tsearch/ts_type.h | 2 +- src/include/utils/array.h | 8 ++++---- src/include/utils/varbit.h | 2 +- src/include/varatt.h | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h index 89c5b932292..0b45bf04c63 100644 --- a/contrib/ltree/ltree.h +++ b/contrib/ltree/ltree.h @@ -48,7 +48,7 @@ typedef struct } ltree; #define LTREE_HDRSIZE MAXALIGN( offsetof(ltree, data) ) -#define LTREE_FIRST(x) ( (ltree_level*)( ((char*)(x))+LTREE_HDRSIZE ) ) +#define LTREE_FIRST(x) ( (ltree_level*)( unconstify(char *, (const char*)(x))+LTREE_HDRSIZE ) ) #define LTREE_MAX_LEVELS PG_UINT16_MAX /* ltree.numlevel is uint16 */ @@ -121,7 +121,7 @@ typedef struct } lquery; #define LQUERY_HDRSIZE MAXALIGN( offsetof(lquery, data) ) -#define LQUERY_FIRST(x) ( (lquery_level*)( ((char*)(x))+LQUERY_HDRSIZE ) ) +#define LQUERY_FIRST(x) ( (lquery_level*)( unconstify(char *, (const char*)(x))+LQUERY_HDRSIZE ) ) #define LQUERY_MAX_LEVELS PG_UINT16_MAX /* lquery.numlevel is uint16 */ #define LQUERY_HASNOT 0x01 diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c index 14a71fe534f..40f9b55abb9 100644 --- a/src/backend/utils/adt/multirangetypes.c +++ b/src/backend/utils/adt/multirangetypes.c @@ -68,11 +68,11 @@ typedef enum * Macros for accessing past MultirangeType parts of multirange: items, flags * and boundaries. */ -#define MultirangeGetItemsPtr(mr) ((uint32 *) ((char *) (mr) + \ +#define MultirangeGetItemsPtr(mr) ((uint32 *) (unconstify(char *, (const char *) (mr)) + \ sizeof(MultirangeType))) -#define MultirangeGetFlagsPtr(mr) ((uint8 *) ((char *) (mr) + \ +#define MultirangeGetFlagsPtr(mr) ((uint8 *) (unconstify(char *, (const char *) (mr)) + \ sizeof(MultirangeType) + ((mr)->rangeCount - 1) * sizeof(uint32))) -#define MultirangeGetBoundariesPtr(mr, align) ((char *) (mr) + \ +#define MultirangeGetBoundariesPtr(mr, align) (unconstify(char *, (const char *) (mr)) + \ att_align_nominal(sizeof(MultirangeType) + \ ((mr)->rangeCount - 1) * sizeof(uint32) + \ (mr)->rangeCount * sizeof(uint8), (align))) diff --git a/src/include/tsearch/ts_type.h b/src/include/tsearch/ts_type.h index 345a2dab930..9002e43b12b 100644 --- a/src/include/tsearch/ts_type.h +++ b/src/include/tsearch/ts_type.h @@ -117,7 +117,7 @@ typedef TSVectorData *TSVector; #define ARRPTR(tsv) ( (tsv)->entries ) /* pointer to start of a tsvector's lexeme storage */ -#define STRPTR(tsv) ( (char *) &(tsv)->entries[(tsv)->size] ) +#define STRPTR(tsv) ( unconstify(char *, (const char *) &(tsv)->entries[(tsv)->size]) ) /* pointer to WordEntryPosVector for a WordEntry */ #define _POSVECPTR(tsv,we) ((WordEntryPosVector *) \ diff --git a/src/include/utils/array.h b/src/include/utils/array.h index e7ee184034e..45040bba72d 100644 --- a/src/include/utils/array.h +++ b/src/include/utils/array.h @@ -292,14 +292,14 @@ typedef struct ArrayIteratorData *ArrayIterator; #define ARR_ELEMTYPE(a) ((a)->elemtype) #define ARR_DIMS(a) \ - ((int *) (((char *) (a)) + sizeof(ArrayType))) + ((int *) ((unconstify(char *, (const char *) (a))) + sizeof(ArrayType))) #define ARR_LBOUND(a) \ - ((int *) (((char *) (a)) + sizeof(ArrayType) + \ + ((int *) ((unconstify(char *, (const char *) (a))) + sizeof(ArrayType) + \ sizeof(int) * ARR_NDIM(a))) #define ARR_NULLBITMAP(a) \ (ARR_HASNULL(a) ? \ - (uint8 *) (((char *) (a)) + sizeof(ArrayType) + \ + (uint8 *) ((unconstify(char *, (const char *) (a))) + sizeof(ArrayType) + \ 2 * sizeof(int) * ARR_NDIM(a)) \ : (uint8 *) NULL) @@ -320,7 +320,7 @@ typedef struct ArrayIteratorData *ArrayIterator; * Returns a pointer to the actual array data. */ #define ARR_DATA_PTR(a) \ - (((char *) (a)) + ARR_DATA_OFFSET(a)) + ((unconstify(char *, (const char *) (a))) + ARR_DATA_OFFSET(a)) /* * Macros for working with AnyArrayType inputs. Beware multiple references! diff --git a/src/include/utils/varbit.h b/src/include/utils/varbit.h index 8e2b981e1f6..f9f848ff969 100644 --- a/src/include/utils/varbit.h +++ b/src/include/utils/varbit.h @@ -68,7 +68,7 @@ VarBitPGetDatum(const VarBit *X) /* Number of bits in this bit string */ #define VARBITLEN(PTR) (((VarBit *) (PTR))->bit_len) /* Pointer to the first byte containing bit string data */ -#define VARBITS(PTR) (((VarBit *) (PTR))->bit_dat) +#define VARBITS(PTR) ((unconstify(VarBit *, (const VarBit *) (PTR)))->bit_dat) /* Number of bytes in the data section of a bit string */ #define VARBITBYTES(PTR) (VARSIZE(PTR) - VARHDRSZ - VARBITHDRSZ) /* Padding of the bit string at the end (in bits) */ diff --git a/src/include/varatt.h b/src/include/varatt.h index 7951a946a87..f288ce30414 100644 --- a/src/include/varatt.h +++ b/src/include/varatt.h @@ -304,10 +304,10 @@ typedef struct #endif /* WORDS_BIGENDIAN */ -#define VARDATA_4B(PTR) (((varattrib_4b *) (PTR))->va_4byte.va_data) -#define VARDATA_4B_C(PTR) (((varattrib_4b *) (PTR))->va_compressed.va_data) -#define VARDATA_1B(PTR) (((varattrib_1b *) (PTR))->va_data) -#define VARDATA_1B_E(PTR) (((varattrib_1b_e *) (PTR))->va_data) +#define VARDATA_4B(PTR) (unconstify(varattrib_4b *, (const varattrib_4b *) (PTR))->va_4byte.va_data) +#define VARDATA_4B_C(PTR) (unconstify(varattrib_4b *, (const varattrib_4b *) (PTR))->va_compressed.va_data) +#define VARDATA_1B(PTR) (unconstify(varattrib_1b *, (const varattrib_1b *) (PTR))->va_data) +#define VARDATA_1B_E(PTR) (unconstify(varattrib_1b_e *, (const varattrib_1b_e *) (PTR))->va_data) /* * Externally visible TOAST functions and macros begin here. All of these -- 2.56.0