Re: [PATCH 10/10] bug.h: Add gcc 4.2+ versions of BUILD_BUG_ON_* macros

Daniel Santos
2012-10-02T16:04:08Z

On 10/01/2012 07:55 PM, Michel Lespinasse wrote:
> On Fri, Sep 28, 2012 at 4:20 PM, Daniel Santos <daniel.santos@pobox.com> wrote:
>> BUILD_BUG_ON42(arg)
>> BUILD_BUG_ON_CONST42(arg)
>>
>> Prior to gcc 4.2, the optimizer was unable to determine that many
>> constant values stored in structs were indeed compile-time constants and
>> optimize them out. Sometimes, it will find an intergral value to be a
>> compile-time constant, but fail to perform a bit-wise AND at
>> compile-time. These two macros provide a mechanism to perform these
>> build-time checks, but not break on older compilers where we already
>> know they can't be checked at compile time.
>>
>> For specific details, consult the doc comments for BUILD_BUG_ON_CONST.
>> These macros are used in the generic rbtree code.
>
> I think the names are quite confusing. BUILD_BUG_ON_NON_CONST42 sounds
> like it's checking if 42 is a constant.
>
> The name probably shouldn't mention what compiler versions support
> this check, but instead it should hint as to when you should use this
> instead of BUILD_BUG_ON_CONST ? Maybe BUILD_BUG_ON_CONST_DEREF or
> something (I'm pretty bad with names too :)
I completely agree about the naming, but I'm also stumped. I choose
version 4.2 after writing a test program & group of scripts and sifting
through the results of 220k tests of __builtin_constant_p()! In gcc
4.2, there are still some tests that will fail, but I went with 4.2 as
the "good version" mostly because:

a. the broken tests didn't affect my generic red-black tree
implementation, and
b. broken cases in 4.2 were the slim minority.

For instance calling __builtin_constant_p() on a dereferenced pointer in
4.2 always fails, while dereferencing a global static array (of
primitives) returns 1 in pretty much every case that it should
(excepting global non-static const, which also fails in 4.7 and perhaps
the compiler figures that somewhere else, const can be cast away and the
data modified anyway?).

Maybe it would be better in the long term to create multiple macros for
testing various constructs. Verbosity does really start to increase
here, but I suppose we can work out some type of nomenclature to control
that while still being clear about what the macro does (not that I have
any ideas at the moment).

BUILD_BUG_ON_NON_CONST_PTR_DEREF - gcc 4.4
BUILD_BUG_ON_NON_CONST_ARRAY_DEREF - gcc 4.2
BUILD_BUG_ON_NON_CONST_STRUCT_MEMBER - gcc 4.2 (unless it's a pointer or
you use -O1)
etc.

To make it any more clear, I suppose I will have to clean up my test
results and share them again (an 82k spreadsheet uncompressed). Let me
know if you want to see it. So it's really for a sort of
full-disclosure that I use the suffix "42" and not something more
specific to what it should test.

Alternately, we can just call it something like
BUILD_BUG_ON_NON_CONST_MODERN and bump the version up gcc 4.4, which is
just as functional as 4.7.

Daniel