Subject: Re: toolchain/22118: make won't compile with -Wcast-qual -Wstrict-prototypes and more
To: der Mouse <mouse@Rodents.Montreal.QC.CA>
From: Greg A. Woods <woods@weird.com>
List: tech-toolchain
Date: 07/18/2003 13:47:21
[ On Thursday, July 17, 2003 at 16:34:47 (-0400), der Mouse wrote: ]
> Subject: Re: toolchain/22118: make won't compile with -Wcast-qual -Wstrict-prototypes and more
>
> > However this would mean that ISO/IEC 9899:1990 does not agree with
> > GCC in practice (i.e. by default and then -fwritable-strings is not
> > used)
> 
> By default?  No, only when -Wwrite-strings is used.

Note that '-W' parameters to GCC don't change the generated code -- they
only change how the warnings are generated.

I.e. without '-fwritable-strings' GCC always puts string constants in
read-only storage which really des mean that they have the implied
"const" qualifier, whether you care to believe it or not.

'-Wwrite-strings', in conjunction with '-Wcast-qual' effectively tells
the compiler to _not_ suppress the warnings about "const" discards from
string literals.

I say this because how the control over these warnings is actually
implemented in the compiler is really irrelevant, at least for the
purposes of writing portable code (as I'll explain below).  For example
unless you give GCC the '-Wwrite-strings' flag it will effectively
suppress (even with '-Wall' and '-Wcast-qual') the warnings about
"const" discards from string literals.  Yes the GCC manual says that
it's the other way around, but any programmer attempting to write truly
portable code must always assume that string literals are effectively
"const" qualified because they _may_ be stored in read-only storage
and/or identical instances may be stored at the same address (and indeed
they are by default with GCC).  I.e. the actual effect of not using
'-Wwrite-strings' really is to suppress the implied and desired
warning(s).

I.e. string literals in C are (at least as of C-89) always implied to be
"const" qualified, regardless of whether the compiler actually works
that way or not and regardless of whether the standard explicitly says
they have the implied type "const char[]".  Let me (re)explain what I
mean by that:

Remember the whole poing of providing "const" qualifiers in the C
language in the first place is to make it possible for the compiler to
give a compile-time warning when a constant may be modified, including
by way of a pointer to const-qualified storage.  These warnings are of
course highly desirable in "new" C because the language standard now
explicitly allows an implementation to use read-only and/or shared
storage for constants.

If your compiler doesn't actually give string literals the implied
"const" qualifier then you cannot get such a warning even if you want
one.

However if your code does not assume that string literals have a "const"
qualifier, or if you explicitly fool the compiler by way of pointer
aliasing (for example), then your users may encounter a run-time error
if and when your code (accidentally, of course) attempts to write to a
string literal.  As you no doubt know the debugging of code that
accidentally modifies storage used for shared constants can be extremely
difficult, especially if that storage is not truly read-only in such a
way that the OS will cause an immediate abort if any attempt is made to
write to it.  So if you do end up with a bug of that kind the best you
can hope for is that the error will be a fatal abort of some kind, but
you may also end up with the surprise of some other formerly identical
string literal being changed by accident and the bug not showing itself
until much later during the ongoing execution of your program.

To me, at least, the proper and complete use of "const" qualifiers on
string literals continues to be _highly_ desirable, especially since I
expect my code to be compiled by GCC and perhaps other compilers which
store string literals in read-only and/or shared storage.

>  Yes, this means
> that gcc -Wwrite-strings does not conform to the standard; neither does
> any invocation of gcc without -ansi -pedantic (and possibly not even
> that).

Well whether GCC is non-conformant on this issue is still apparently
open to some question, though Todd's quote from the draft standard
strongly suggests that GCC does fully conform on this matter, regardless
of what command-line options are used.

In any case what the standard says specifically about the implied type
of a string literal is somewhat irrelevant, at least w.r.t. the "const"
qualifier, because of (a) the overriding allowance by the standard for
use of read-only and/or shared storage for constants (including string
literals); and because (b) the standard does not specify what warnings
an implementation should generate when and if it detects discard of
"const" qualifiers.  Thus I think it remains important for portable code
to at least assume that string literals always have a "const" qualifier.

-- 
						Greg A. Woods

+1 416 218-0098                  VE3TCP            RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com>          Secrets of the Weird <woods@weird.com>