pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
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) download diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 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.c index 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.c index 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.c index 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.c index 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.c index 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.c index 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.c index 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.trailer index 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.c index 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.c index 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.c index 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; =

view thread (11+ messages)  latest in thread

Message-ID: <1324889.1764886170@sss.pgh.pa.us>
Permalink:  ../1324889.1764886170@sss.pgh.pa.us/
Also on:    postgresql.org/message-id/1324889.1764886170@sss.pgh.pa.us

 ·  · 

reply

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