Using array_length macro outside function
Commit Message
* Joseph Myers:
> On Mon, 4 Feb 2019, Florian Weimer wrote:
>
>> Do not use a statement expression and _Static_assert in array_length,
>> so that array_length can be used at file scope and as a constant
>> expression.
>>
>> The compiler error message looks like this, so this is still
>> acceptable:
>>
>> t.c:3:28: error: zero width for bit-field ‘ARGUMENT_NOT_AN_ARRAY’
>> 0 * sizeof (struct { int ARGUMENT_NOT_AN_ARRAY: \
>
> You can use _Static_assert inside a struct; you don't need to do things
> with bit-field sizes.
That's certainly nicer. Please consider the patch below.
Thanks,
Florian
array_length: Make usable as a constant expression
Do not use a statement expression in array_length, so that
array_length can be used at file scope and as a constant expression.
Instead, put the _Static_assert into a struct (as a declaration),
and nest this in the expression using a sizeof expression.
2019-02-04 Florian Weimer <fweimer@redhat.com>
* include/array_length.h (array_length): Do not use a statement
expression and _Static_assert, so that array_length can be used at
file scope and as a constant expression.
Comments
Hello Florian-san,
From: Florian Weimer <fweimer@redhat.com>
Subject: Re: Using array_length macro outside function
Date: Tue, 05 Feb 2019 13:29:08 +0100
> > You can use _Static_assert inside a struct; you don't need to do things
> > with bit-field sizes.
>
> That's certainly nicer. Please consider the patch below.
Looks good to me. Applying the revised patch, I have also confirmed
that the test can be compiled successfully.
Tested-by: TAMUKI Shoichi <tamuki@linet.gr.jp>
Regards,
TAMUKI Shoichi
@@ -22,12 +22,12 @@
/* array_length (VAR) is the number of elements in the array VAR. VAR
must evaluate to an array, not a pointer. */
#define array_length(var) \
- __extension__ ({ \
- _Static_assert (!__builtin_types_compatible_p \
- (__typeof (var), __typeof (&(var)[0])), \
- "argument must be an array"); \
- sizeof (var) / sizeof ((var)[0]); \
- })
+ (sizeof (var) / sizeof ((var)[0]) \
+ + 0 * sizeof (struct { \
+ _Static_assert (!__builtin_types_compatible_p \
+ (__typeof (var), __typeof (&(var)[0])), \
+ "argument must be an array"); \
+ }))
/* array_end (VAR) is a pointer one past the end of the array VAR.
VAR must evaluate to an array, not a pointer. */