Consider this C code:
void foo(char *);
void bar(void) {
foo("");
}
When I compile that with -pedantic -Wall -Wextra
with GCC or Clang, or with -Weverything
with Clang, it compiles without giving me any relevant warnings. If I add -Wwrite-strings
, then GCC gives me this:
<source>:4:9: warning: passing argument 1 of 'foo' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
4 | foo("");
| ^~
<source>:1:10: note: expected 'char *' but argument is of type 'const char *'
1 | void foo(char *);
| ^~~~~~
And clang gives me this:
<source>:4:9: warning: passing 'const char [1]' to parameter of type 'char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
foo("");
^~
<source>:1:16: note: passing argument to parameter here
void foo(char *);
^
Lots of things seem wrong here to me:
- This seems like a pretty important warning not only to be off by default, but also to be off even with most of the ways that people enable warnings in practice.
- GCC's output refers to
-Wdiscarded-qualifiers
, but if I pass that instead of-Wwrite-strings
, I don't get that warning. - I thought
-Weverything
meant "literally every single warning the compiler knows about", but this seems to contradict that. - If I compile the same code as C++ instead of as C, then both GCC and Clang give me the warning I want without needing any compiler flags at all. I'm not sure why there's a difference between the languages here, since AFAIK, both C and C++ have undefined behavior if you actually write to the string literal.
What's going on here? Why does this particular warning seem so buggy?