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 18:00:16
[ On Friday, July 18, 2003 at 15:43:10 (-0400), der Mouse wrote: ]
> Subject: Re: toolchain/22118: make won't compile with -Wcast-qual -Wstrict-prototypes and more
>
> > The whole purpose of the "const" qualifier in the first place is to
> > help the compiler know when to warn the programmer that he or she (or
> > a Standard-define API) has declared that a code path _may_ result in
> > an attempt to modify a constant, including a string literal constant.
> 
> What is your basis for believing you know the intent behind "const"?
> 
> Second Edition K&R says (A8.2) that the purpose of const is "to
> announce objects that may be placed in read-only memory, and perhaps to
> increase opportunities for optimization".

What do you think the difference is between what I say and what K&R say?

As far as I can tell there is no difference.  I only use different
phrasing in order to try to offer another view of the same issue.

> You appear to believe that it is somehow inherently Wrong to have a
> path via which a const qualifier can ever be stripped from a pointer
> target type, because (near as I can figure) this introduces an
> opportunity for a bug to attempt to write into read-only storage
> without any opportunity for the compiler to notice it through "attempt
> to modify a const object" detection.

It's not so much a matter that it's wrong but rather just I don't
pretend to believe that it'll ever be possible to implement a compiler
that can somehow intuit what will happen in the future when the code it
is generated is run.

> Yes, such a path does introduce such potential.

Exactly.  And that's all the compiler can know.  If you don't want to
use -fwritable-strings then you need to heed the compiler's warnings
lest together you or some future maintainer of your code make a mistake
which turns that potential into reality.

> That does not make it inherently wrong.

It's not "wrong" -- it's just a warning.  As I said, you can choose to
ignore, or disable, or even work around, the warning if you wish.
However as I've also said I believe any programmer would be stupid to do
any of those things, especially if he or she expected the code in
question to be compiled with any compiler such as GCC which does take
advantage of Standard C's allowance for placing string constants in
read-only (and/or shared for identical strings) storage.  I don't mind
having to either fix or use -fwritable-strings for such bugs in code
written for pre-ANSI implementations, but it bothers me a great deal
when I have to fix such bugs in code that claims to be standards
compatible but turns out to clearly not be standards compatible.

> Only provided you, the coder, have been sufficiently disciplined.

That's why the compiler spits out warnings -- to discipline the coder.

As with most forms of self-discipline it only works if the recipient is
at least somewhat willing to be disciplined.  -Werror helps make the
warning more than a slap on the wrist but unless your code is reviewed
and controlled by someone who insists on using -Werror it's still
nothing more than self-discipline.

> > It should be quite clear to all that "const" is merely advice to the
> > compiler about what the programmer believes the code will do and that
> > the warnings in return are merely advice to the programmer [...]
> 
> Right.  So why are you so bent out of shape over using things like
> deconst() as additional advice to the compiler

DECONST() is inherently wrong and dangerous because it hides the real
problem.  Disseminating use of something like DECONST() encourages very
bad programming practices.  DECONST() makes a joke of all attempts to
use "const" and the related GCC warning features.

It is one thing to complain about what you perceive to be a poorly
defined API.  It is quite another entirely to claim it is OK to play
tricks on the compiler just to hide the problems you perceive in an API,
especially if you are then going to claim the code you've written those
tricks into is somehow still portable (not saying you have made such a
claim, but if you were to...).

> that in _this_
> particular place, the coder advises the compiler that the apparent
> danger is only apparent, not real?

Note that the code which started this discussion is still wrong with
respect to its use of "const" and all of the problems I can see with it
are strictly internal -- none even relate to anything like "struct
iovec" and as such it should be possible to fix them all without any
real trouble with any public APIs whatsoever.

I.e. in this case the proper fix is to correct the "const" advice that
has been given to the compiler, not to tell the compiler to ignore it.

> Of course, if the coder mis-advises the compiler, problems can result.
> That has always been true and always will be, and is by no means
> restricted to inappropriate use of deconst().

Indeed, but the only examples to date of such incorrect advice have been
from improperly concieved attempts to get rid of valid "const" discard
warnings.

The ability of the compiler to warn the programmer of mis-use of "const"
is obviously restricted by use of DECONST() and thus all such uses are
always inappropriate.

I.e. there is no valid possible place for UNCONST(), DECONST(), or
whatever you want to call it, in any portable Standard C code and
especially not in any that claims to be somewhat compatible with
Standard C.

Either give the compiler the correct "const" advice in the first place,
or use '-fwritable-strings' with GCC and hope the only other compilers
your code ever encounters are also capable of disabling the use of
read-only and/or shared storage for constants.


> > I.e. if you think you need DECONST() then you are mistaken as the
> > real problem is elsewhere.  So far nobody has demonstrated even a
> > hint of a standard (de facto or otherwise) API which mis-uses "const"
> > and thus would require DECONST() tricks to either implement or use it
> > without changing the original API
> 
> Apparently you missed the message in which I cited four such:

As I've already discussed, in some depth, none of those APIs are really
valid excuses in any way whatsoever (at least not for Standard C).

> Like all such, you _can_ use them without deconst()

Actually as far as I can see it happens that with all but "struct iovec"
it is most natural to use those APIs in ways that would never confuse
anyone into thinking they needed DECONST().

With "struct iovec" (as with my lesser example of a DB key) it's
necessary to use array variables, but so be it.  That's the price we pay
for continuing to use in Standard C APIs that were designed for K&R C,
(or at least were designed before Standard C came along, or without it's
new constraints in mind).

> > I'm trying to prevent you and others from inventing and disseminating
> > a construct that is blatantly wrong and which will result in far more
> > problems than it appears to initially solve,
> 
> ...specifically...?

_EVERY_ time you work behind the compiler's back to prevent it from
detecting potential problems you have done something which can cause
problems for any future maintainer.  Disseminating and promoting such
bad hacks is always blatantly wrong.

> > I'm also very happy to learn from this discussion that GCC's use of
> > writable storage for "char foo[]" initializers is likely to be
> > mirrored by other conforming Standard C implementations.
> 
> You are so utterly confused on this I'm not sure how to fix it.

It is not I who is confused, but rather it is you who are confused about
what you think I mean.  (hint:  data from initializers for char foo[]
variables is placed in writable storage)

-- 
						Greg A. Woods

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