From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@lists.postgresql.org
Subject: More const-marking cleanup
Date: Thu, 04 Dec 2025 17:09:30 -0500
Message-ID: <1324889.1764886170@sss.pgh.pa.us> (raw)
I noticed that our two buildfarm animals that are running Fedora
rawhide (caiman, midge) are emitting warnings like
compression.c: In function "parse_compress_options":
compression.c:458:13: warning: assignment discards "const" qualifier from pointer target type [-Wdiscarded-qualifiers]
458 | sep = strchr(option, ':');
| ^
Apparently, latest gcc is able to notice that constructions like
const char *str = ...;
char *ptr = strchr(str, ':');
are effectively casting away const. This is a good thing and long
overdue, but we have some work to do to clean up the places where
we are doing that.
Attached is a patch that cleans up all the cases I saw on a local
rawhide installation. Most of it is unremarkable, but the changes
in ecpg are less so. In particular, variable.c is a mess, because
somebody const-ified some of the char* arguments to find_struct()
and find_struct_member() without regard for the fact that all their
char* arguments point at the same string. (Not that you could
discover that from their nonexistent documentation.) I considered
just reverting that change, but was able to fix things up reasonably
well at the price of a few extra strdup's. It turned out that
find_struct_member()'s modification of its input string is actually
entirely useless, because it undoes that before consulting the
string again. find_struct() and find_variable() need to make
copies, though.
regards, tom lane
Attachments:v1-fix-missing-const-markers.patch (text/x-diff, 10.6K) downloaddiff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.cindex 257c7da8568..4a69a81b9fb 100644--- a/src/backend/catalog/pg_type.c+++ b/src/backend/catalog/pg_type.c@@ -948,7 +948,7 @@ char *
makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
{
char *buf;
- char *rangestr;+ const char *rangestr;
/*
* If the range type name contains "range" then change that to
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.cindex 146801885d7..0dab31f0ddb 100644--- a/src/backend/tsearch/spell.c+++ b/src/backend/tsearch/spell.c@@ -2320,7 +2320,7 @@ CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPla
}
else
{
- char *affbegin;+ const char *affbegin;
while ((*ptr)->affix)
{
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.cindex 5bfeda2ffde..c3cb022a400 100644--- a/src/backend/utils/adt/formatting.c+++ b/src/backend/utils/adt/formatting.c@@ -1046,8 +1046,9 @@ typedef struct NUMProc
char *number, /* string with number */
*number_p, /* pointer to current number position */
*inout, /* in / out buffer */
- *inout_p, /* pointer to current inout position */- *last_relevant, /* last relevant number after decimal point */+ *inout_p; /* pointer to current inout position */++ const char *last_relevant, /* last relevant number after decimal point */
*L_negative_sign, /* Locale */
*L_positive_sign,
@@ -1118,7 +1119,7 @@ static FormatNode *NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *
static char *int_to_roman(int number);
static int roman_to_int(NUMProc *Np, size_t input_len);
static void NUM_prepare_locale(NUMProc *Np);
-static char *get_last_relevant_decnum(const char *num);+static const char *get_last_relevant_decnum(const char *num);
static void NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len);
static void NUM_numpart_to_char(NUMProc *Np, int id);
static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
@@ -5297,10 +5298,10 @@ NUM_prepare_locale(NUMProc *Np)
* If there is no decimal point, return NULL (which will result in same
* behavior as if FM hadn't been specified).
*/
-static char *+static const char *
get_last_relevant_decnum(const char *num)
{
- char *result,+ const char *result,
*p = strchr(num, '.');
#ifdef DEBUG_TO_FROM_CHAR
diff --git a/src/backend/utils/adt/xid8funcs.c b/src/backend/utils/adt/xid8funcs.cindex a211a107767..4b3f7a69b3b 100644--- a/src/backend/utils/adt/xid8funcs.c+++ b/src/backend/utils/adt/xid8funcs.c@@ -194,7 +194,7 @@ is_visible_fxid(FullTransactionId value, const pg_snapshot *snap)
#ifdef USE_BSEARCH_IF_NXIP_GREATER
else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
{
- void *res;+ const void *res;
res = bsearch(&value, snap->xip, snap->nxip, sizeof(FullTransactionId),
cmp_fxid);
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.cindex c6d6ba79e44..1c1ccf59f65 100644--- a/src/bin/pg_waldump/pg_waldump.c+++ b/src/bin/pg_waldump/pg_waldump.c@@ -160,7 +160,7 @@ create_fullpage_directory(char *path)
static void
split_path(const char *path, char **dir, char **fname)
{
- char *sep;+ const char *sep;
/* split filepath into directory & filename */
sep = strrchr(path, '/');
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.cindex 68774a59efd..00593fab5e1 100644--- a/src/bin/pgbench/pgbench.c+++ b/src/bin/pgbench/pgbench.c@@ -6254,7 +6254,7 @@ findBuiltin(const char *name)
static int
parseScriptWeight(const char *option, char **script)
{
- char *sep;+ const char *sep;
int weight;
if ((sep = strrchr(option, WSEP)))
diff --git a/src/common/compression.c b/src/common/compression.cindex 4c3c9fd7b50..eb434542fbd 100644--- a/src/common/compression.c+++ b/src/common/compression.c@@ -425,7 +425,7 @@ validate_compress_specification(pg_compress_specification *spec)
void
parse_compress_options(const char *option, char **algorithm, char **detail)
{
- char *sep;+ const char *sep;
char *endp;
long result;
diff --git a/src/interfaces/ecpg/pgtypeslib/datetime.c b/src/interfaces/ecpg/pgtypeslib/datetime.cindex 1b253747fc4..f43343b4594 100644--- a/src/interfaces/ecpg/pgtypeslib/datetime.c+++ b/src/interfaces/ecpg/pgtypeslib/datetime.c@@ -335,8 +335,8 @@ PGTYPESdate_defmt_asc(date * d, const char *fmt, const char *str)
*/
int token[3][2];
int token_values[3] = {-1, -1, -1};
- char *fmt_token_order;- char *fmt_ystart,+ const char *fmt_token_order;+ const char *fmt_ystart,
*fmt_mstart,
*fmt_dstart;
unsigned int i;
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailerindex 6f94b832a03..be94ca5bbfa 100644--- a/src/interfaces/ecpg/preproc/ecpg.trailer+++ b/src/interfaces/ecpg/preproc/ecpg.trailer@@ -1975,12 +1975,14 @@ civarind: cvariable indicator
char_civar: char_variable
{
- char *ptr = strstr(@1, ".arr");+ char *var = mm_strdup(@1);+ char *ptr = strstr(var, ".arr");
if (ptr) /* varchar, we need the struct name here, not
* the struct element */
*ptr = '\0';
- add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator);+ add_variable_to_head(&argsinsert, find_variable(var), &no_indicator);+ @$ = var;
}
;
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.cindex 2c67e33e92e..350e780c000 100644--- a/src/interfaces/ecpg/preproc/variable.c+++ b/src/interfaces/ecpg/preproc/variable.c@@ -6,6 +6,19 @@
static struct variable *allvariables = NULL;
+/* this probably belongs in util.c, but for now it's only needed here */+static char *+mm_nstrdup(const char *in, size_t len)+{+ char *out;++ out = mm_alloc(len + 1);+ memcpy(out, in, len);+ out[len] = '\0';++ return out;+}+
struct variable *
new_variable(const char *name, struct ECPGtype *type, int brace_level)
{
@@ -22,17 +35,11 @@ new_variable(const char *name, struct ECPGtype *type, int brace_level)
}
static struct variable *
-find_struct_member(const char *name, char *str, struct ECPGstruct_member *members, int brace_level)+find_struct_member(const char *name, const char *str,+ struct ECPGstruct_member *members, int brace_level)
{
- char *next = strpbrk(++str, ".-["),- *end,- c = '\0';-- if (next != NULL)- {- c = *next;- *next = '\0';- }+ const char *next = strpbrk(++str, ".-["),+ *end;
for (; members; members = members->next)
{
@@ -54,8 +61,7 @@ find_struct_member(const char *name, char *str, struct ECPGstruct_member *member
}
else
{
- *next = c;- if (c == '[')+ if (*next == '[')
{
int count;
@@ -123,25 +129,24 @@ find_struct_member(const char *name, char *str, struct ECPGstruct_member *member
}
static struct variable *
-find_struct(const char *name, char *next, char *end)+find_struct(const char *name, const char *next, const char *end)
{
+ char *prefix;
struct variable *p;
- char c = *next;
/* first get the mother structure entry */
- *next = '\0';- p = find_variable(name);+ prefix = mm_nstrdup(name, next - name);+ p = find_variable(prefix);- if (c == '-')+ if (*next == '-')
{
if (p->type->type != ECPGt_array)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);- /* restore the name, we will need it later */- *next = c;+ free(prefix);
return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
}
@@ -150,23 +155,21 @@ find_struct(const char *name, char *next, char *end)
if (next == end)
{
if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
- mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", prefix);- /* restore the name, we will need it later */- *next = c;+ free(prefix);
return find_struct_member(name, end, p->type->u.members, p->brace_level);
}
else
{
if (p->type->type != ECPGt_array)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", prefix);
if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);- /* restore the name, we will need it later */- *next = c;+ free(prefix);
return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
}
@@ -192,7 +195,7 @@ find_simple(const char *name)
struct variable *
find_variable(const char *name)
{
- char *next,+ const char *next,
*end;
struct variable *p;
int count;
@@ -227,15 +230,14 @@ find_variable(const char *name)
p = find_struct(name, next, end);
else
{
- char c = *next;+ char *prefix = mm_nstrdup(name, next - name);- *next = '\0';- p = find_simple(name);+ p = find_simple(prefix);
if (p == NULL)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);+ mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", prefix);
if (p->type->type != ECPGt_array)
- mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", name);- *next = c;+ mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);+ free(prefix);
switch (p->type->u.element->type)
{
case ECPGt_array:
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.cindex efc41fca2ba..58d41207605 100644--- a/src/test/regress/pg_regress.c+++ b/src/test/regress/pg_regress.c@@ -693,7 +693,7 @@ static
const char *
get_expectfile(const char *testname, const char *file)
{
- char *file_type;+ const char *file_type;
_resultmap *rm;
/*
diff --git a/src/timezone/zic.c b/src/timezone/zic.cindex a8c1de9910d..8dcc7b337a7 100644--- a/src/timezone/zic.c+++ b/src/timezone/zic.c@@ -2620,7 +2620,7 @@ doabbr(char *abbr, struct zone const *zp, char const *letters,
bool isdst, zic_t save, bool doquotes)
{
char *cp;
- char *slashp;+ char const *slashp;
size_t len;
char const *format = zp->z_format;
=
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: tgl@sss.pgh.pa.us, pgsql-hackers@lists.postgresql.org
Subject: Re: More const-marking cleanup
In-Reply-To: <1324889.1764886170@sss.pgh.pa.us>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox