Using array_length macro outside function

Message ID 87va1ybeqz.fsf@oldenburg2.str.redhat.com
State Committed
Headers

Commit Message

Florian Weimer Feb. 5, 2019, 12:29 p.m. UTC
  * 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

TAMUKI Shoichi Feb. 6, 2019, 3:27 a.m. UTC | #1
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
  

Patch

diff --git a/include/array_length.h b/include/array_length.h
index 65f583063d..db98a69899 100644
--- a/include/array_length.h
+++ b/include/array_length.h
@@ -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.  */