Unlike other -W family options, -Wwrite-strings does not actually behave as a warning option but as an option that alters the language semantics. I think this inconsistency should be considered a bug and fixed. It leads to multiple issues:
1. Warning messages wrongly show as [enabled by default] rather than [-Wwrite-strings], since discarding const qualifier is enabled by default.
2. Some code which should produce a warning actually produces an error. As a trivial but stupid example, if(0)*""=0; One can of course construct non-trivial, non-stupid examples of this, particularly with the ?: operator.
3. The semantics of code using __typeof__, ?:, and now more importantly with C11, _Generic, are changed by -Wwrite-strings. As a particularly bad case, I think this could lead to the introduction of aliasing violations and undefined behavior in code that had well-defined behavior without -Wwrite-strings.
Ideally the current implementation of -Wwrite-strings should be scrapped and replaced with one that actually detects particular usage that's deemed dangerous rather than changing the language semantics.
Agreed. It seems that in order to get the desired warning, the solution was to change the type and warn implicitly, rather than detect the potential cases explicitly. This is a quite ugly hack.
On the other hand, I don't expect an existing GCC developer to fix this, given the long history of -Wwrite-strings. Someone new will have to step up, implement it and defend it in front of the C FE maintainers.
Confirmed. I might possibly get to this.
(In reply to Marek Polacek from comment #2)
> Confirmed. I might possibly get to this.
For gcc 9 maybe?
Wow, how has it been 4 years already? Maybe this time around then. :)
(In reply to Marek Polacek from comment #4)
> Wow, how has it been 4 years already? Maybe this time around then. :)
Hopefully! I keep seeing it come up places...
Could "-Wwrite-strings" be split into two options? The warning could remain (and become part of -Wall for C as well as C++) if the compiler can spot and warn about attempts to write to string literals, while keeping these of type "char[len]" as required by C.
A new option "-fconst-strings" could be put under "Code Gen Options" which makes C string literals be type "const char[len]" for those that want it, encouraging a slightly safer code style that is not standard C.
(In reply to David Brown from comment #7)
> Could "-Wwrite-strings" be split into two options? The warning could remain
> (and become part of -Wall for C as well as C++) if the compiler can spot and
> warn about attempts to write to string literals, while keeping these of type
> "char[len]" as required by C.
I think the issue is that the warning is implemented by changing the type of string literals and then using the already existing warning for passing const char* to char*. Someone would need to reimplement the warning to explicitly detect string literals instead of changing their type, probably somewhere in this function: https://github.com/gcc-mirror/gcc/blob/259c3965b1ba04f7ee022846af6173fb1c343bc8/gcc/c/c-typeck.c#L6585
> A new option "-fconst-strings" could be put under "Code Gen Options" which
> makes C string literals be type "const char[len]" for those that want it,
> encouraging a slightly safer code style that is not standard C.
I am not sure this is a good solution, since the only benefit of -fconst-strings would be to trigger the warnings. I'm pretty sure it will not affect optimization, so it is useless as a codegen option. It doesn't solve all the issues described in comment #0.
The fix is the one outlined above: detect that the argument or assigment is a literal string and special case the "discarding const qualifier" to trigger in that case with -Write-strings.
But, the only way to find out for sure is to submit a patch to gcc-patches and start the discussion.
pr90404 is somewhat related to this: it requests a new warning option to flag attempts to modify a const object of any type/kind. In my prototype implementation of it that I hope to submit for GCC 11 I call the option -Wwrite-const. It's implemented in the middle end so it detects all such attempts, including for instance things like '*strchr("x", 'x') = 0', and avoids triggering on provably unreachable code. It's just as capable as other late warnings, but, of course, also subject to just as many false positives and negatives as they are.