mbox series

[v5,0/3] c: Add __lengthof__ operator

Message ID 20240806231151.1046913-1-alx@kernel.org
Headers show
Series c: Add __lengthof__ operator | expand

Message

Alejandro Colomar Aug. 6, 2024, 11:11 p.m. UTC
Hi!

This is ready for review.

v5:

-  Add changelog entries.
-  Wording fixes in commit messages.
-  s/sizeof/lengthof/ in comment.
-  CC += David, Florian, Andreas  [Qing]
-  Docs: Remove some details about future directions.  [Qing]
-  Docs: Add examples.  [Qing]
-  Docs: Clarify when __lengthof__ evaluates as a constant expression
   and when it evaluates as a run-time value.  [Joseph, Qing]
-  Tests: Use several -Wno-* flags to turn off unwanted warnings.
   [Martin, Joseph]
-  Tests: Merge into the same commit that adds the feature.
-  Tests: Fix style (whitespace).

I won't paste the example program I used for development, since it's the
same as in v4.  Check that cover letter if necessary.

When reviewing, mind that some parts of the code have been blindly
pasted from sizeof, and might not make much sense; I didn't fully
understand some parts.  However, it seems to behave well, and more or
less it makes sense.  Just be careful about it.

At the bottom of this message is the range-diff against v4.

Have a lovely night!
Alex


BTW, I've tested that there are no regressions:

	alx@debian:~/src/gnu/gcc$ find len0 -type f
	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum
	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum
	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum
	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum
	len0/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum
	len0/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum
	len0/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum
	len0/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum
	alx@debian:~/src/gnu/gcc$ find len1 -type f
	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum
	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum
	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum
	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum
	len1/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum
	len1/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum
	len1/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum
	len1/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum
	alx@debian:~/src/gnu/gcc$ cat <(cd len0; find -type f) \
				| while read f; do
					diff -u "len0/$f" "len1/$f";
				done;
	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06
	+22:22:44.514175252 +0200
	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06
	+23:29:53.693730123 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== gcc tests ===
	@@ -86504,6 +86504,15 @@
	 PASS: gcc.dg/large-size-array.c  (test for errors, line 19)
	 PASS: gcc.dg/large-size-array.c (test for excess errors)
	 UNSUPPORTED: gcc.dg/lazy-ptr-test.c
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 11)
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 15)
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 27)
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 42)
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 45)
	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 48)
	+PASS: gcc.dg/lengthof-compile.c (test for excess errors)
	+PASS: gcc.dg/lengthof.c (test for excess errors)
	+PASS: gcc.dg/lengthof.c execution test
	 PASS: gcc.dg/limits-width-1.c (test for excess errors)
	 PASS: gcc.dg/limits-width-2.c (test for excess errors)
	 PASS: gcc.dg/live-patching-1.c (test for excess errors)
	@@ -204639,7 +204648,7 @@

			=== gcc Summary ===

	-# of expected passes           199780
	+# of expected passes           199789
	 # of unexpected failures       31
	 # of unexpected successes      2
	 # of expected failures         1463
	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06
	+22:22:44.546175561 +0200
	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06
	+23:29:53.877731933 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== gfortran tests ===
	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06
	+22:22:44.462174752 +0200
	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06
	+23:29:53.845731618 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== objc tests ===
	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06
	+22:22:44.622176292 +0200
	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06
	+23:29:53.781730989 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== g++ tests ===
	--- len0/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06
	+22:22:46.206191541 +0200
	+++ len1/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06
	+23:29:55.573748613 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== libitm tests ===
	--- len0/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06
	+22:22:45.694186612 +0200
	+++ len1/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06
	+23:29:54.717740194 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== libgomp tests ===
	--- len0/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06
	+22:22:46.110190617 +0200
	+++ len1/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06
	+23:29:55.393746843 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:53 2024
	+Test run by alx on Tue Aug  6 22:49:12 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== libatomic tests ===
	--- len0/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06
	+22:22:45.998189539 +0200
	+++ len1/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06
	+23:29:55.137744325 +0200
	@@ -1,4 +1,4 @@
	-Test run by alx on Tue Aug  6 19:28:54 2024
	+Test run by alx on Tue Aug  6 22:49:13 2024
	 Native configuration is x86_64-pc-linux-gnu

			=== libstdc++ tests ===





Alejandro Colomar (3):
  gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
  Merge definitions of array_type_nelts_top()
  c: Add __lengthof__ operator

 gcc/c-family/c-common.cc                |  26 +++++
 gcc/c-family/c-common.def               |   3 +
 gcc/c-family/c-common.h                 |   2 +
 gcc/c/c-decl.cc                         |  30 ++++--
 gcc/c/c-fold.cc                         |   7 +-
 gcc/c/c-parser.cc                       |  61 +++++++++---
 gcc/c/c-tree.h                          |   4 +
 gcc/c/c-typeck.cc                       | 114 ++++++++++++++++++++-
 gcc/config/aarch64/aarch64.cc           |   2 +-
 gcc/config/i386/i386.cc                 |   2 +-
 gcc/cp/cp-tree.h                        |   1 -
 gcc/cp/decl.cc                          |   2 +-
 gcc/cp/init.cc                          |   8 +-
 gcc/cp/lambda.cc                        |   3 +-
 gcc/cp/operators.def                    |   1 +
 gcc/cp/tree.cc                          |  13 ---
 gcc/doc/extend.texi                     |  23 +++++
 gcc/expr.cc                             |   8 +-
 gcc/fortran/trans-array.cc              |   2 +-
 gcc/fortran/trans-openmp.cc             |   4 +-
 gcc/rust/backend/rust-tree.cc           |  13 ---
 gcc/rust/backend/rust-tree.h            |   2 -
 gcc/target.h                            |   3 +
 gcc/testsuite/gcc.dg/lengthof-compile.c |  49 +++++++++
 gcc/testsuite/gcc.dg/lengthof.c         | 127 ++++++++++++++++++++++++
 gcc/tree.cc                             |  17 +++-
 gcc/tree.h                              |   3 +-
 27 files changed, 451 insertions(+), 79 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/lengthof-compile.c
 create mode 100644 gcc/testsuite/gcc.dg/lengthof.c

Range-diff against v4:
1:  73010cb4af6 = 1:  73010cb4af6 gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
2:  2bb966a0a89 ! 2:  9b835478721 Merge definitions of array_type_nelts_top()
    @@ Commit message
         Merge definitions of array_type_nelts_top()
     
         There were two identical definitions, and none of them are available
    -    where they are needed for implementing __lengthof__().  Merge them, and
    +    where they are needed for implementing __lengthof__.  Merge them, and
         provide the single definition in gcc/tree.{h,cc}, where it's available
    -    for __lengthof__().
    +    for __lengthof__, which will be added in the following commit.
    +
    +    gcc/ChangeLog:
    +
    +            * tree.h (array_type_nelts_top):
    +            * tree.cc (array_type_nelts_top): Define function (moved from
    +            gcc/cp/).
    +
    +    gcc/cp/ChangeLog:
    +
    +            * cp-tree.h (array_type_nelts_top):
    +            * tree.cc (array_type_nelts_top): Remove function (move
    +            to gcc/).
    +
    +    gcc/rust/ChangeLog:
    +
    +            * backend/rust-tree.h (array_type_nelts_top):
    +            * backend/rust-tree.cc (array_type_nelts_top): Remove function.
     
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
3:  e2dbfc43b14 ! 3:  af05d01e68d c: Add __lengthof__() operator (n2529)
    @@ Metadata
     Author: Alejandro Colomar <alx@kernel.org>
     
      ## Commit message ##
    -    c: Add __lengthof__() operator (n2529)
    +    c: Add __lengthof__ operator
     
    -    This operator is similar to sizeof() but can only be applied to an
    -    array, and returns its length (number of elements).
    +    This operator is similar to sizeof but can only be applied to an array,
    +    and returns its length (number of elements).
     
         FUTURE DIRECTIONS:
     
    -            We could make it work with array parameters to functions, and
    -            somehow magically return the length designator of the array,
    -            regardless of it being really a pointer.
    +      We could make it work with array parameters to functions, and
    +      somehow magically return the length designator of the array,
    +      regardless of it being really a pointer.
     
    -    Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf>
    -    Link: <https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/>
    -    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>
    -    Co-developed-by: Martin Uecker <uecker@tugraz.at>
    -    Cc: Gabriel Ravier <gabravier@gmail.com>
         Cc: Joseph Myers <josmyers@redhat.com>
    +    Cc: Gabriel Ravier <gabravier@gmail.com>
         Cc: Jakub Jelinek <jakub@redhat.com>
         Cc: Kees Cook <keescook@chromium.org>
         Cc: Qing Zhao <qing.zhao@oracle.com>
         Cc: Jens Gustedt <jens.gustedt@inria.fr>
    +    Cc: David Brown <david.brown@hesbynett.no>
    +    Cc: Florian Weimer <fweimer@redhat.com>
    +    Cc: Andreas Schwab <schwab@linux-m68k.org>
    +
    +    gcc/ChangeLog:
    +
    +            * doc/extend.texi: Document __lengthof__ operator.
    +            * target.h (enum type_context_kind): Add __lengthof__ operator.
    +
    +    gcc/c-family/ChangeLog:
    +
    +            * c-common.h:
    +            * c-common.def:
    +            * c-common.cc (c_lengthof_type): Add __lengthof__ operator.
    +
    +    gcc/c/ChangeLog:
    +
    +            * c-tree.h
    +            (c_expr_lengthof_expr, c_expr_lengthof_type):
    +            * c-decl.cc
    +            (start_struct, finish_struct):
    +            (start_enum, finish_enum):
    +            * c-parser.cc
    +            (c_parser_sizeof_expression):
    +            (c_parser_lengthof_expression):
    +            (c_parser_sizeof_or_lengthof_expression):
    +            (c_parser_unary_expression):
    +            * c-typeck.cc
    +            (build_external_ref):
    +            (record_maybe_used_decl, pop_maybe_used):
    +            (is_top_array_vla):
    +            (c_expr_lengthof_expr, c_expr_lengthof_type):
    +            Add __lengthof__operator.
    +
    +    gcc/cp/ChangeLog:
    +
    +            * operators.def: Add __lengthof__ operator.
    +
    +    gcc/testsuite/ChangeLog:
    +
    +            * gcc.dg/lengthof-compile.c:
    +            * gcc.dg/lengthof.c: Add tests for __lengthof__ operator.
    +
    +    Link: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf
    +    Link: https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/
    +    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>
    +    Co-developed-by: Martin Uecker <uecker@tugraz.at>
         Signed-off-by: Alejandro Colomar <alx@kernel.org>
     
      ## gcc/c-family/c-common.cc ##
    @@ gcc/c/c-typeck.cc: int in_alignof;
      /* The level of nesting inside "sizeof".  */
      int in_sizeof;
      
    -+/* The level of nesting inside "sizeof".  */
    ++/* The level of nesting inside "lengthof".  */
     +int in_lengthof;
     +
      /* The level of nesting inside "typeof".  */
    @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} expression is a fu
     +Its syntax is just like @code{sizeof}.
     +The operand must be a complete array type.
     +The operand is not evaluated
    -+if the top-level length designator is an integer constant expression;
    ++if the top-level length designator is an integer constant expression
    ++(in this case, the operator results in a constant expression);
     +and it is evaluated
    -+if the top-level length designator is not an integer constant expression.
    ++if the top-level length designator is not an integer constant expression
    ++(in this case, the operator results in a run-time value).
    ++For example:
     +
    -+XXX: Do we want to document the following?  I think so.
    -+XXX: It would prevent users from relying on __lengthof__
    -+XXX: for distinguishing arrays from pointers.
    -+XXX: I don't want users to complain in the future
    -+XXX: if this doesn't report errors on function parameters anymore
    -+XXX: and that breaks their assumptions.
    -+In the future,
    -+it might also accept a function parameter with array notation,
    -+an incomplete array whose length is specified by other means,
    -+such as attributes,
    -+or other similar cases.
    ++@smallexample
    ++__lengthof__ (int [7][n++]);  // constexpr
    ++__lengthof__ (int [n++][7]);  // run-time value
    ++@end smallexample
     +
      @node Inline
      @section An Inline Function is As Fast As a Macro
    @@ gcc/target.h: enum type_context_kind {
        /* Creating objects of type T with static storage duration.  */
        TCTX_STATIC_STORAGE,
      
    +
    + ## gcc/testsuite/gcc.dg/lengthof-compile.c (new) ##
    +@@
    ++/* { dg-do compile } */
    ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */
    ++
    ++extern int x[];
    ++
    ++void
    ++incomplete (int p[])
    ++{
    ++  unsigned n;
    ++
    ++  n = __lengthof__ (x);  /* { dg-error "incomplete" } */
    ++
    ++  /* We want to support the following one in the future,
    ++     but for now it should fail.  */
    ++  n = __lengthof__ (p);  /* { dg-error "invalid" } */
    ++}
    ++
    ++void
    ++fam (void)
    ++{
    ++  struct {
    ++    int x;
    ++    int fam[];
    ++  } s;
    ++  unsigned n;
    ++
    ++  n = __lengthof__ (s.fam); /* { dg-error "incomplete" } */
    ++}
    ++
    ++void fix_fix (int i, char (*a)[3][5], int (*x)[__lengthof__ (*a)]);
    ++void fix_var (int i, char (*a)[3][i], int (*x)[__lengthof__ (*a)]);
    ++void fix_uns (int i, char (*a)[3][*], int (*x)[__lengthof__ (*a)]);
    ++
    ++void
    ++func (void)
    ++{
    ++  int  i3[3];
    ++  int  i5[5];
    ++  char c35[3][5];
    ++
    ++  fix_fix (5, &c35, &i3);
    ++  fix_fix (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
    ++
    ++  fix_var (5, &c35, &i3);
    ++  fix_var (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
    ++
    ++  fix_uns (5, &c35, &i3);
    ++  fix_uns (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
    ++}
    +
    + ## gcc/testsuite/gcc.dg/lengthof.c (new) ##
    +@@
    ++/* { dg-do run } */
    ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */
    ++
    ++#undef NDEBUG
    ++#include <assert.h>
    ++
    ++void
    ++array (void)
    ++{
    ++  short a[7];
    ++
    ++  assert (__lengthof__ (a) == 7);
    ++  assert (__lengthof__ (long [0]) == 0);
    ++  assert (__lengthof__ (unsigned [99]) == 99);
    ++}
    ++
    ++void
    ++vla (void)
    ++{
    ++  unsigned n;
    ++
    ++  n = 99;
    ++  assert (__lengthof__ (short [n - 10]) == 99 - 10);
    ++
    ++  int v[n / 2];
    ++  assert (__lengthof__ (v) == 99 / 2);
    ++
    ++  n = 0;
    ++  int z[n];
    ++  assert (__lengthof__ (z) == 0);
    ++}
    ++
    ++void
    ++member (void)
    ++{
    ++  struct {
    ++    int a[8];
    ++  } s;
    ++
    ++  assert (__lengthof__ (s.a) == 8);
    ++}
    ++
    ++void
    ++vla_eval (void)
    ++{
    ++  int i;
    ++
    ++  i = 7;
    ++  assert (__lengthof__ (struct {int x;}[i++]) == 7);
    ++  assert (i == 7 + 1);
    ++
    ++  int v[i];
    ++  int (*p)[i];
    ++  p = &v;
    ++  assert (__lengthof__ (*p++) == i);
    ++  assert (p - 1 == &v);
    ++}
    ++
    ++void
    ++inner_vla_noeval (void)
    ++{
    ++  int i;
    ++
    ++  i = 3;
    ++  assert (__lengthof__ (struct {int x[i++];}[3]) == 3);
    ++  assert (i == 3);
    ++}
    ++
    ++void
    ++array_noeval (void)
    ++{
    ++  long a[5];
    ++  long (*p)[__lengthof__ (a)];
    ++
    ++  p = &a;
    ++  assert (__lengthof__ (*p++) == 5);
    ++  assert (p == &a);
    ++}
    ++
    ++void
    ++matrix_zero (void)
    ++{
    ++  int i;
    ++
    ++  assert (__lengthof__ (int [0][4]) == 0);
    ++  i = 3;
    ++  assert (__lengthof__ (int [0][i]) == 0);
    ++}
    ++
    ++void
    ++matrix_fixed (void)
    ++{
    ++  int i;
    ++
    ++  assert (__lengthof__ (int [7][4]) == 7);
    ++  i = 3;
    ++  assert (__lengthof__ (int [7][i]) == 7);
    ++}
    ++
    ++void
    ++matrix_vla (void)
    ++{
    ++  int i, j;
    ++
    ++  i = 7;
    ++  assert (__lengthof__ (int [i++][4]) == 7);
    ++  assert (i == 7 + 1);
    ++
    ++  i = 9;
    ++  j = 3;
    ++  assert (__lengthof__ (int [i++][j]) == 9);
    ++  assert (i == 9 + 1);
    ++}
    ++
    ++int
    ++main (void)
    ++{
    ++  array ();
    ++  vla ();
    ++  member ();
    ++  vla_eval ();
    ++  inner_vla_noeval ();
    ++  array_noeval ();
    ++  matrix_zero ();
    ++  matrix_fixed ();
    ++  matrix_vla ();
    ++}
4:  9a691f7f208 < -:  ----------- testsuite: Add tests for __lengthof__

Comments

Alejandro Colomar Aug. 6, 2024, 11:25 p.m. UTC | #1
<david.brown@hesbynett.no> is bouncing.  FYI.  I've removed it.

On Wed, Aug 07, 2024 at 01:12:00AM GMT, Alejandro Colomar wrote:
> Hi!
> 
> This is ready for review.
> 
> v5:
> 
> -  Add changelog entries.
> -  Wording fixes in commit messages.
> -  s/sizeof/lengthof/ in comment.
> -  CC += David, Florian, Andreas  [Qing]
> -  Docs: Remove some details about future directions.  [Qing]
> -  Docs: Add examples.  [Qing]
> -  Docs: Clarify when __lengthof__ evaluates as a constant expression
>    and when it evaluates as a run-time value.  [Joseph, Qing]
> -  Tests: Use several -Wno-* flags to turn off unwanted warnings.
>    [Martin, Joseph]
> -  Tests: Merge into the same commit that adds the feature.
> -  Tests: Fix style (whitespace).
> 
> I won't paste the example program I used for development, since it's the
> same as in v4.  Check that cover letter if necessary.
> 
> When reviewing, mind that some parts of the code have been blindly
> pasted from sizeof, and might not make much sense; I didn't fully
> understand some parts.  However, it seems to behave well, and more or
> less it makes sense.  Just be careful about it.
> 
> At the bottom of this message is the range-diff against v4.
> 
> Have a lovely night!
> Alex
> 
> 
> BTW, I've tested that there are no regressions:
> 
> 	alx@debian:~/src/gnu/gcc$ find len0 -type f
> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum
> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum
> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum
> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum
> 	len0/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum
> 	len0/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum
> 	len0/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum
> 	len0/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum
> 	alx@debian:~/src/gnu/gcc$ find len1 -type f
> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum
> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum
> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum
> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum
> 	len1/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum
> 	len1/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum
> 	len1/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum
> 	len1/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum
> 	alx@debian:~/src/gnu/gcc$ cat <(cd len0; find -type f) \
> 				| while read f; do
> 					diff -u "len0/$f" "len1/$f";
> 				done;
> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06
> 	+22:22:44.514175252 +0200
> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06
> 	+23:29:53.693730123 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== gcc tests ===
> 	@@ -86504,6 +86504,15 @@
> 	 PASS: gcc.dg/large-size-array.c  (test for errors, line 19)
> 	 PASS: gcc.dg/large-size-array.c (test for excess errors)
> 	 UNSUPPORTED: gcc.dg/lazy-ptr-test.c
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 11)
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 15)
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 27)
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 42)
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 45)
> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 48)
> 	+PASS: gcc.dg/lengthof-compile.c (test for excess errors)
> 	+PASS: gcc.dg/lengthof.c (test for excess errors)
> 	+PASS: gcc.dg/lengthof.c execution test
> 	 PASS: gcc.dg/limits-width-1.c (test for excess errors)
> 	 PASS: gcc.dg/limits-width-2.c (test for excess errors)
> 	 PASS: gcc.dg/live-patching-1.c (test for excess errors)
> 	@@ -204639,7 +204648,7 @@
> 
> 			=== gcc Summary ===
> 
> 	-# of expected passes           199780
> 	+# of expected passes           199789
> 	 # of unexpected failures       31
> 	 # of unexpected successes      2
> 	 # of expected failures         1463
> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06
> 	+22:22:44.546175561 +0200
> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06
> 	+23:29:53.877731933 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== gfortran tests ===
> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06
> 	+22:22:44.462174752 +0200
> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06
> 	+23:29:53.845731618 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== objc tests ===
> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06
> 	+22:22:44.622176292 +0200
> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06
> 	+23:29:53.781730989 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== g++ tests ===
> 	--- len0/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06
> 	+22:22:46.206191541 +0200
> 	+++ len1/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06
> 	+23:29:55.573748613 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== libitm tests ===
> 	--- len0/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06
> 	+22:22:45.694186612 +0200
> 	+++ len1/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06
> 	+23:29:54.717740194 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== libgomp tests ===
> 	--- len0/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06
> 	+22:22:46.110190617 +0200
> 	+++ len1/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06
> 	+23:29:55.393746843 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:53 2024
> 	+Test run by alx on Tue Aug  6 22:49:12 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== libatomic tests ===
> 	--- len0/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06
> 	+22:22:45.998189539 +0200
> 	+++ len1/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06
> 	+23:29:55.137744325 +0200
> 	@@ -1,4 +1,4 @@
> 	-Test run by alx on Tue Aug  6 19:28:54 2024
> 	+Test run by alx on Tue Aug  6 22:49:13 2024
> 	 Native configuration is x86_64-pc-linux-gnu
> 
> 			=== libstdc++ tests ===
> 
> 
> 
> 
> 
> Alejandro Colomar (3):
>   gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
>   Merge definitions of array_type_nelts_top()
>   c: Add __lengthof__ operator
> 
>  gcc/c-family/c-common.cc                |  26 +++++
>  gcc/c-family/c-common.def               |   3 +
>  gcc/c-family/c-common.h                 |   2 +
>  gcc/c/c-decl.cc                         |  30 ++++--
>  gcc/c/c-fold.cc                         |   7 +-
>  gcc/c/c-parser.cc                       |  61 +++++++++---
>  gcc/c/c-tree.h                          |   4 +
>  gcc/c/c-typeck.cc                       | 114 ++++++++++++++++++++-
>  gcc/config/aarch64/aarch64.cc           |   2 +-
>  gcc/config/i386/i386.cc                 |   2 +-
>  gcc/cp/cp-tree.h                        |   1 -
>  gcc/cp/decl.cc                          |   2 +-
>  gcc/cp/init.cc                          |   8 +-
>  gcc/cp/lambda.cc                        |   3 +-
>  gcc/cp/operators.def                    |   1 +
>  gcc/cp/tree.cc                          |  13 ---
>  gcc/doc/extend.texi                     |  23 +++++
>  gcc/expr.cc                             |   8 +-
>  gcc/fortran/trans-array.cc              |   2 +-
>  gcc/fortran/trans-openmp.cc             |   4 +-
>  gcc/rust/backend/rust-tree.cc           |  13 ---
>  gcc/rust/backend/rust-tree.h            |   2 -
>  gcc/target.h                            |   3 +
>  gcc/testsuite/gcc.dg/lengthof-compile.c |  49 +++++++++
>  gcc/testsuite/gcc.dg/lengthof.c         | 127 ++++++++++++++++++++++++
>  gcc/tree.cc                             |  17 +++-
>  gcc/tree.h                              |   3 +-
>  27 files changed, 451 insertions(+), 79 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/lengthof-compile.c
>  create mode 100644 gcc/testsuite/gcc.dg/lengthof.c
> 
> Range-diff against v4:
> 1:  73010cb4af6 = 1:  73010cb4af6 gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
> 2:  2bb966a0a89 ! 2:  9b835478721 Merge definitions of array_type_nelts_top()
>     @@ Commit message
>          Merge definitions of array_type_nelts_top()
>      
>          There were two identical definitions, and none of them are available
>     -    where they are needed for implementing __lengthof__().  Merge them, and
>     +    where they are needed for implementing __lengthof__.  Merge them, and
>          provide the single definition in gcc/tree.{h,cc}, where it's available
>     -    for __lengthof__().
>     +    for __lengthof__, which will be added in the following commit.
>     +
>     +    gcc/ChangeLog:
>     +
>     +            * tree.h (array_type_nelts_top):
>     +            * tree.cc (array_type_nelts_top): Define function (moved from
>     +            gcc/cp/).
>     +
>     +    gcc/cp/ChangeLog:
>     +
>     +            * cp-tree.h (array_type_nelts_top):
>     +            * tree.cc (array_type_nelts_top): Remove function (move
>     +            to gcc/).
>     +
>     +    gcc/rust/ChangeLog:
>     +
>     +            * backend/rust-tree.h (array_type_nelts_top):
>     +            * backend/rust-tree.cc (array_type_nelts_top): Remove function.
>      
>          Signed-off-by: Alejandro Colomar <alx@kernel.org>
>      
> 3:  e2dbfc43b14 ! 3:  af05d01e68d c: Add __lengthof__() operator (n2529)
>     @@ Metadata
>      Author: Alejandro Colomar <alx@kernel.org>
>      
>       ## Commit message ##
>     -    c: Add __lengthof__() operator (n2529)
>     +    c: Add __lengthof__ operator
>      
>     -    This operator is similar to sizeof() but can only be applied to an
>     -    array, and returns its length (number of elements).
>     +    This operator is similar to sizeof but can only be applied to an array,
>     +    and returns its length (number of elements).
>      
>          FUTURE DIRECTIONS:
>      
>     -            We could make it work with array parameters to functions, and
>     -            somehow magically return the length designator of the array,
>     -            regardless of it being really a pointer.
>     +      We could make it work with array parameters to functions, and
>     +      somehow magically return the length designator of the array,
>     +      regardless of it being really a pointer.
>      
>     -    Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf>
>     -    Link: <https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/>
>     -    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>
>     -    Co-developed-by: Martin Uecker <uecker@tugraz.at>
>     -    Cc: Gabriel Ravier <gabravier@gmail.com>
>          Cc: Joseph Myers <josmyers@redhat.com>
>     +    Cc: Gabriel Ravier <gabravier@gmail.com>
>          Cc: Jakub Jelinek <jakub@redhat.com>
>          Cc: Kees Cook <keescook@chromium.org>
>          Cc: Qing Zhao <qing.zhao@oracle.com>
>          Cc: Jens Gustedt <jens.gustedt@inria.fr>
>     +    Cc: David Brown <david.brown@hesbynett.no>
>     +    Cc: Florian Weimer <fweimer@redhat.com>
>     +    Cc: Andreas Schwab <schwab@linux-m68k.org>
>     +
>     +    gcc/ChangeLog:
>     +
>     +            * doc/extend.texi: Document __lengthof__ operator.
>     +            * target.h (enum type_context_kind): Add __lengthof__ operator.
>     +
>     +    gcc/c-family/ChangeLog:
>     +
>     +            * c-common.h:
>     +            * c-common.def:
>     +            * c-common.cc (c_lengthof_type): Add __lengthof__ operator.
>     +
>     +    gcc/c/ChangeLog:
>     +
>     +            * c-tree.h
>     +            (c_expr_lengthof_expr, c_expr_lengthof_type):
>     +            * c-decl.cc
>     +            (start_struct, finish_struct):
>     +            (start_enum, finish_enum):
>     +            * c-parser.cc
>     +            (c_parser_sizeof_expression):
>     +            (c_parser_lengthof_expression):
>     +            (c_parser_sizeof_or_lengthof_expression):
>     +            (c_parser_unary_expression):
>     +            * c-typeck.cc
>     +            (build_external_ref):
>     +            (record_maybe_used_decl, pop_maybe_used):
>     +            (is_top_array_vla):
>     +            (c_expr_lengthof_expr, c_expr_lengthof_type):
>     +            Add __lengthof__operator.
>     +
>     +    gcc/cp/ChangeLog:
>     +
>     +            * operators.def: Add __lengthof__ operator.
>     +
>     +    gcc/testsuite/ChangeLog:
>     +
>     +            * gcc.dg/lengthof-compile.c:
>     +            * gcc.dg/lengthof.c: Add tests for __lengthof__ operator.
>     +
>     +    Link: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf
>     +    Link: https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/
>     +    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>
>     +    Co-developed-by: Martin Uecker <uecker@tugraz.at>
>          Signed-off-by: Alejandro Colomar <alx@kernel.org>
>      
>       ## gcc/c-family/c-common.cc ##
>     @@ gcc/c/c-typeck.cc: int in_alignof;
>       /* The level of nesting inside "sizeof".  */
>       int in_sizeof;
>       
>     -+/* The level of nesting inside "sizeof".  */
>     ++/* The level of nesting inside "lengthof".  */
>      +int in_lengthof;
>      +
>       /* The level of nesting inside "typeof".  */
>     @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} expression is a fu
>      +Its syntax is just like @code{sizeof}.
>      +The operand must be a complete array type.
>      +The operand is not evaluated
>     -+if the top-level length designator is an integer constant expression;
>     ++if the top-level length designator is an integer constant expression
>     ++(in this case, the operator results in a constant expression);
>      +and it is evaluated
>     -+if the top-level length designator is not an integer constant expression.
>     ++if the top-level length designator is not an integer constant expression
>     ++(in this case, the operator results in a run-time value).
>     ++For example:
>      +
>     -+XXX: Do we want to document the following?  I think so.
>     -+XXX: It would prevent users from relying on __lengthof__
>     -+XXX: for distinguishing arrays from pointers.
>     -+XXX: I don't want users to complain in the future
>     -+XXX: if this doesn't report errors on function parameters anymore
>     -+XXX: and that breaks their assumptions.
>     -+In the future,
>     -+it might also accept a function parameter with array notation,
>     -+an incomplete array whose length is specified by other means,
>     -+such as attributes,
>     -+or other similar cases.
>     ++@smallexample
>     ++__lengthof__ (int [7][n++]);  // constexpr
>     ++__lengthof__ (int [n++][7]);  // run-time value
>     ++@end smallexample
>      +
>       @node Inline
>       @section An Inline Function is As Fast As a Macro
>     @@ gcc/target.h: enum type_context_kind {
>         /* Creating objects of type T with static storage duration.  */
>         TCTX_STATIC_STORAGE,
>       
>     +
>     + ## gcc/testsuite/gcc.dg/lengthof-compile.c (new) ##
>     +@@
>     ++/* { dg-do compile } */
>     ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */
>     ++
>     ++extern int x[];
>     ++
>     ++void
>     ++incomplete (int p[])
>     ++{
>     ++  unsigned n;
>     ++
>     ++  n = __lengthof__ (x);  /* { dg-error "incomplete" } */
>     ++
>     ++  /* We want to support the following one in the future,
>     ++     but for now it should fail.  */
>     ++  n = __lengthof__ (p);  /* { dg-error "invalid" } */
>     ++}
>     ++
>     ++void
>     ++fam (void)
>     ++{
>     ++  struct {
>     ++    int x;
>     ++    int fam[];
>     ++  } s;
>     ++  unsigned n;
>     ++
>     ++  n = __lengthof__ (s.fam); /* { dg-error "incomplete" } */
>     ++}
>     ++
>     ++void fix_fix (int i, char (*a)[3][5], int (*x)[__lengthof__ (*a)]);
>     ++void fix_var (int i, char (*a)[3][i], int (*x)[__lengthof__ (*a)]);
>     ++void fix_uns (int i, char (*a)[3][*], int (*x)[__lengthof__ (*a)]);
>     ++
>     ++void
>     ++func (void)
>     ++{
>     ++  int  i3[3];
>     ++  int  i5[5];
>     ++  char c35[3][5];
>     ++
>     ++  fix_fix (5, &c35, &i3);
>     ++  fix_fix (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
>     ++
>     ++  fix_var (5, &c35, &i3);
>     ++  fix_var (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
>     ++
>     ++  fix_uns (5, &c35, &i3);
>     ++  fix_uns (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
>     ++}
>     +
>     + ## gcc/testsuite/gcc.dg/lengthof.c (new) ##
>     +@@
>     ++/* { dg-do run } */
>     ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */
>     ++
>     ++#undef NDEBUG
>     ++#include <assert.h>
>     ++
>     ++void
>     ++array (void)
>     ++{
>     ++  short a[7];
>     ++
>     ++  assert (__lengthof__ (a) == 7);
>     ++  assert (__lengthof__ (long [0]) == 0);
>     ++  assert (__lengthof__ (unsigned [99]) == 99);
>     ++}
>     ++
>     ++void
>     ++vla (void)
>     ++{
>     ++  unsigned n;
>     ++
>     ++  n = 99;
>     ++  assert (__lengthof__ (short [n - 10]) == 99 - 10);
>     ++
>     ++  int v[n / 2];
>     ++  assert (__lengthof__ (v) == 99 / 2);
>     ++
>     ++  n = 0;
>     ++  int z[n];
>     ++  assert (__lengthof__ (z) == 0);
>     ++}
>     ++
>     ++void
>     ++member (void)
>     ++{
>     ++  struct {
>     ++    int a[8];
>     ++  } s;
>     ++
>     ++  assert (__lengthof__ (s.a) == 8);
>     ++}
>     ++
>     ++void
>     ++vla_eval (void)
>     ++{
>     ++  int i;
>     ++
>     ++  i = 7;
>     ++  assert (__lengthof__ (struct {int x;}[i++]) == 7);
>     ++  assert (i == 7 + 1);
>     ++
>     ++  int v[i];
>     ++  int (*p)[i];
>     ++  p = &v;
>     ++  assert (__lengthof__ (*p++) == i);
>     ++  assert (p - 1 == &v);
>     ++}
>     ++
>     ++void
>     ++inner_vla_noeval (void)
>     ++{
>     ++  int i;
>     ++
>     ++  i = 3;
>     ++  assert (__lengthof__ (struct {int x[i++];}[3]) == 3);
>     ++  assert (i == 3);
>     ++}
>     ++
>     ++void
>     ++array_noeval (void)
>     ++{
>     ++  long a[5];
>     ++  long (*p)[__lengthof__ (a)];
>     ++
>     ++  p = &a;
>     ++  assert (__lengthof__ (*p++) == 5);
>     ++  assert (p == &a);
>     ++}
>     ++
>     ++void
>     ++matrix_zero (void)
>     ++{
>     ++  int i;
>     ++
>     ++  assert (__lengthof__ (int [0][4]) == 0);
>     ++  i = 3;
>     ++  assert (__lengthof__ (int [0][i]) == 0);
>     ++}
>     ++
>     ++void
>     ++matrix_fixed (void)
>     ++{
>     ++  int i;
>     ++
>     ++  assert (__lengthof__ (int [7][4]) == 7);
>     ++  i = 3;
>     ++  assert (__lengthof__ (int [7][i]) == 7);
>     ++}
>     ++
>     ++void
>     ++matrix_vla (void)
>     ++{
>     ++  int i, j;
>     ++
>     ++  i = 7;
>     ++  assert (__lengthof__ (int [i++][4]) == 7);
>     ++  assert (i == 7 + 1);
>     ++
>     ++  i = 9;
>     ++  j = 3;
>     ++  assert (__lengthof__ (int [i++][j]) == 9);
>     ++  assert (i == 9 + 1);
>     ++}
>     ++
>     ++int
>     ++main (void)
>     ++{
>     ++  array ();
>     ++  vla ();
>     ++  member ();
>     ++  vla_eval ();
>     ++  inner_vla_noeval ();
>     ++  array_noeval ();
>     ++  matrix_zero ();
>     ++  matrix_fixed ();
>     ++  matrix_vla ();
>     ++}
> 4:  9a691f7f208 < -:  ----------- testsuite: Add tests for __lengthof__
> -- 
> 2.45.2
>
David Brown Aug. 7, 2024, 8:11 a.m. UTC | #2
Hi,The address david.brown@hesbynett.no is not bouncing.  Its my email address, and I'm getting the emails in this discussion just fine.However, I don't think I have anything to contribute here, so I don't object to being removed from the discussion. I am not a gcc developer, but as a long term user I  occasionally post on the developer mailing list. I don't remember having posted about a potential __lengthof__ operator, but it is certainly possible. On behalf of all gcc users, thank you for your efforts in working to improve gcc, no matter how this proposal turns out.Mvh.,David Browndavid.brown@hesbynett.no
-------- Original message --------From: Alejandro Colomar <alx@kernel.org> Date: 07/08/2024  01:26  (GMT+01:00) To: gcc-patches@gcc.gnu.org Cc: Martin Uecker <uecker@tugraz.at>, Xavier Del Campo Romero <xavi.dcr@tutanota.com>, Joseph Myers <josmyers@redhat.com>, Gabriel Ravier <gabravier@gmail.com>, Jakub Jelinek <jakub@redhat.com>, Kees Cook <keescook@chromium.org>, Qing Zhao <qing.zhao@oracle.com>, Jens Gustedt <jens.gustedt@inria.fr>, David Brown <david.brown@hesbynett.no>, Florian Weimer <fweimer@redhat.com>, Andreas Schwab <schwab@linux-m68k.org> Subject: Re: [PATCH v5 0/3] c: Add __lengthof__ operator <david.brown@hesbynett.no> is bouncing.  FYI.  I've removed it.On Wed, Aug 07, 2024 at 01:12:00AM GMT, Alejandro Colomar wrote:> Hi!> > This is ready for review.> > v5:> > -  Add changelog entries.> -  Wording fixes in commit messages.> -  s/sizeof/lengthof/ in comment.> -  CC += David, Florian, Andreas  [Qing]> -  Docs: Remove some details about future directions.  [Qing]> -  Docs: Add examples.  [Qing]> -  Docs: Clarify when __lengthof__ evaluates as a constant expression>    and when it evaluates as a run-time value.  [Joseph, Qing]> -  Tests: Use several -Wno-* flags to turn off unwanted warnings.>    [Martin, Joseph]> -  Tests: Merge into the same commit that adds the feature.> -  Tests: Fix style (whitespace).> > I won't paste the example program I used for development, since it's the> same as in v4.  Check that cover letter if necessary.> > When reviewing, mind that some parts of the code have been blindly> pasted from sizeof, and might not make much sense; I didn't fully> understand some parts.  However, it seems to behave well, and more or> less it makes sense.  Just be careful about it.> > At the bottom of this message is the range-diff against v4.> > Have a lovely night!> Alex> > > BTW, I've tested that there are no regressions:> > 	alx@debian:~/src/gnu/gcc$ find len0 -type f> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum> 	len0/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum> 	len0/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum> 	len0/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum> 	len0/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum> 	len0/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum> 	alx@debian:~/src/gnu/gcc$ find len1 -type f> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum> 	len1/host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum> 	len1/x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum> 	len1/x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum> 	len1/x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum> 	len1/x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum> 	alx@debian:~/src/gnu/gcc$ cat <(cd len0; find -type f) \> 				| while read f; do> 					diff -u "len0/$f" "len1/$f";> 				done;> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06> 	+22:22:44.514175252 +0200> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gcc/gcc.sum   2024-08-06> 	+23:29:53.693730123 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== gcc tests ===> 	@@ -86504,6 +86504,15 @@> 	 PASS: gcc.dg/large-size-array.c  (test for errors, line 19)> 	 PASS: gcc.dg/large-size-array.c (test for excess errors)> 	 UNSUPPORTED: gcc.dg/lazy-ptr-test.c> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 11)> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 15)> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 27)> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 42)> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 45)> 	+PASS: gcc.dg/lengthof-compile.c  (test for errors, line 48)> 	+PASS: gcc.dg/lengthof-compile.c (test for excess errors)> 	+PASS: gcc.dg/lengthof.c (test for excess errors)> 	+PASS: gcc.dg/lengthof.c execution test> 	 PASS: gcc.dg/limits-width-1.c (test for excess errors)> 	 PASS: gcc.dg/limits-width-2.c (test for excess errors)> 	 PASS: gcc.dg/live-patching-1.c (test for excess errors)> 	@@ -204639,7 +204648,7 @@> > 			=== gcc Summary ===> > 	-# of expected passes           199780> 	+# of expected passes           199789> 	 # of unexpected failures       31> 	 # of unexpected successes      2> 	 # of expected failures         1463> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06> 	+22:22:44.546175561 +0200> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/gfortran/gfortran.sum 2024-08-06> 	+23:29:53.877731933 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== gfortran tests ===> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06> 	+22:22:44.462174752 +0200> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/objc/objc.sum 2024-08-06> 	+23:29:53.845731618 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== objc tests ===> 	--- len0/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06> 	+22:22:44.622176292 +0200> 	+++ len1/./host-x86_64-pc-linux-gnu/gcc/testsuite/g++/g++.sum   2024-08-06> 	+23:29:53.781730989 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== g++ tests ===> 	--- len0/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06> 	+22:22:46.206191541 +0200> 	+++ len1/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum      2024-08-06> 	+23:29:55.573748613 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== libitm tests ===> 	--- len0/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06> 	+22:22:45.694186612 +0200> 	+++ len1/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum    2024-08-06> 	+23:29:54.717740194 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== libgomp tests ===> 	--- len0/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06> 	+22:22:46.110190617 +0200> 	+++ len1/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum        2024-08-06> 	+23:29:55.393746843 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:53 2024> 	+Test run by alx on Tue Aug  6 22:49:12 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== libatomic tests ===> 	--- len0/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06> 	+22:22:45.998189539 +0200> 	+++ len1/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum     2024-08-06> 	+23:29:55.137744325 +0200> 	@@ -1,4 +1,4 @@> 	-Test run by alx on Tue Aug  6 19:28:54 2024> 	+Test run by alx on Tue Aug  6 22:49:13 2024> 	 Native configuration is x86_64-pc-linux-gnu> > 			=== libstdc++ tests ===> > > > > > Alejandro Colomar (3):>   gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()>   Merge definitions of array_type_nelts_top()>   c: Add __lengthof__ operator> >  gcc/c-family/c-common.cc                |  26 +++++>  gcc/c-family/c-common.def               |   3 +>  gcc/c-family/c-common.h                 |   2 +>  gcc/c/c-decl.cc                         |  30 ++++-->  gcc/c/c-fold.cc                         |   7 +->  gcc/c/c-parser.cc                       |  61 +++++++++--->  gcc/c/c-tree.h                          |   4 +>  gcc/c/c-typeck.cc                       | 114 ++++++++++++++++++++->  gcc/config/aarch64/aarch64.cc           |   2 +->  gcc/config/i386/i386.cc                 |   2 +->  gcc/cp/cp-tree.h                        |   1 ->  gcc/cp/decl.cc                          |   2 +->  gcc/cp/init.cc                          |   8 +->  gcc/cp/lambda.cc                        |   3 +->  gcc/cp/operators.def                    |   1 +>  gcc/cp/tree.cc                          |  13 --->  gcc/doc/extend.texi                     |  23 +++++>  gcc/expr.cc                             |   8 +->  gcc/fortran/trans-array.cc              |   2 +->  gcc/fortran/trans-openmp.cc             |   4 +->  gcc/rust/backend/rust-tree.cc           |  13 --->  gcc/rust/backend/rust-tree.h            |   2 ->  gcc/target.h                            |   3 +>  gcc/testsuite/gcc.dg/lengthof-compile.c |  49 +++++++++>  gcc/testsuite/gcc.dg/lengthof.c         | 127 ++++++++++++++++++++++++>  gcc/tree.cc                             |  17 +++->  gcc/tree.h                              |   3 +->  27 files changed, 451 insertions(+), 79 deletions(-)>  create mode 100644 gcc/testsuite/gcc.dg/lengthof-compile.c>  create mode 100644 gcc/testsuite/gcc.dg/lengthof.c> > Range-diff against v4:> 1:  73010cb4af6 = 1:  73010cb4af6 gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()> 2:  2bb966a0a89 ! 2:  9b835478721 Merge definitions of array_type_nelts_top()>     @@ Commit message>          Merge definitions of array_type_nelts_top()>      >          There were two identical definitions, and none of them are available>     -    where they are needed for implementing __lengthof__().  Merge them, and>     +    where they are needed for implementing __lengthof__.  Merge them, and>          provide the single definition in gcc/tree.{h,cc}, where it's available>     -    for __lengthof__().>     +    for __lengthof__, which will be added in the following commit.>     +>     +    gcc/ChangeLog:>     +>     +            * tree.h (array_type_nelts_top):>     +            * tree.cc (array_type_nelts_top): Define function (moved from>     +            gcc/cp/).>     +>     +    gcc/cp/ChangeLog:>     +>     +            * cp-tree.h (array_type_nelts_top):>     +            * tree.cc (array_type_nelts_top): Remove function (move>     +            to gcc/).>     +>     +    gcc/rust/ChangeLog:>     +>     +            * backend/rust-tree.h (array_type_nelts_top):>     +            * backend/rust-tree.cc (array_type_nelts_top): Remove function.>      >          Signed-off-by: Alejandro Colomar <alx@kernel.org>>      > 3:  e2dbfc43b14 ! 3:  af05d01e68d c: Add __lengthof__() operator (n2529)>     @@ Metadata>      Author: Alejandro Colomar <alx@kernel.org>>      >       ## Commit message ##>     -    c: Add __lengthof__() operator (n2529)>     +    c: Add __lengthof__ operator>      >     -    This operator is similar to sizeof() but can only be applied to an>     -    array, and returns its length (number of elements).>     +    This operator is similar to sizeof but can only be applied to an array,>     +    and returns its length (number of elements).>      >          FUTURE DIRECTIONS:>      >     -            We could make it work with array parameters to functions, and>     -            somehow magically return the length designator of the array,>     -            regardless of it being really a pointer.>     +      We could make it work with array parameters to functions, and>     +      somehow magically return the length designator of the array,>     +      regardless of it being really a pointer.>      >     -    Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf>>     -    Link: <https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/>>     -    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>>     -    Co-developed-by: Martin Uecker <uecker@tugraz.at>>     -    Cc: Gabriel Ravier <gabravier@gmail.com>>          Cc: Joseph Myers <josmyers@redhat.com>>     +    Cc: Gabriel Ravier <gabravier@gmail.com>>          Cc: Jakub Jelinek <jakub@redhat.com>>          Cc: Kees Cook <keescook@chromium.org>>          Cc: Qing Zhao <qing.zhao@oracle.com>>          Cc: Jens Gustedt <jens.gustedt@inria.fr>>     +    Cc: David Brown <david.brown@hesbynett.no>>     +    Cc: Florian Weimer <fweimer@redhat.com>>     +    Cc: Andreas Schwab <schwab@linux-m68k.org>>     +>     +    gcc/ChangeLog:>     +>     +            * doc/extend.texi: Document __lengthof__ operator.>     +            * target.h (enum type_context_kind): Add __lengthof__ operator.>     +>     +    gcc/c-family/ChangeLog:>     +>     +            * c-common.h:>     +            * c-common.def:>     +            * c-common.cc (c_lengthof_type): Add __lengthof__ operator.>     +>     +    gcc/c/ChangeLog:>     +>     +            * c-tree.h>     +            (c_expr_lengthof_expr, c_expr_lengthof_type):>     +            * c-decl.cc>     +            (start_struct, finish_struct):>     +            (start_enum, finish_enum):>     +            * c-parser.cc>     +            (c_parser_sizeof_expression):>     +            (c_parser_lengthof_expression):>     +            (c_parser_sizeof_or_lengthof_expression):>     +            (c_parser_unary_expression):>     +            * c-typeck.cc>     +            (build_external_ref):>     +            (record_maybe_used_decl, pop_maybe_used):>     +            (is_top_array_vla):>     +            (c_expr_lengthof_expr, c_expr_lengthof_type):>     +            Add __lengthof__operator.>     +>     +    gcc/cp/ChangeLog:>     +>     +            * operators.def: Add __lengthof__ operator.>     +>     +    gcc/testsuite/ChangeLog:>     +>     +            * gcc.dg/lengthof-compile.c:>     +            * gcc.dg/lengthof.c: Add tests for __lengthof__ operator.>     +>     +    Link: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf>     +    Link: https://inbox.sourceware.org/gcc/M8S4oQy--3-2@tutanota.com/T/>     +    Suggested-by: Xavier Del Campo Romero <xavi.dcr@tutanota.com>>     +    Co-developed-by: Martin Uecker <uecker@tugraz.at>>          Signed-off-by: Alejandro Colomar <alx@kernel.org>>      >       ## gcc/c-family/c-common.cc ##>     @@ gcc/c/c-typeck.cc: int in_alignof;>       /* The level of nesting inside "sizeof".  */>       int in_sizeof;>       >     -+/* The level of nesting inside "sizeof".  */>     ++/* The level of nesting inside "lengthof".  */>      +int in_lengthof;>      +>       /* The level of nesting inside "typeof".  */>     @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} expression is a fu>      +Its syntax is just like @code{sizeof}.>      +The operand must be a complete array type.>      +The operand is not evaluated>     -+if the top-level length designator is an integer constant expression;>     ++if the top-level length designator is an integer constant expression>     ++(in this case, the operator results in a constant expression);>      +and it is evaluated>     -+if the top-level length designator is not an integer constant expression.>     ++if the top-level length designator is not an integer constant expression>     ++(in this case, the operator results in a run-time value).>     ++For example:>      +>     -+XXX: Do we want to document the following?  I think so.>     -+XXX: It would prevent users from relying on __lengthof__>     -+XXX: for distinguishing arrays from pointers.>     -+XXX: I don't want users to complain in the future>     -+XXX: if this doesn't report errors on function parameters anymore>     -+XXX: and that breaks their assumptions.>     -+In the future,>     -+it might also accept a function parameter with array notation,>     -+an incomplete array whose length is specified by other means,>     -+such as attributes,>     -+or other similar cases.>     ++@smallexample>     ++__lengthof__ (int [7][n++]);  // constexpr>     ++__lengthof__ (int [n++][7]);  // run-time value>     ++@end smallexample>      +>       @node Inline>       @section An Inline Function is As Fast As a Macro>     @@ gcc/target.h: enum type_context_kind {>         /* Creating objects of type T with static storage duration.  */>         TCTX_STATIC_STORAGE,>       >     +>     + ## gcc/testsuite/gcc.dg/lengthof-compile.c (new) ##>     +@@>     ++/* { dg-do compile } */>     ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */>     ++>     ++extern int x[];>     ++>     ++void>     ++incomplete (int p[])>     ++{>     ++  unsigned n;>     ++>     ++  n = __lengthof__ (x);  /* { dg-error "incomplete" } */>     ++>     ++  /* We want to support the following one in the future,>     ++     but for now it should fail.  */>     ++  n = __lengthof__ (p);  /* { dg-error "invalid" } */>     ++}>     ++>     ++void>     ++fam (void)>     ++{>     ++  struct {>     ++    int x;>     ++    int fam[];>     ++  } s;>     ++  unsigned n;>     ++>     ++  n = __lengthof__ (s.fam); /* { dg-error "incomplete" } */>     ++}>     ++>     ++void fix_fix (int i, char (*a)[3][5], int (*x)[__lengthof__ (*a)]);>     ++void fix_var (int i, char (*a)[3][i], int (*x)[__lengthof__ (*a)]);>     ++void fix_uns (int i, char (*a)[3][*], int (*x)[__lengthof__ (*a)]);>     ++>     ++void>     ++func (void)>     ++{>     ++  int  i3[3];>     ++  int  i5[5];>     ++  char c35[3][5];>     ++>     ++  fix_fix (5, &c35, &i3);>     ++  fix_fix (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */>     ++>     ++  fix_var (5, &c35, &i3);>     ++  fix_var (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */>     ++>     ++  fix_uns (5, &c35, &i3);>     ++  fix_uns (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */>     ++}>     +>     + ## gcc/testsuite/gcc.dg/lengthof.c (new) ##>     +@@>     ++/* { dg-do run } */>     ++/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */>     ++>     ++#undef NDEBUG>     ++#include <assert.h>>     ++>     ++void>     ++array (void)>     ++{>     ++  short a[7];>     ++>     ++  assert (__lengthof__ (a) == 7);>     ++  assert (__lengthof__ (long [0]) == 0);>     ++  assert (__lengthof__ (unsigned [99]) == 99);>     ++}>     ++>     ++void>     ++vla (void)>     ++{>     ++  unsigned n;>     ++>     ++  n = 99;>     ++  assert (__lengthof__ (short [n - 10]) == 99 - 10);>     ++>     ++  int v[n / 2];>     ++  assert (__lengthof__ (v) == 99 / 2);>     ++>     ++  n = 0;>     ++  int z[n];>     ++  assert (__lengthof__ (z) == 0);>     ++}>     ++>     ++void>     ++member (void)>     ++{>     ++  struct {>     ++    int a[8];>     ++  } s;>     ++>     ++  assert (__lengthof__ (s.a) == 8);>     ++}>     ++>     ++void>     ++vla_eval (void)>     ++{>     ++  int i;>     ++>     ++  i = 7;>     ++  assert (__lengthof__ (struct {int x;}[i++]) == 7);>     ++  assert (i == 7 + 1);>     ++>     ++  int v[i];>     ++  int (*p)[i];>     ++  p = &v;>     ++  assert (__lengthof__ (*p++) == i);>     ++  assert (p - 1 == &v);>     ++}>     ++>     ++void>     ++inner_vla_noeval (void)>     ++{>     ++  int i;>     ++>     ++  i = 3;>     ++  assert (__lengthof__ (struct {int x[i++];}[3]) == 3);>     ++  assert (i == 3);>     ++}>     ++>     ++void>     ++array_noeval (void)>     ++{>     ++  long a[5];>     ++  long (*p)[__lengthof__ (a)];>     ++>     ++  p = &a;>     ++  assert (__lengthof__ (*p++) == 5);>     ++  assert (p == &a);>     ++}>     ++>     ++void>     ++matrix_zero (void)>     ++{>     ++  int i;>     ++>     ++  assert (__lengthof__ (int [0][4]) == 0);>     ++  i = 3;>     ++  assert (__lengthof__ (int [0][i]) == 0);>     ++}>     ++>     ++void>     ++matrix_fixed (void)>     ++{>     ++  int i;>     ++>     ++  assert (__lengthof__ (int [7][4]) == 7);>     ++  i = 3;>     ++  assert (__lengthof__ (int [7][i]) == 7);>     ++}>     ++>     ++void>     ++matrix_vla (void)>     ++{>     ++  int i, j;>     ++>     ++  i = 7;>     ++  assert (__lengthof__ (int [i++][4]) == 7);>     ++  assert (i == 7 + 1);>     ++>     ++  i = 9;>     ++  j = 3;>     ++  assert (__lengthof__ (int [i++][j]) == 9);>     ++  assert (i == 9 + 1);>     ++}>     ++>     ++int>     ++main (void)>     ++{>     ++  array ();>     ++  vla ();>     ++  member ();>     ++  vla_eval ();>     ++  inner_vla_noeval ();>     ++  array_noeval ();>     ++  matrix_zero ();>     ++  matrix_fixed ();>     ++  matrix_vla ();>     ++}> 4:  9a691f7f208 < -:  ----------- testsuite: Add tests for __lengthof__> -- > 2.45.2> -- <https://www.alejandro-colomar.es/>
Alejandro Colomar Aug. 7, 2024, 8:30 a.m. UTC | #3
Hi David,

On Wed, Aug 07, 2024 at 10:11:12AM GMT, david.brown wrote:
> Hi,The address david.brown@hesbynett.no is not bouncing.  Its my email
> address, and I'm getting the emails in this discussion just fine.

Ahh, sorry, I didn't read the bounce notification properly; the address
is indeed reachable, but it rejected some message as spam (and notified
me, which is the first time I see that happen:).

(At the bottom I pasted part of the report I received.)

Thanks for replying!

>  However, I don't think I have anything to contribute here, so I don't
> object to being removed from the discussion. I am not a gcc developer,
> but as a long term user I  occasionally post on the developer mailing
> list. I don't remember having posted about a potential __lengthof__
> operator, but it is certainly possible.

You did post 4 years ago:
<https://inbox.sourceware.org/gcc/23d3556f-6829-789d-49ba-0551dfa4cfd5@hesbynett.no/>
<https://inbox.sourceware.org/gcc/6f8be1ed-4d76-dbf3-f19a-e9105f7450d4@hesbynett.no/>

I will keep you on CC, unless you expressely want to be remvoved.  ;)

> On behalf of all gcc users, thank you for your efforts in working to
> improve gcc, no matter how this proposal turns out.

Thanks!

> Mvh.,David Browndavid.brown@hesbynett.no

Have a lovely day!
Alex

---

This is the mail system at host dfw.source.kernel.org.

I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to postmaster.

If you do so, please include this problem report. You can
delete your own text from the attached returned message.

                   The mail system

<david.brown@hesbynett.no>: host spam01.hesbynett.no[81.29.32.152] said: 550
    5.7.1 Rejected by spam filter (4cb5907b-5449-11ef-98be-506b8dfa0e58) (in
    reply to end of DATA command)
Alejandro Colomar Aug. 8, 2024, 10:41 p.m. UTC | #4
Hi!

While running `make check -j24`, I've seen an internal compiler error.
I've tried to reproduce it, but it only triggered once that time.

This is the only log I've been able to collect.  I hope it helps.

	lto1: internal compiler error: in lto_read_decls, at lto/lto-common.cc:1970
	0x23234de internal_error(char const*, ...)
		../.././gcc/diagnostic-global-context.cc:491
	0x923807 fancy_abort(char const*, int, char const*)
		../.././gcc/diagnostic.cc:1772
	0x71d494 lto_read_decls
		../.././gcc/lto/lto-common.cc:1970
	0x97b959 lto_file_finalize
		../.././gcc/lto/lto-common.cc:2299
	0x97b959 lto_create_files_from_ids
		../.././gcc/lto/lto-common.cc:2309
	0x97b959 lto_file_read
		../.././gcc/lto/lto-common.cc:2364
	0x97b959 read_cgraph_and_symbols(unsigned int, char const**)
		../.././gcc/lto/lto-common.cc:2812
	0x95c012 lto_main()
		../.././gcc/lto/lto.cc:658
	Please submit a full bug report, with preprocessed source (by using -freport-bug).
	Please include the complete backtrace with any bug report.
	See <https://gcc.gnu.org/bugs/> for instructions.
	lto-wrapper: fatal error: /home/alx/src/gnu/gcc/len/host-x86_64-pc-linux-gnu/gcc/xgcc returned 1 exit status
	compilation terminated.
	/usr/bin/ld: error: lto-wrapper failed
	collect2: error: ld returned 1 exit status

To clarify, this was run after running a slightly-modified version of
this patch set, and nothing else.  In theory, I think, I haven't touched
anything that should cause an lto ICE.  I've rebased on top of git HEAD
earlier today, and have applied the changes shown below.

I assume I'm causing it somehow, with my patches, but maybe it's not.
Is git HEAD known to be in a bad state at the moment regarding lto?


The range-diff below is what will be v6, which I was planning to send
today, but haven't because of this ICE.

Cheers,
Alex


$ git range-diff 73010cb4af6^..af05d01e68d gnu/master..HEAD
1:  73010cb4af6 = 1:  8b68e250503 gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
2:  9b835478721 = 2:  21433097103 Merge definitions of array_type_nelts_top()
3:  af05d01e68d ! 3:  e8867c0fef4 c: Add __lengthof__ operator
    @@ Commit message
     
         FUTURE DIRECTIONS:
     
    -      We could make it work with array parameters to functions, and
    -      somehow magically return the length designator of the array,
    -      regardless of it being really a pointer.
    +    -  We should make it work with array parameters to functions,
    +       and somehow magically return the length designator of the array,
    +       regardless of it being really a pointer.
    +
    +    -  Fix support for [0].
     
         Cc: Joseph Myers <josmyers@redhat.com>
         Cc: Gabriel Ravier <gabravier@gmail.com>
    @@ Commit message
         gcc/testsuite/ChangeLog:
     
                 * gcc.dg/lengthof-compile.c:
    +            * gcc.dg/lengthof-vla.c:
                 * gcc.dg/lengthof.c: Add tests for __lengthof__ operator.
     
         Link: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.pdf
    @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct c_type_name *t)
     +static bool
     +is_top_array_vla (tree type)
     +{
    -+  bool zero, var;
    ++  bool zero, star, var;
     +  tree d;
     +
     +  if (TREE_CODE (type) != ARRAY_TYPE)
    @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct c_type_name *t)
     +
     +  d = TYPE_DOMAIN (type);
     +  zero = !TYPE_MAX_VALUE (d);
    -+  var = (!zero
    -+   && (TREE_CODE (TYPE_MIN_VALUE (d)) != INTEGER_CST
    -+       || TREE_CODE (TYPE_MAX_VALUE (d)) != INTEGER_CST));
    -+  var = var || (zero && C_TYPE_VARIABLE_SIZE (type));
    ++  star = (zero && C_TYPE_VARIABLE_SIZE (type));
    ++  if (star)
    ++    return true;
    ++  if (zero)
    ++    return false;
    ++
    ++  var = (TREE_CODE (TYPE_MIN_VALUE (d)) != INTEGER_CST
    ++   || TREE_CODE (TYPE_MAX_VALUE (d)) != INTEGER_CST);
     +  return var;
     +}
     +
    @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} expression is a fu
     +
     +The keyword @code{__lengthof__} determines the length of an array operand,
     +that is, the number of elements in the array.
    -+Its syntax is just like @code{sizeof}.
    -+The operand must be a complete array type.
    ++Its syntax is similar to @code{sizeof}.
    ++The operand must be a complete array type or an expression of that type.
    ++For example:
    ++
    ++@smallexample
    ++int a[n];
    ++__lengthof__ (a);  // returns n
    ++__lengthof__ (int [7][3]);  // returns 7
    ++@end smallexample
    ++
     +The operand is not evaluated
     +if the top-level length designator is an integer constant expression
    -+(in this case, the operator results in a constant expression);
    ++(in this case, the operator results in an integer constant expression);
     +and it is evaluated
     +if the top-level length designator is not an integer constant expression
     +(in this case, the operator results in a run-time value).
     +For example:
     +
     +@smallexample
    -+__lengthof__ (int [7][n++]);  // constexpr
    -+__lengthof__ (int [n++][7]);  // run-time value
    ++__lengthof__ (int [7][n++]);  // integer constant expression
    ++__lengthof__ (int [n++][7]);  // run-time value; n++ is evaluated
     +@end smallexample
     +
      @node Inline
    @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new)
     +
     +extern int x[];
     +
    ++static int w[] = {1, 2, 3};
    ++
    ++static int z[0];
    ++static int y[__lengthof__(z)];
    ++
    ++void
    ++automatic(void)
    ++{
    ++  __lengthof__ (w);
    ++}
    ++
     +void
     +incomplete (int p[])
     +{
    -+  unsigned n;
    -+
    -+  n = __lengthof__ (x);  /* { dg-error "incomplete" } */
    ++  __lengthof__ (x);  /* { dg-error "incomplete" } */
     +
     +  /* We want to support the following one in the future,
     +     but for now it should fail.  */
    -+  n = __lengthof__ (p);  /* { dg-error "invalid" } */
    ++  __lengthof__ (p);  /* { dg-error "invalid" } */
     +}
     +
     +void
    @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new)
     +    int x;
     +    int fam[];
     +  } s;
    -+  unsigned n;
     +
    -+  n = __lengthof__ (s.fam); /* { dg-error "incomplete" } */
    ++  __lengthof__ (s.fam); /* { dg-error "incomplete" } */
     +}
     +
     +void fix_fix (int i, char (*a)[3][5], int (*x)[__lengthof__ (*a)]);
    @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new)
     +  fix_uns (5, &c35, &i3);
     +  fix_uns (5, &c35, &i5); /* { dg-error "incompatible-pointer-types" } */
     +}
    ++
    ++void
    ++non_arr(void)
    ++{
    ++  int x;
    ++  int *p;
    ++  struct s {
    ++    int x[3];
    ++  } s;
    ++
    ++  __lengthof__ (x); /* { dg-error "invalid" } */
    ++  __lengthof__ (int); /* { dg-error "invalid" } */
    ++  __lengthof__ (s); /* { dg-error "invalid" } */
    ++  __lengthof__ (struct s); /* { dg-error "invalid" } */
    ++  __lengthof__ (&x); /* { dg-error "invalid" } */
    ++  __lengthof__ (p); /* { dg-error "invalid" } */
    ++  __lengthof__ (int *); /* { dg-error "invalid" } */
    ++  __lengthof__ (&s.x); /* { dg-error "invalid" } */
    ++  __lengthof__ (int (*)[3]); /* { dg-error "invalid" } */
    ++}
    ++
    ++static int f1(), f2();
    ++int a[10][10];
    ++int n;
    ++
    ++void
    ++syms(void)
    ++{
    ++  int b[n][n];
    ++
    ++  __lengthof__ (a[f1()]);
    ++  __lengthof__ (b[f2()]); /* { dg-warning "never defined" } */
    ++}
    ++
    ++void
    ++no_parens(void)
    ++{
    ++  __lengthof__ a;
    ++  __lengthof__ *a;
    ++  __lengthof__ (int [3]) {};
    ++
    ++  __lengthof__ int [3]; /* { dg-error "expected expression before" } */
    ++}
    ++
    ++void
    ++const_expr(void)
    ++{
    ++  int n = 7;
    ++
    ++  _Static_assert (__lengthof__ (int [3][n]) == 3);
    ++  _Static_assert (__lengthof__ (int [n][3]) == 7); /* { dg-warning "not constant"} */
    ++  _Static_assert (__lengthof__ (int [0][3]) == 0);
    ++  _Static_assert (__lengthof__ (int [0]) == 0);
    ++
    ++  /* FIXME: lengthog(int [0][n]) should result in a constant expression.  */
    ++  _Static_assert (__lengthof__ (int [0][n]) == 0); /* { dg-warning "not constant"} */
    ++}
    +
    + ## gcc/testsuite/gcc.dg/lengthof-vla.c (new) ##
    +@@
    ++/* { dg-do compile } */
    ++/* { dg-options "-Wno-pedantic -Wvla-parameter" } */
    ++
    ++void fix_fix (int i,
    ++        char (*a)[3][5],
    ++        int (*x)[__lengthof__ (*a)]);
    ++void fix_var (int i,
    ++        char (*a)[3][i], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]);
    ++void fix_uns (int i,
    ++        char (*a)[3][*],
    ++        int (*x)[__lengthof__ (*a)]);
    ++
    ++void zro_fix (int i,
    ++        char (*a)[0][5],
    ++        int (*x)[__lengthof__ (*a)]);
    ++void zro_var (int i,
    ++        char (*a)[0][i], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]);
    ++void zro_uns (int i,
    ++        char (*a)[0][*],
    ++        int (*x)[__lengthof__ (*a)]);
    ++
    ++void var_fix (int i,
    ++        char (*a)[i][5], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
    ++void var_var (int i,
    ++        char (*a)[i][i], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
    ++void var_uns (int i,
    ++        char (*a)[i][*], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
    ++
    ++void uns_fix (int i,
    ++        char (*a)[*][5],
    ++        int (*x)[__lengthof__ (*a)]);
    ++void uns_var (int i,
    ++        char (*a)[*][i], /* dg-warn "variable" */
    ++        int (*x)[__lengthof__ (*a)]);
    ++void uns_uns (int i,
    ++        char (*a)[*][*],
    ++        int (*x)[__lengthof__ (*a)]);
    ++
    ++// Can't test due to bug: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116284>
    ++//static int z2[0];
    ++//static int y2[__lengthof__(z2)];
     
      ## gcc/testsuite/gcc.dg/lengthof.c (new) ##
     @@
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +{
     +  short a[7];
     +
    -+  assert (__lengthof__ (a) == 7);
    -+  assert (__lengthof__ (long [0]) == 0);
    -+  assert (__lengthof__ (unsigned [99]) == 99);
    ++  static_assert (__lengthof__ (a) == 7);
    ++  static_assert (__lengthof__ (long [0]) == 0);
    ++  static_assert (__lengthof__ (unsigned [99]) == 99);
    ++}
    ++
    ++void
    ++automatic(void)
    ++{
    ++  int a[] = {1, 2, 3};
    ++  int z[] = {};
    ++
    ++  static_assert (__lengthof__ (a) == 3);
    ++  static_assert (__lengthof__ (z) == 0);
     +}
     +
     +void
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +    int a[8];
     +  } s;
     +
    -+  assert (__lengthof__ (s.a) == 8);
    ++  static_assert (__lengthof__ (s.a) == 8);
     +}
     +
     +void
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +  int i;
     +
     +  i = 3;
    -+  assert (__lengthof__ (struct {int x[i++];}[3]) == 3);
    ++  static_assert (__lengthof__ (struct {int x[i++];}[3]) == 3);
     +  assert (i == 3);
     +}
     +
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +  long (*p)[__lengthof__ (a)];
     +
     +  p = &a;
    -+  assert (__lengthof__ (*p++) == 5);
    ++  static_assert (__lengthof__ (*p++) == 5);
     +  assert (p == &a);
     +}
     +
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +{
     +  int i;
     +
    -+  assert (__lengthof__ (int [0][4]) == 0);
    ++  static_assert (__lengthof__ (int [0][4]) == 0);
     +  i = 3;
     +  assert (__lengthof__ (int [0][i]) == 0);
     +}
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +{
     +  int i;
     +
    -+  assert (__lengthof__ (int [7][4]) == 7);
    ++  static_assert (__lengthof__ (int [7][4]) == 7);
     +  i = 3;
    -+  assert (__lengthof__ (int [7][i]) == 7);
    ++  static_assert (__lengthof__ (int [7][i]) == 7);
     +}
     +
     +void
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +  assert (i == 9 + 1);
     +}
     +
    ++void
    ++no_parens(void)
    ++{
    ++  int n = 3;
    ++  int a[7];
    ++  int v[n];
    ++
    ++  static_assert (__lengthof__ a == 7); 
    ++  assert (__lengthof__ v == 3); 
    ++}
    ++
     +int
     +main (void)
     +{
     +  array ();
    ++  automatic ();
     +  vla ();
     +  member ();
     +  vla_eval ();
    @@ gcc/testsuite/gcc.dg/lengthof.c (new)
     +  matrix_zero ();
     +  matrix_fixed ();
     +  matrix_vla ();
    ++  no_parens ();
     +}