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 <a...@kernel.org>
     
3:  e2dbfc43b14 ! 3:  af05d01e68d c: Add __lengthof__() operator (n2529)
    @@ Metadata
     Author: Alejandro Colomar <a...@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--...@tutanota.com/T/>
    -    Suggested-by: Xavier Del Campo Romero <xavi....@tutanota.com>
    -    Co-developed-by: Martin Uecker <uec...@tugraz.at>
    -    Cc: Gabriel Ravier <gabrav...@gmail.com>
         Cc: Joseph Myers <josmy...@redhat.com>
    +    Cc: Gabriel Ravier <gabrav...@gmail.com>
         Cc: Jakub Jelinek <ja...@redhat.com>
         Cc: Kees Cook <keesc...@chromium.org>
         Cc: Qing Zhao <qing.z...@oracle.com>
         Cc: Jens Gustedt <jens.gust...@inria.fr>
    +    Cc: David Brown <david.br...@hesbynett.no>
    +    Cc: Florian Weimer <fwei...@redhat.com>
    +    Cc: Andreas Schwab <sch...@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--...@tutanota.com/T/
    +    Suggested-by: Xavier Del Campo Romero <xavi....@tutanota.com>
    +    Co-developed-by: Martin Uecker <uec...@tugraz.at>
         Signed-off-by: Alejandro Colomar <a...@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

Attachment: signature.asc
Description: PGP signature

Reply via email to