[RFC] add NetBSD compat macros to sys/cdefs.h

Bruce Evans brde at optusnet.com.au
Tue May 28 05:06:30 UTC 2013


On Mon, 27 May 2013, Alfred Perlstein wrote:

> On 5/27/13 7:21 PM, Garrett Cooper wrote:
>> Hi,
>>      One of the things that I've done in order to reduce unnecessary
>> divergence when porting NetBSD testcases to FreeBSD is I've pushed a
>> few macros into my sys/cdefs.h in order to facilitate compatibility
>> with NetBSD:
>> 
>> /* NetBSD compat */
>> /*
>>   * The following macro is used to remove const cast-away warnings
>>   * from gcc -Wcast-qual; it should be used with caution because it
>>   * can hide valid errors; in particular most valid uses are in
>>   * situations where the API requires it, not to cast away string
>>   * constants. We don't use *intptr_t on purpose here and we are
>>   * explicit about unsigned long so that we don't have additional
>>   * dependencies.
>>   */
>> #define __UNCONST(a)    ((void *)(unsigned long)(const void *)(a))

Ugh.  Like __DECONST(), this shouldn't exist.  It never existed in my
versions of FreeBSD.  I policed its use a bit until FreeBSD-5, so that
my local patches for FreeBSD-5 only have to burn it in 8 files (3 in
the kernel and 5 in the kernel).

Warnings from -Wcast-qual should never be "fixed" using this.  Either
don't use -Wcast-qual, or fix the bugs that it finds.  Sometimes it
is impossible to fix the bugs because they are in a standard API.  Then
all methods of avoiding the warning are bad, and using __DECONST() is
one of the worst.  Its only advantage is that it is so ugly and
unportable that it serves to document the API bug.

Unlike __DECONST(), __UNCONST() doesn't even work.  uintptr_t (better
__uintptr_t to reduce dependencies) must be used, since unsigned long
just doesn't work unless it is identical to uintptr_t and that is true
on all 32-bit arches.

Apart from its design errors, the __DEMISTAKE() family has many
implementation errors.  I only fixed these by removing it.  It is large
and ugly, but not large and ugly enough to work in all cases.  The
main broken cases are:
- __DECONST() on a const volatile type (it strips the volatile qualifier)
- __DEVOLATILE() on a const volatile type (it strips the const qualifier)
- missing casts from uintptr_t to void * on the way back to a pointer.
   uintptr_t is only guaranteed to work with void * or qualified void *.
It is a feature that it is not documented in any man page.  This should
prevent its use.  Its dependency on other headers is OK since this
would be in the documentation if it had any.

>> 
>> #define ___STRING(x)            __STRING(x)
>> #define __arraycount(__x)       (sizeof(__x) / sizeof(__x[0]))
>> /* End NetBSD compat */
>> 
>> To clarify...
>> - I know __UNCONST is basically like __DECONST on steroids as
>> __UNCONST doesn't have the typecasting like __DECONST does.

It is not really on steroids, just has different broken casts.  It isn't
missing the cast to void * on the way back to a pointer.  Not casting to
a final pointer type is probably better, but gives subtly different
semantics.

Bruce


More information about the freebsd-arch mailing list