This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Using array_length macro outside function


* TAMUKI Shoichi:

> [1] to calculate the number of elements in the array.
>
> [1] https://sourceware.org/ml/libc-alpha/2017-10/msg01054.html
>
> Now, I tried to further improve this as patched below;
>
> ----------------------------------------------------------------------
> diff --git a/time/tst-strftime2.c b/time/tst-strftime2.c
> index 57d2144..6c2d359 100644
> --- a/time/tst-strftime2.c
> +++ b/time/tst-strftime2.c
> @@ -25,8 +25,10 @@
>  #include <string.h>
>  
>  static const char *locales[] = { "ja_JP.UTF-8", "lo_LA.UTF-8", "th_TH.UTF-8" };
> +#define nlocales array_length (locales)

> +static char ref[nlocales][nformats][ndates][100];

The other problem is that array_length (locales) is not a constant
expression because a statement expression is never a constant
expression.  I had not considered these problems when I wrote the
array_length macro.

I would like to retain the verification that the macro argument is not a
pointer.  What do you think about the patch below?

Thanks,
Florian

array_length: Make usable as a constant expression

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: \
                            ^~~~~~~~~~~~~~~~~~~~~
t.c:10:7: note: in expansion of macro ‘array_length’
 int b[array_length (c) + 1];
       ^~~~~~~~~~~~

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.

diff --git a/include/array_length.h b/include/array_length.h
index 65f583063d..cee8897ba7 100644
--- a/include/array_length.h
+++ b/include/array_length.h
@@ -21,13 +21,11 @@
 
 /* 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]);                                   \
-  })
+#define array_length(var)                                       \
+  (sizeof (var) / sizeof ((var)[0])                             \
+   + 0 * sizeof (struct { int ARGUMENT_NOT_AN_ARRAY:            \
+       1 - (__builtin_types_compatible_p                        \
+            (__typeof (var), __typeof (&(var)[0]))); }))
 
 /* array_end (VAR) is a pointer one past the end of the array VAR.
    VAR must evaluate to an array, not a pointer.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]