On 18.08.26 11:04, Peter Eisentraut wrote:
The attached patches fix more cases where qualifiers (const, volatile)
are cast away either accidentally, or unnecessarily, or where it can be
worked around easily.
I split these into tiny bits to simplify review and to show that they
are all independent. But they could perhaps be committed all together.
(See also similar commit 3f988629805.)
I have a local WIP branch that fixes all remaining -Wcast-qual warnings.
The attached patches are the "easy" half of that. I plan to propose
addressing the other half separately later.
Here are more patches for this. (I suppose this is half of the
above-mentioned other half.)
The first two patches address the issue that unconstify cannot be used
for global variables. I'm introducing an unconstify_constexpr that can
be used for that but only works for GCC.
The third patch adjusts unconstify, unconstify_constexpr, and unvolatize
so that they don't trigger -Wcast-qual warnings. This will be useful
later when we have fixed all the remaining issues and we can turn on
-Wcast-qual.
Patches 4 through 7 add various unconstify and unvolatize in place of or
in addition to existing casts.
The last patch would then turn on the warning option, but it's only for
illustration right, as there is more (increasingly complicated) stuff to
fix after this.
From 76b8ce879e21fd79173ddf77acbb511d39b00b77 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 1/8] Add unconstify_constexpr
unconstify_constexpr is like unconstify but for contexts where a
constant expression is required, such as for initializing global
variables. It provides the same level of checking as unconstify, but
the checking only works on GCC, otherwise it lets anything through.
Also, if the check fails, it gives a less clear error message. So it
should only be used when necessary.
(An unvolatize_constexpr doesn't seem necessary, but it could be added if
required.)
---
src/include/c.h | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 20cfbac54e7..341076f06ad 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1363,20 +1363,37 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
* design or language restrictions prevent you from declaring that
* (e.g. because a function returns both const and non-const variables).
*
- * Note that this only works in function scope, not for global variables (it'd
- * be nice, but not trivial, to improve that).
+ * unconstify_constexpr is for contexts where a constant expression is
+ * required, such as for initializing global variables. It provides the same
+ * level of checking as unconstify, but the checking only works on GCC,
+ * otherwise it lets anything through. Also, if the check fails, it gives a
+ * less clear error message. So it should only be used when necessary.
+ *
+ * (An unvolatize_constexpr doesn't seem necessary, but it could be added if
+ * required.)
*/
#if defined(__cplusplus)
#define unconstify(underlying_type, expr) const_cast<underlying_type>(expr)
+#define unconstify_constexpr(underlying_type, expr)
const_cast<underlying_type>(expr)
#define unvolatize(underlying_type, expr) const_cast<underlying_type>(expr)
-#else
+#else /* !__cplusplus */
#define unconstify(underlying_type, expr) \
(StaticAssertVariableIsOfTypeMacro(expr, const underlying_type), \
(underlying_type) (expr))
#define unvolatize(underlying_type, expr) \
(StaticAssertVariableIsOfTypeMacro(expr, volatile underlying_type), \
(underlying_type) (expr))
-#endif
+#ifdef __GNUC__
+#define unconstify_constexpr(underlying_type, expr) \
+ __builtin_choose_expr( \
+ _Generic((expr), const underlying_type: 1, default: 0), \
+ (underlying_type) (expr), \
+ (void) 0)
+#else /* !__GNUC_ */
+#define unconstify_constexpr(underlying_type, expr) \
+ ((underlying_type) (expr))
+#endif /* !__GNUC_ */
+#endif /* !__cplusplus */
/*
* SSE2 instructions are part of the spec for the 64-bit x86 ISA. We assume
--
2.55.0
From 3a6dea7ddfcf5cfdba6ae3ff01bf884491e1133c Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 2/8] Use unconstify_constexpr
Add uses of unconstify_constexpr were appropriate.
---
src/backend/tcop/dest.c | 2 +-
src/backend/utils/adt/numeric.c | 12 ++++++------
src/pl/plpython/plpy_cursorobject.c | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c
index bdc3dad3357..4c2b5b87522 100644
--- a/src/backend/tcop/dest.c
+++ b/src/backend/tcop/dest.c
@@ -93,7 +93,7 @@ static const DestReceiver spi_printtupDR = {
* It's ok to cast the constness away as any modification of the none receiver
* would be a bug (which gets easier to catch this way).
*/
-DestReceiver *None_Receiver = (DestReceiver *) &donothingDR;
+DestReceiver *None_Receiver = unconstify_constexpr(DestReceiver *,
&donothingDR);
/* ----------------
* BeginCommand - initialize the destination at start of command
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 37f24e33857..ede77bde485 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -415,18 +415,18 @@ typedef struct NumericSumAccum
*/
static const NumericDigit const_zero_data[1] = {0};
static const NumericVar const_zero =
-{0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
+{0, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *,
const_zero_data)};
static const NumericDigit const_one_data[1] = {1};
static const NumericVar const_one =
-{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
+{1, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *,
const_one_data)};
static const NumericVar const_minus_one =
-{1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
+{1, 0, NUMERIC_NEG, 0, NULL, unconstify_constexpr(NumericDigit *,
const_one_data)};
static const NumericDigit const_two_data[1] = {2};
static const NumericVar const_two =
-{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
+{1, 0, NUMERIC_POS, 0, NULL, unconstify_constexpr(NumericDigit *,
const_two_data)};
#if DEC_DIGITS == 4
static const NumericDigit const_zero_point_nine_data[1] = {9000};
@@ -436,7 +436,7 @@ static const NumericDigit const_zero_point_nine_data[1] =
{90};
static const NumericDigit const_zero_point_nine_data[1] = {9};
#endif
static const NumericVar const_zero_point_nine =
-{1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
+{1, -1, NUMERIC_POS, 1, NULL, unconstify_constexpr(NumericDigit *,
const_zero_point_nine_data)};
#if DEC_DIGITS == 4
static const NumericDigit const_one_point_one_data[2] = {1, 1000};
@@ -446,7 +446,7 @@ static const NumericDigit const_one_point_one_data[2] = {1,
10};
static const NumericDigit const_one_point_one_data[2] = {1, 1};
#endif
static const NumericVar const_one_point_one =
-{2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
+{2, 0, NUMERIC_POS, 1, NULL, unconstify_constexpr(NumericDigit *,
const_one_point_one_data)};
static const NumericVar const_nan =
{0, 0, NUMERIC_NAN, 0, NULL, NULL};
diff --git a/src/pl/plpython/plpy_cursorobject.c
b/src/pl/plpython/plpy_cursorobject.c
index 054dc97db1b..8d29e4725b2 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -39,7 +39,7 @@ static PyType_Slot PLyCursor_slots[] =
Py_tp_dealloc, PLy_cursor_dealloc
},
{
- Py_tp_doc, (char *) PLy_cursor_doc
+ Py_tp_doc, unconstify_constexpr(char *, PLy_cursor_doc)
},
{
Py_tp_iter, PyObject_SelfIter
--
2.55.0
From 59e2476d28fe74b4eed242c7b6e4a5492c07a64b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 3/8] Adjust unconstify/unvolatize to avoid -Wcast-qual
warnings
An intermediate cast to uintptr_t avoids the warning. That way, we
could turn on -Wcast-qual, and all unconstify() and unvolatize() uses
would pass but bare casts that discard qualifiers would raise
warnings.
---
src/include/c.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/include/c.h b/src/include/c.h
index 341076f06ad..2efdd75cafa 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1379,19 +1379,19 @@ typedef struct PGAlignedXLogBlock PGAlignedXLogBlock;
#else /* !__cplusplus */
#define unconstify(underlying_type, expr) \
(StaticAssertVariableIsOfTypeMacro(expr, const underlying_type), \
- (underlying_type) (expr))
+ (underlying_type) (uintptr_t) (expr))
#define unvolatize(underlying_type, expr) \
(StaticAssertVariableIsOfTypeMacro(expr, volatile underlying_type), \
- (underlying_type) (expr))
+ (underlying_type) (uintptr_t) (expr))
#ifdef __GNUC__
#define unconstify_constexpr(underlying_type, expr) \
__builtin_choose_expr( \
_Generic((expr), const underlying_type: 1, default: 0), \
- (underlying_type) (expr), \
+ (underlying_type) (uintptr_t) (expr), \
(void) 0)
#else /* !__GNUC_ */
#define unconstify_constexpr(underlying_type, expr) \
- ((underlying_type) (expr))
+ ((underlying_type) (uintptr_t) (expr))
#endif /* !__GNUC_ */
#endif /* !__cplusplus */
--
2.55.0
From dec63526aa152329f5649d509a72aa1975170868 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 4/8] Fix -Wcast-qual warnings with external APIs
These casts were there only drop a qualifier to satisfy some external
API. Convert them to unconstify to make the purpose clear.
---
src/backend/libpq/be-secure-gssapi.c | 2 +-
src/backend/libpq/be-secure-openssl.c | 2 +-
src/backend/port/win32/socket.c | 2 +-
src/bin/psql/tab-complete.in.c | 2 +-
src/interfaces/libpq/fe-secure-gssapi.c | 2 +-
src/interfaces/libpq/fe-secure-openssl.c | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/backend/libpq/be-secure-gssapi.c
b/src/backend/libpq/be-secure-gssapi.c
index 540ed62a5cc..eb841cb0c96 100644
--- a/src/backend/libpq/be-secure-gssapi.c
+++ b/src/backend/libpq/be-secure-gssapi.c
@@ -195,7 +195,7 @@ be_gssapi_write(Port *port, const void *ptr, size_t len)
else
input.length = bytes_to_encrypt;
- input.value = (char *) ptr + bytes_encrypted;
+ input.value = unconstify(char *, (const char *) ptr +
bytes_encrypted);
output.value = NULL;
output.length = 0;
diff --git a/src/backend/libpq/be-secure-openssl.c
b/src/backend/libpq/be-secure-openssl.c
index b7ded8a0250..bf403142fd4 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -1804,7 +1804,7 @@ alpn_cb(SSL *ssl,
Assert(outlen != NULL);
Assert(in != NULL);
- retval = SSL_select_next_proto((unsigned char **) out, outlen,
+ retval = SSL_select_next_proto(unconstify(unsigned char **, out),
outlen,
alpn_protos,
sizeof(alpn_protos),
in, inlen);
if (*out == NULL || *outlen > sizeof(alpn_protos) || *outlen <= 0)
diff --git a/src/backend/port/win32/socket.c b/src/backend/port/win32/socket.c
index e16fd85ddd4..092d41e3f63 100644
--- a/src/backend/port/win32/socket.c
+++ b/src/backend/port/win32/socket.c
@@ -466,7 +466,7 @@ pgwin32_send(SOCKET s, const void *buf, int len, int flags)
return -1;
wbuf.len = len;
- wbuf.buf = (char *) buf;
+ wbuf.buf = unconstify(void *, buf);
/*
* Readiness of socket to send data to UDP socket may be not true:
socket
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index e27a3e2208a..f4c06bed666 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1514,7 +1514,7 @@ static char *dequote_file_name(char *fname, int
quote_char);
void
initialize_readline(void)
{
- rl_readline_name = (char *) pset.progname;
+ rl_readline_name = unconstify(char *, pset.progname);
rl_attempted_completion_function = psql_completion;
#ifdef USE_FILENAME_QUOTING_FUNCTIONS
diff --git a/src/interfaces/libpq/fe-secure-gssapi.c
b/src/interfaces/libpq/fe-secure-gssapi.c
index cc60240582d..5ae10af5678 100644
--- a/src/interfaces/libpq/fe-secure-gssapi.c
+++ b/src/interfaces/libpq/fe-secure-gssapi.c
@@ -185,7 +185,7 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
else
input.length = bytes_to_encrypt;
- input.value = (char *) ptr + bytes_encrypted;
+ input.value = unconstify(char *, (const char *) ptr) +
bytes_encrypted;
output.value = NULL;
output.length = 0;
diff --git a/src/interfaces/libpq/fe-secure-openssl.c
b/src/interfaces/libpq/fe-secure-openssl.c
index 8895a17ff8a..243ed240087 100644
--- a/src/interfaces/libpq/fe-secure-openssl.c
+++ b/src/interfaces/libpq/fe-secure-openssl.c
@@ -1153,7 +1153,7 @@ initialize_SSL(PGconn *conn)
!(strspn(host, "0123456789.") == strlen(host) ||
strchr(host, ':')))
{
- if (SSL_set_tlsext_host_name(conn->ssl, host) != 1)
+ if (SSL_set_tlsext_host_name(conn->ssl, unconstify(char
*, host)) != 1)
{
char *errm =
SSLerrmessage(ERR_get_error());
--
2.55.0
From d5384f9e391a10177fd7bf06c866e62834f52896 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 5/8] Change float{4,8}in_internal take const char * input
argument
This makes the function signature match strtof()/strtod().
A caller then doesn't have to cast away a const anymore.
---
contrib/postgres_fdw/postgres_fdw.c | 2 +-
src/backend/utils/adt/float.c | 32 ++++++++++++++---------------
src/include/utils/float.h | 4 ++--
3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/contrib/postgres_fdw/postgres_fdw.c
b/contrib/postgres_fdw/postgres_fdw.c
index eceee1b649d..ec291d95fdc 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -6458,7 +6458,7 @@ set_float_arg(NullableDatum *arg, const char *s)
{
if (s)
{
- float4 val = float4in_internal((char *) s, NULL,
"float", s, NULL);
+ float4 val = float4in_internal(s, NULL, "float", s,
NULL);
arg->value = Float4GetDatum(val);
arg->isnull = false;
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index fd7a6587132..18b43c81d74 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -221,7 +221,7 @@ float4in(PG_FUNCTION_ARGS)
* comments also apply here, except regarding use in geometric types.
*/
float4
-float4in_internal(char *num, char **endptr_p,
+float4in_internal(const char *num, char **endptr_p,
const char *type_name, const char
*orig_string,
struct Node *escontext)
{
@@ -269,37 +269,37 @@ float4in_internal(char *num, char **endptr_p,
if (pg_strncasecmp(num, "NaN", 3) == 0)
{
val = get_float4_nan();
- endptr = num + 3;
+ endptr = unconstify(char *, num) + 3;
}
else if (pg_strncasecmp(num, "Infinity", 8) == 0)
{
val = get_float4_infinity();
- endptr = num + 8;
+ endptr = unconstify(char *, num) + 8;
}
else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
{
val = get_float4_infinity();
- endptr = num + 9;
+ endptr = unconstify(char *, num) + 9;
}
else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
{
val = -get_float4_infinity();
- endptr = num + 9;
+ endptr = unconstify(char *, num) + 9;
}
else if (pg_strncasecmp(num, "inf", 3) == 0)
{
val = get_float4_infinity();
- endptr = num + 3;
+ endptr = unconstify(char *, num) + 3;
}
else if (pg_strncasecmp(num, "+inf", 4) == 0)
{
val = get_float4_infinity();
- endptr = num + 4;
+ endptr = unconstify(char *, num) + 4;
}
else if (pg_strncasecmp(num, "-inf", 4) == 0)
{
val = -get_float4_infinity();
- endptr = num + 4;
+ endptr = unconstify(char *, num) + 4;
}
else if (save_errno == ERANGE)
{
@@ -433,7 +433,7 @@ float8in(PG_FUNCTION_ARGS)
* unreasonable amount of extra casting both here and in callers, so we don't.
*/
float8
-float8in_internal(char *num, char **endptr_p,
+float8in_internal(const char *num, char **endptr_p,
const char *type_name, const char
*orig_string,
struct Node *escontext)
{
@@ -475,37 +475,37 @@ float8in_internal(char *num, char **endptr_p,
if (pg_strncasecmp(num, "NaN", 3) == 0)
{
val = get_float8_nan();
- endptr = num + 3;
+ endptr = unconstify(char *, num) + 3;
}
else if (pg_strncasecmp(num, "Infinity", 8) == 0)
{
val = get_float8_infinity();
- endptr = num + 8;
+ endptr = unconstify(char *, num) + 8;
}
else if (pg_strncasecmp(num, "+Infinity", 9) == 0)
{
val = get_float8_infinity();
- endptr = num + 9;
+ endptr = unconstify(char *, num) + 9;
}
else if (pg_strncasecmp(num, "-Infinity", 9) == 0)
{
val = -get_float8_infinity();
- endptr = num + 9;
+ endptr = unconstify(char *, num) + 9;
}
else if (pg_strncasecmp(num, "inf", 3) == 0)
{
val = get_float8_infinity();
- endptr = num + 3;
+ endptr = unconstify(char *, num) + 3;
}
else if (pg_strncasecmp(num, "+inf", 4) == 0)
{
val = get_float8_infinity();
- endptr = num + 4;
+ endptr = unconstify(char *, num) + 4;
}
else if (pg_strncasecmp(num, "-inf", 4) == 0)
{
val = -get_float8_infinity();
- endptr = num + 4;
+ endptr = unconstify(char *, num) + 4;
}
else if (save_errno == ERANGE)
{
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index ffa743d6273..dbfbb3bf6ad 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -37,10 +37,10 @@ extern float8 float_overflow_error_ext(struct Node
*escontext);
extern float8 float_underflow_error_ext(struct Node *escontext);
extern float8 float_zero_divide_error_ext(struct Node *escontext);
extern int is_infinite(float8 val);
-extern float8 float8in_internal(char *num, char **endptr_p,
+extern float8 float8in_internal(const char *num, char **endptr_p,
const char
*type_name, const char *orig_string,
struct Node
*escontext);
-extern float4 float4in_internal(char *num, char **endptr_p,
+extern float4 float4in_internal(const char *num, char **endptr_p,
const char
*type_name, const char *orig_string,
struct Node
*escontext);
extern char *float8out_internal(float8 num);
--
2.55.0
From cc2a7ff6444a68ecfcb51d7c9e2841609fb182f5 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 6/8] Convert some casts to unconstify
These casts existed only to cast away a const qualifier. Convert them
to unconstify to make that more explicit.
---
src/backend/executor/execExpr.c | 2 +-
src/backend/replication/slot.c | 2 +-
src/backend/storage/ipc/shmem.c | 2 +-
src/backend/storage/smgr/md.c | 2 +-
src/backend/utils/mb/mbutils.c | 4 ++--
src/port/bsearch_arg.c | 2 +-
src/port/path.c | 2 +-
7 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 82e846a1f4f..3f063b79f4d 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -4312,7 +4312,7 @@ ExecBuildHash32Expr(TupleDesc desc, const
TupleTableSlotOps *ops,
state->parent = parent;
/* Insert setup steps as needed. */
- ExecCreateExprSetupSteps(state, (Node *) hash_exprs);
+ ExecCreateExprSetupSteps(state, unconstify(Node *, (const Node *)
hash_exprs));
/*
* Make a place to store intermediate hash values between subsequent
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 63ce6d27885..f2d416487fa 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -420,7 +420,7 @@ ReplicationSlotCreate(const char *name, bool db_specific,
errmsg("cannot enable failover for a
temporary replication slot"));
}
- INJECTION_POINT("replication-slot-create-begin", (char *) name);
+ INJECTION_POINT("replication-slot-create-begin", unconstify(char *,
name));
/*
* If some other backend ran this code concurrently with us, we'd likely
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index f971ee24192..51c892bf8e1 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -935,7 +935,7 @@ RegisterShmemCallbacks(const ShmemCallbacks *callbacks)
{
/* Remember the callbacks for later */
registered_shmem_callbacks = lappend(registered_shmem_callbacks,
-
(void *) callbacks);
+
unconstify(ShmemCallbacks *, callbacks));
}
else
elog(ERROR, "cannot request shared memory at this time");
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 780c88c0630..4c777757757 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1101,7 +1101,7 @@ mdwritev(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum,
if (nblocks_this_segment != nblocks)
elog(ERROR, "write crosses segment boundary");
- iovcnt = buffers_to_iovec(iov, (void **) buffers,
nblocks_this_segment);
+ iovcnt = buffers_to_iovec(iov, unconstify(void **, buffers),
nblocks_this_segment);
size_this_segment = nblocks_this_segment * BLCKSZ;
transferred_this_segment = 0;
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index e4f29c2b1c9..b57dba4ead1 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -1945,7 +1945,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int
*utf16len)
*/
if (IsTransactionState())
{
- utf8 = (char *) pg_do_encoding_conversion((unsigned
char *) str,
+ utf8 = (char *) pg_do_encoding_conversion((unsigned
char *) unconstify(char *, str),
len,
msgenc,
PG_UTF8);
@@ -1953,7 +1953,7 @@ pgwin32_message_to_UTF16(const char *str, int len, int
*utf16len)
len = strlen(utf8);
}
else
- utf8 = (char *) str;
+ utf8 = unconstify(char *, str);
utf16 = palloc_array(WCHAR, len + 1);
dstlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, utf16, len);
diff --git a/src/port/bsearch_arg.c b/src/port/bsearch_arg.c
index bc2db8239cd..3739225e755 100644
--- a/src/port/bsearch_arg.c
+++ b/src/port/bsearch_arg.c
@@ -67,7 +67,7 @@ bsearch_arg(const void *key, const void *base0,
p = base + (lim >> 1) * size;
cmp = (*compar) (key, p, arg);
if (cmp == 0)
- return (void *) p;
+ return unconstify(void *, p);
if (cmp > 0)
{ /* key > p:
move right */
base = (const char *) p + size;
diff --git a/src/port/path.c b/src/port/path.c
index fef0ae77f87..75017c5185b 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -78,7 +78,7 @@ skip_drive(const char *path)
{
path += 2;
}
- return (char *) path;
+ return unconstify(char *, path);
}
#else
--
2.55.0
From bb7d887646ec7f1a83d1a5f9e370861a82c86ff8 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 7/8] Additional unvolatize uses
Add some uses of unvolatize to silence warnings that would be
triggered by -Wcast-qual.
Note that the MemSet() calls would be normal "discards qualifier"
warnings if memset() (or another function with a prototype, not a
macro) were used.
---
src/backend/storage/ipc/pmsignal.c | 2 +-
src/backend/storage/ipc/procsignal.c | 4 ++--
src/backend/utils/activity/backend_progress.c | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/backend/storage/ipc/pmsignal.c
b/src/backend/storage/ipc/pmsignal.c
index bdad5fdd043..911dde32fa9 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -145,7 +145,7 @@ PMSignalShmemRequest(void *arg)
mul_size(num_child_flags,
sizeof(sig_atomic_t)));
ShmemRequestStruct(.name = "PMSignalState",
.size = size,
- .ptr = (void **) &PMSignalState,
+ .ptr = (void **)
unvolatize(PMSignalData **, &PMSignalState),
);
}
diff --git a/src/backend/storage/ipc/procsignal.c
b/src/backend/storage/ipc/procsignal.c
index 21a77f98c1d..ea1355df8ee 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -155,7 +155,7 @@ ProcSignalShmemInit(void *arg)
SpinLockInit(&slot->pss_mutex);
pg_atomic_init_u32(&slot->pss_pid, 0);
slot->pss_cancel_key_len = 0;
- MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
+ MemSet(unvolatize(sig_atomic_t *, slot->pss_signalFlags), 0,
sizeof(slot->pss_signalFlags));
pg_atomic_init_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX);
pg_atomic_init_u32(&slot->pss_barrierCheckMask, 0);
ConditionVariableInit(&slot->pss_barrierCV);
@@ -186,7 +186,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
old_pss_pid = pg_atomic_read_u32(&slot->pss_pid);
/* Clear out any leftover signal reasons */
- MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS *
sizeof(sig_atomic_t));
+ MemSet(unvolatize(sig_atomic_t *, slot->pss_signalFlags), 0,
NUM_PROCSIGNALS * sizeof(sig_atomic_t));
/*
* Publish the PID before reading the global barrier generation to
ensure
diff --git a/src/backend/utils/activity/backend_progress.c
b/src/backend/utils/activity/backend_progress.c
index dee05b1abb1..a1c39b7fb15 100644
--- a/src/backend/utils/activity/backend_progress.c
+++ b/src/backend/utils/activity/backend_progress.c
@@ -35,7 +35,7 @@ pgstat_progress_start_command(ProgressCommandType cmdtype,
Oid relid)
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
beentry->st_progress_command = cmdtype;
beentry->st_progress_command_target = relid;
- MemSet(&beentry->st_progress_param, 0,
sizeof(beentry->st_progress_param));
+ MemSet(&unvolatize(PgBackendStatus *, beentry)->st_progress_param, 0,
sizeof(beentry->st_progress_param));
PGSTAT_END_WRITE_ACTIVITY(beentry);
}
--
2.55.0
From 44f414be6af1d7519d5543a5c25bff8ea7140cde Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Tue, 15 Sep 2026 08:43:09 +0200
Subject: [PATCH v2 8/8] WIP: Add warning option -Wcast-qual
---
configure | 4 ++--
configure.ac | 4 ++--
meson.build | 1 +
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/configure b/configure
index d42a7a794ff..a2bdc4a2a53 100755
--- a/configure
+++ b/configure
@@ -5249,8 +5249,8 @@ fi
# but has its own. Also check other compiler-specific flags here.
if test "$GCC" = yes -a "$ICC" = no; then
- CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
- CXXFLAGS="-Wall -Wpointer-arith"
+ CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith -Wcast-qual"
+ CXXFLAGS="-Wall -Wpointer-arith -Wcast-qual"
# These work in some but not all gcc versions
save_CFLAGS=$CFLAGS
diff --git a/configure.ac b/configure.ac
index a331749fcb5..e2c2876675e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -535,8 +535,8 @@ fi
# but has its own. Also check other compiler-specific flags here.
if test "$GCC" = yes -a "$ICC" = no; then
- CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith"
- CXXFLAGS="-Wall -Wpointer-arith"
+ CFLAGS="-Wall -Wmissing-prototypes -Wpointer-arith -Wcast-qual"
+ CXXFLAGS="-Wall -Wpointer-arith -Wcast-qual"
# These work in some but not all gcc versions
save_CFLAGS=$CFLAGS
PGAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement])
diff --git a/meson.build b/meson.build
index f4cde249242..2c1fd41a3c5 100644
--- a/meson.build
+++ b/meson.build
@@ -2203,6 +2203,7 @@ unroll_loops_cflags =
cc.get_supported_arguments(['-funroll-loops'])
common_warning_flags = [
'-Wpointer-arith',
+ '-Wcast-qual',
# Really don't want VLAs to be used in our dialect of C
'-Werror=vla',
# On macOS, complain about usage of symbols newer than the deployment target
--
2.55.0