[Openswan dev] libosw (fwd)

D. Hugh Redelmeier hugh at mimosa.com
Tue Sep 13 11:57:43 EDT 2011


| From: Michael Richardson <mcr at sandelman.ca>

| I'm using libopenswan (initsubnet, etc.) in another project.
| We just discovered that gcc-4.5 is even more pedantic.
| 
| initsubnet.c: In function 'initsubnet':
| initsubnet.c:38:2: error: new qualifiers in middle of multi-level non-const cast are unsafe
| 
| referring to:
| 
| 	n = addrbytesptr(&dst->addr, (const unsigned char **)&p);

That's odd.  I don't think that the new qualifier is in the middle --
it's on the lowest level.

C's const is too simplistic.  One wants to write functions where the
qualifications of some arguments or results is a function of the
qualifications of some other arguments or results.  That cannot be
expressed.

The classic example is strchr.  The definition says:
	char *strchr(const char *s, int c);
BUT the correct (inexpressible) qualification of the first arg is
const-optional and the correct qualification of the result is
same-constness-as-s.  So that is a fudge.

If C allowed overloading, you'd have two functions:
	char *strchr(char *s, int c);
	const char *strchr(const char *s, int c);
with one implementation (because the implementation doesn't actually
depend on the constness).

addrbytesptr wants the same thing (constness **dstp should be the same
as the constness of *src) but has been coded in the pure way: with
both const.

Here's what I GUESS would pass any purity test.  This replaces the call
to addrbytesptr in initsubnet.

	{
		const unsigned char *q;

		n = addrbytesptr(&dst->addr, &q);
		p = (unsigned char *) (void *) &dst->addr;
		p += (const unsigned char *)q - p;
	}

A simpler but sloppy change would be to remove the const from the
declaration of dstp in addrbytesptr.  I expect that the compiler would
whine.  You could find out how glibc gets around this for strchr (I'm
too lazy at the moment).

| the net suggests that maybe it should be:
| 	n = addrbytesptr(&dst->addr, (const unsigned char *const *)&p);
| 
| but, actually that's not right, the function is going to modify the
| thing pointed to, but not the pointer itself. 

Agreed.  A "middle" const qualification isn't in play.

Heck -- maybe it's a gcc bug.  Try gcc 4.6.

| google found one hit for this error on the openswan list a year ago, but
| nobody appears to have solved this, unless I missed something.

I don't subscribe to the users list and the archive seems to be down
at the moment.

| Do you understand this?

The semantics of const are (is?) slippery.

It doesn't mean "this thing isn't going to change".

I think that it really means "nobody will write to this thing using an
L-value derived from this value or referent".  That means that casting
away const does not get rid of the obligation.  But casting to const
does create an obligation!  Note: I haven't read the standard on this
in years so my internalization is possibly wrong (likely more
consistent).

|  I think that I need to write "non-const", but I
| didn't think I could do that.

Not writing "const" means "non-const".


More information about the Dev mailing list