On Tue, Mar 3, 2026 at 4:35 PM Branko Čibej <[email protected]> wrote:
> On 3. 3. 26 14:53, Evgeny Kotkov wrote: > > Branko Čibej <[email protected]> <[email protected]> writes: > > > There is something fishy going on here. For example, this is the prototype > for strstr: > > char *strstr(const char*, const char*); > > The relevant change here could be the C23 proposal "N3020 - Qualifier- > preserving Standard Functions", which updated these functions to preserve > const qualifiers [1, 2]: > > QChar *strstr (QChar *s1, const char *s2); > > [where QChar stands for "qualified char"] > > The prototype `char *strstr (const char*, …)` seems to have been a workaround > for the lack of function overloading in C. But the downside is that it does > not preserve constness and effectively works like an implicit const_cast. > > > Yes, indeed, but we should be using -std=c90 in our build, and the C90 > stdlib doesn't have those new prototypes. Does the CMake build set the C > standard parameters? > > + char *p = NULL; > char *ep = NULL; > int sd; > > This makes no sense. Not only is 'p' already const, nothing is being > modified through '*p' but something _is_ being modified through '*ep'. > > I think the underlying question here and in similar cases is how the non-const > `char* ep` was obtained from `const char *p` in the first place. > > In trunk, the const qualifier seems to be silently stripped away when passing > the pointer to functions like strstr() or strchr(): > > ep = strchr(p, '\n'); > > Type-wise, this is equivalent to: > > ep = (char*)p; > > and it's problematic, because it discards the const from the original pointer. > > > Right. This is what we old-timer C programmers call a "horrible hack but > it works" :) > > To some extent, I would say that using `const char *` is even misleading if > it's the only pointer available, as it obscures the fact that the data > eventually get modified without any explicit typecasts: > > const char *keyword = APR_ARRAY_IDX(keyword_tokens, i, const char *); > /* The only pointer we had originally was const. */ > > if (expand_custom_keywords) > { > char *sep; > > sep = strchr(keyword, '='); > if (sep) > { > *sep = '\0'; /* But then the data is modified here > without typecasts */ > > > This is how the C standard library (used to) work ... a compromise. It's > confusing and misleading and causes way too many bugs and is often abused > for precisely this reason, to avoid explicit casts. That's one of the > reasons why we force -std=c90. > > -- Brane > > In fact, this warning also occurs with an explicit --std=c90. The QChar thing is just a nice way to ensure that there are no implicit const_casts from functions like strchr. This might reveal real issues just like when a 'const char *' is explicitly casted into a 'char *'. If an argument is given to a function and marked as const, it assumes that the function does not change it. By the way, it is true that CMake does not properly set up the C standard. -- Timofei Zhakov

