Hi!

v6:

-  Note that support for 0-length arrays is slightly broken.
-  Improve readability of is_top_array_vla(), without changing behavior.
-  Doc: Clarify that both types and expressions are accepted, and
   provide an example.  [Joseph]
-  Doc: Wording improvements.  [Joseph, Jens]
-  Tests:  [Joseph, Martin]
   -  Remove unnecessary assignments where we're just interested in
      the __lengthof__ expression.
   -  Add tests for arrays whose length is implicit: [] = {...}
   -  Add tests for 0-length arrays.
   -  Add tests for non-arrays.
   -  Add tests for undefined symbols.
   -  Add tests for the version without parentheses.
   -  Test whether some expressions are constant or variable.
   -  Use static_assert(3) instead of assert(3) where possible.
-  CC: Add an LLVM developer: Timm.

Below is a range-diff against v5.

I've tested for regressions, and it seems there aren't (x86_64).
I've also replaced sizeof divisions in the C testsuite by __lengthof__,
to get broader testing, and it also worked well (those changes are not
included in this patch).

I've seen some internal compiler errors while running `make -j24 check`
that I haven't been able to reproduce consistently.  However, they are
in parts of the repository that are unrelated to my changes, so I
suspect those are problems that existed before my patches.  (I've
reported the ICE in an earlier subthread of this thread.)


Have a lovely day!
Alex


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                       | 118 ++++++++++++++++++-
 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                     |  31 +++++
 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 | 115 ++++++++++++++++++
 gcc/testsuite/gcc.dg/lengthof-vla.c     |  46 ++++++++
 gcc/testsuite/gcc.dg/lengthof.c         | 150 ++++++++++++++++++++++++
 gcc/tree.cc                             |  17 ++-
 gcc/tree.h                              |   3 +-
 28 files changed, 598 insertions(+), 79 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/lengthof-compile.c
 create mode 100644 gcc/testsuite/gcc.dg/lengthof-vla.c
 create mode 100644 gcc/testsuite/gcc.dg/lengthof.c

Range-diff against v5:
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:  71fd2013967 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 <josmy...@redhat.com>
         Cc: Gabriel Ravier <gabrav...@gmail.com>
    @@ Commit message
         Cc: David Brown <david.br...@hesbynett.no>
         Cc: Florian Weimer <fwei...@redhat.com>
         Cc: Andreas Schwab <sch...@linux-m68k.org>
    +    Cc: Timm Baeder <tbae...@redhat.com>
     
         gcc/ChangeLog:
     
    @@ 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();
    ++static int f2(); /* { dg-warning "never defined" } */
    ++int a[10][10];
    ++int n;
    ++
    ++void
    ++syms(void)
    ++{
    ++  int b[n][n];
    ++
    ++  __lengthof__ (a[f1()]);
    ++  __lengthof__ (b[f2()]);
    ++}
    ++
    ++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-error "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-error "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 ();
     +}
-- 
2.45.2

Attachment: signature.asc
Description: PGP signature

Reply via email to