Date: Fri, 30 Jan 2015 17:53:26 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Dimitry Andric <dim@freebsd.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r277903 - head/sys/libkern Message-ID: <20150130165756.I1034@besplex.bde.org> In-Reply-To: <201501292154.t0TLs2Nw062949@svn.freebsd.org> References: <201501292154.t0TLs2Nw062949@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20150130165756.I1034>