svn commit: r277903 - head/sys/libkern

Bruce Evans brde at optusnet.com.au
Fri Jan 30 06:53:47 UTC 2015


On Thu, 29 Jan 2015, Dimitry Andric wrote:

> Log:
>  Similar to r277901, fix more -Wcast-qual warnings in libkern's strtoq(),
>  strtoul() and strtouq(), by using __DECONST.  No functional change.

Here the fix is no worse than the original code.

> Modified: head/sys/libkern/strtoq.c
> ==============================================================================
> --- head/sys/libkern/strtoq.c	Thu Jan 29 21:31:29 2015	(r277902)
> +++ head/sys/libkern/strtoq.c	Thu Jan 29 21:54:01 2015	(r277903)
> @@ -125,6 +125,6 @@ strtoq(const char *nptr, char **endptr,
> 	} else if (neg)
> 		acc = -acc;
> 	if (endptr != 0)
> -		*((const char **)endptr) = any ? s - 1 : nptr;
> +		*endptr = __DECONST(char *, any ? s - 1 : nptr);
> 	return (acc);
> }

libc does use either the previous bogus cast or __DECONST().  It just
writes the conversion in C:

 		endptr = (char *)(any ? s - 1 : nptr);

This reminds me that __DECONST() is never needed for clang, since
-Wcast-qual is broken for clang.  -Wcast-qual works for gcc, so together
with -Werror it gives a non-C compiler that can't compile the libc version.
However, -Wcast-qual has never been used for compiling libc, and the above
C code hasn't been mutilated in it.  -Wcast-qual is turned on at WARNS > 4
in userland, and seems to have led to more breakages of the warning than
API fixes.  -Wcast-qual has been on in the kernel since 1999 although it
was intentionally left out originally.  So libkern/strtol.c needed some
hack to compile with gcc.  It no longer needs this hack to compile with
clang.

For variations of the following function:

 	void foo(const char *cp, char endp) { *endp = p; }

these errors are detected:

- with no cast of p: C requires a diagnostic.  gcc always prints one.
   clangs warning says that this is under -Wfoo, where foo is too long to
   type
- with p cast to char *: C requires this to work as well as possible, with
   no diagnostic.  gcc and clang work right by default.
- with p cast to char *, and -Wcast-qual: the option behaviour not defined
   by standard.  For gcc, it is documented to restore the warning that is
   killed by the cast.  The documentation in the man page is quite complete.
   It even gives an example of how adding const qualifiers using bogus casts
   has the same effect as removing them.  For clang, -Wcast-qual is
   undocumented in any man or info page and has no effect.

The bogus cast previously used in libkern/strtol.c is precisely the one
used in gcc's example.  Its bogusness is even more complicated than I
first thought or mentioned above:
- it was a bug in gcc that -Wcast-qual didn't detected its bogusness.  It
   worked to break the warning up to at least gcc-4.2.  But this is fixed
   in gcc-4.8.  The example using it is new in gcc-4.8 too.
- you apparently "fixed" this to work with ports versions of gcc, or to
   work with a non-broken undocumented unsupported by *mk clang option that
   gives the same results as the gcc -Wcast-qual.

Note that if -Wcast-qual was complete, it would also warn for the type
hacks in __DECONST().  Casting to uintptr_t subverts type checking even
more completely than casting to another pointer type.

The only advantage of __DECONST() is to make type hacks more blatant.  I
casts so rarely that almost all uses of casts are type hacks.

Bruce


More information about the svn-src-head mailing list