Re: A: a new bug to old plain C

Александр Поваляев via Gcc <[email protected]>
Newsgroups gmane.comp.gcc.devel,gmane.comp.gcc.help
Message-ID <CAGT+J5w-hjACrc6-pyzciyExmFJQkHdbb7Gbxr8g5zeZkDkDcg@mail.gmail.com>
Hi there!

Your example is irrelevant. We're discussing "Foo**"->"const Foo * const *
const" conversion (all-consts).
And your example is about "const Foo*const*", see void foo(const int *const
*p) {}.
Below is the right example (I already posted it, so once again):
"
void subfunc(struct zzz const * const * const arg) {

if (arg != NULL) {
printf("%s", "Done!");
}
}

void func(struct zzz ** arr_of_ptr, unsigned count) {

subfunc((struct zzz const * const * const)arr_of_ptr); // ОК!

*subfunc(arr_of_ptr);* // CLANG: x86-64 clang (trunk) - WARNING!!!
// GCC: x86-64 gcc (trunk) - ERROR!!!
// INTEL: x86-64 icc 2021.10.0 - OK!!!
// MICROSOFT(c++?): x64 msvc v19.latest - OK!!!
// POWER64 GCC trunk - ERROR!!!
// ARM gcc(trunk) - ERROR!!!
// NOTE: based on godbolt.org
}".
And here in green the results of different compilers are shown.
Introducing ''-pedantic-errors'' compilation parameters makes a difference
for CLANG (x86-65 clang (trunk)) compiler - it starts reporting an error
instead of warning.

Meanwhile GCC (x86-64 gcc (trunk)) works fine (without a warning) for both
      "Foo**" -> "Foo** const" conversion and
for  "Foo**" -> "Foo* const * const" conversion.
But it shows an error with "Foo**"  -> "Foo const * const * const".

The conversion "Foo**" -> "Foo const * const * const" is not explicitly
prohibited by C standard and yes, it has been known for a long time. Has
been known as a "safe conversion" :)
"Safe conversion" which has quite useful use-cases.
And I think array of pointers and const-INVARIANTS are two quite widely
used "patterns".

It might be a subject to warning, but it is not an error. Because it
implies no erroneous behaviour, clear and well understandable.
I think tomorrow GCC might silently start reporting such conversion as just
a warning, or even without a warning at all.
And I think nobody will be arguing against it.
So, let's make these useful changes to GCC (I personally consider this as a
bug) earlier.

Respectfully,
Aleksandr G Povaliaev.

пт, 28 нояб. 2025 г. в 23:14, Andrey Tarasevich <[email protected]>:

> I'm not sure how you managed to obtain that "makes only difference to
> CLANG" result in your experiments. A simple code sample
>
>   void foo(const int *const *p) {}
>   int main(void) {
>     int **p = 0;
>     foo(p);
>   }
>
> immediately demonstrates that GCC and Clang in '-pedantic-errors'
> mode both issue an "error" message for this code (and abort
> compilation).
> Both compilers behave identically in this regard. This
> applies to
> your original code as well.
>
> Now, the portions of C language standard that make it a hard error are:
>
> * List of constraints for "Simple assignment"
>
>   https://port70.net/~nsz/c/c11/n1570.html#6.5.16.1p1
>
>   (which also apply to initialization), and
>
> * "Type qualifiers" section, which explains how qualifiers affect type
>   compatibility
>
>   https://port70.net/~nsz/c/c11/n1570.html#6.7.3p10
>
> (The above links refer to an older version of the document, but it is
> good enough for our purposes).
>
> The former states that you can only assign to each other pointers to
> "qualified or unqualified versions of _compatible_ types". The latter says
> that in order for two types to be compatible wrt qualifiers, both types
> have to be _identically_ qualified.
>
> That "qualified or unqualified versions" part is what permits you to
> convert
> 'T *' to 'const T *', i.e. there's some freedom wrt qualifiers at the very
> first level of indirection. But there's no such freedom at deeper levels
> of indirection: all qualifiers at the deeper levels have to be absolutely
> positively 100% identical. Otherwise, the constraint is violated,
> which is a hard error.
>
> I'm not sure what specific "C FAQ" you are referring to here, but it is
> besides the point anyway. FAQs are not normative. Language standard is.
>
> Finally, there's no room for "little bit early" of any kind here. The
> issue in question is well-known and already researched to death. It is
> anscient, meaning that "early" is not really an appropriare word here.
>
> And it is really not a debate. When I posted my original answer, the
> matter has been closed. All we are doing at this point
> is trying to
> help you understand this issue, which has obviously proven to be a bit
> surprising
> to you.
>
> --
> Best regards,
> Andrey
>
> P.S. Yes, the 'void *' trick does work as a workaround here. Albeit it is
> a fairly inelegant one...
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.