On Wed, Oct 02, 2024 at 08:21:54PM +0200, Alejandro Colomar wrote:
> 
> Hi Daniel,
> 
> Here's a revised version of the WG14 paper, with all issues addressed.

I had a topy in the paper number.  Here's the paper with the number
fixed.

Cheers,
Alex

> 
> Have a lovely day!
> Alex
> 
> On Wed, Oct 02, 2024 at 11:41:20AM +0200, Alejandro Colomar wrote:
> > Hi!
> > 
> > This operator is as voted in a WG14 meeting yesterday, with the only
> > difference that we name it __lengthof__ instead of _Lengthof, to be able
> > to add it without being bound by ISO bureaucracy.
> > 
> > No semantic changes since v12; only the rename, according to what WG14
> > preferred.  WG14 agreed on the semantic changes of the operator as I
> > implemented them in v12.
> > 
> > Changes since v12:
> > 
> > -  Rename s/__nelementsof__/__lengthof__/
> > -  Fix typo in documentation.
> > 
> > Below is a range diff against v12.
> > 
> > Have a lovely day!
> > Alex
> > 
> > 
> > Alejandro Colomar (4):
> >   contrib/: Add support for Cc: and Link: tags
> >   gcc/: Rename array_type_nelts() => array_type_nelts_minus_one()
> >   Merge definitions of array_type_nelts_top()
> >   c: Add __lengthof__ operator
> > 
> >  contrib/gcc-changelog/git_commit.py        |   5 +-
> >  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                            |  32 +++--
> >  gcc/c/c-fold.cc                            |   7 +-
> >  gcc/c/c-parser.cc                          |  62 +++++++--
> >  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                        |  30 +++++
> >  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/nelementsof-compile.c | 115 ++++++++++++++++
> >  gcc/testsuite/gcc.dg/nelementsof-vla.c     |  46 +++++++
> >  gcc/testsuite/gcc.dg/nelementsof.c         | 150 +++++++++++++++++++++
> >  gcc/tree.cc                                |  17 ++-
> >  gcc/tree.h                                 |   3 +-
> >  29 files changed, 604 insertions(+), 80 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/nelementsof-compile.c
> >  create mode 100644 gcc/testsuite/gcc.dg/nelementsof-vla.c
> >  create mode 100644 gcc/testsuite/gcc.dg/nelementsof.c
> > 
> > Range-diff against v12:
> > 1:  d7fca49888a = 1:  d7fca49888a contrib/: Add support for Cc: and Link: 
> > tags
> > 2:  e65245ac294 = 2:  e65245ac294 gcc/: Rename array_type_nelts() => 
> > array_type_nelts_minus_one()
> > 3:  03de2d67bb1 = 3:  03de2d67bb1 Merge definitions of 
> > array_type_nelts_top()
> > 4:  4373c48205d ! 4:  f635871da1f c: Add __nelementsof__ operator
> >     @@ Metadata
> >      Author: Alejandro Colomar <a...@kernel.org>
> >      
> >       ## Commit message ##
> >     -    c: Add __nelementsof__ operator
> >     +    c: Add __lengthof__ operator
> >      
> >          This operator is similar to sizeof but can only be applied to an 
> > array,
> >          and returns its number of elements.
> >     @@ Commit message
> >      
> >          gcc/ChangeLog:
> >      
> >     -            * doc/extend.texi: Document __nelementsof__ operator.
> >     -            * target.h (enum type_context_kind): Add __nelementsof__ 
> > operator.
> >     +            * 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_nelementsof_type): Add __nelementsof__ 
> > operator.
> >     +            * c-common.cc (c_lengthof_type): Add __lengthof__ operator.
> >      
> >          gcc/c/ChangeLog:
> >      
> >                  * c-tree.h
> >     -            (c_expr_nelementsof_expr, c_expr_nelementsof_type)
> >     +            (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_nelementsof_expression)
> >     -            (c_parser_sizeof_or_nelementsof_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_nelementsof_expr, c_expr_nelementsof_type):
> >     -            Add __nelementsof__operator.
> >     +            (c_expr_lengthof_expr, c_expr_lengthof_type):
> >     +            Add __lengthof__operator.
> >      
> >          gcc/cp/ChangeLog:
> >      
> >     -            * operators.def: Add __nelementsof__ operator.
> >     +            * operators.def: Add __lengthof__ operator.
> >      
> >          gcc/testsuite/ChangeLog:
> >      
> >     -            * gcc.dg/nelementsof-compile.c
> >     -            * gcc.dg/nelementsof-vla.c
> >     -            * gcc.dg/nelementsof.c: Add tests for __nelementsof__ 
> > operator.
> >     +            * 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/n3313.pdf>
> >          Link: 
> > <https://inbox.sourceware.org/gcc/m8s4oqy--...@tutanota.com/T/>
> >     @@ gcc/c-family/c-common.cc: const struct c_common_resword 
> > c_common_reswords[] =
> >         { "__inline",               RID_INLINE,     0 },
> >         { "__inline__",     RID_INLINE,     0 },
> >         { "__label__",      RID_LABEL,      0 },
> >     -+  { "__nelementsof__",        RID_NELEMENTSOF, 0 },
> >     ++  { "__lengthof__",   RID_LENGTHOF,   0 },
> >         { "__null",         RID_NULL,       0 },
> >         { "__real",         RID_REALPART,   0 },
> >         { "__real__",               RID_REALPART,   0 },
> >     @@ gcc/c-family/c-common.cc: c_alignof_expr (location_t loc, tree expr)
> >      +   Return the number of elements of an array.  */
> >      +
> >      +tree
> >     -+c_nelementsof_type (location_t loc, tree type)
> >     ++c_lengthof_type (location_t loc, tree type)
> >      +{
> >      +  enum tree_code type_code;
> >      +
> >      +  type_code = TREE_CODE (type);
> >      +  if (type_code != ARRAY_TYPE)
> >      +    {
> >     -+      error_at (loc, "invalid application of %<nelementsof%> to type 
> > %qT", type);
> >     ++      error_at (loc, "invalid application of %<lengthof%> to type 
> > %qT", type);
> >      +      return error_mark_node;
> >      +    }
> >      +  if (!COMPLETE_TYPE_P (type))
> >      +    {
> >      +      error_at (loc,
> >     -+              "invalid application of %<nelementsof%> to incomplete 
> > type %qT",
> >     ++              "invalid application of %<lengthof%> to incomplete type 
> > %qT",
> >      +              type);
> >      +      return error_mark_node;
> >      +    }
> >     @@ gcc/c-family/c-common.def: DEFTREECODE (EXCESS_PRECISION_EXPR, 
> > "excess_precision
> >          number.  */
> >       DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
> >       
> >     -+/* Represents a 'nelementsof' expression.  */
> >     -+DEFTREECODE (NELEMENTSOF_EXPR, "nelementsof_expr", tcc_expression, 1)
> >     ++/* Represents a 'lengthof' expression.  */
> >     ++DEFTREECODE (LENGTHOF_EXPR, "lengthof_expr", tcc_expression, 1)
> >      +
> >       /* Represents a 'sizeof' expression during C++ template expansion,
> >          or for the purpose of -Wsizeof-pointer-memaccess warning.  */
> >     @@ gcc/c-family/c-common.h: enum rid
> >       
> >         /* C extensions */
> >         RID_ASM,       RID_TYPEOF,   RID_TYPEOF_UNQUAL, RID_ALIGNOF,  
> > RID_ATTRIBUTE,
> >     -+  RID_NELEMENTSOF,
> >     ++  RID_LENGTHOF,
> >         RID_VA_ARG,
> >         RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL,    
> > RID_CHOOSE_EXPR,
> >         RID_TYPES_COMPATIBLE_P,      RID_BUILTIN_COMPLEX,      
> > RID_BUILTIN_SHUFFLE,
> >     @@ gcc/c-family/c-common.h: extern tree c_common_truthvalue_conversion 
> > (location_t,
> >       extern void c_apply_type_quals_to_decl (int, tree);
> >       extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, 
> > int);
> >       extern tree c_alignof_expr (location_t, tree);
> >     -+extern tree c_nelementsof_type (location_t, tree);
> >     ++extern tree c_lengthof_type (location_t, tree);
> >       /* Print an error message for invalid operands to arith operation 
> > CODE.
> >          NOP_EXPR is used as a special case (see truthvalue_conversion).  */
> >       extern void binary_op_error (rich_location *, enum tree_code, tree, 
> > tree);
> >     @@ gcc/c/c-decl.cc: start_struct (location_t loc, enum tree_code code, 
> > tree name,
> >            sizeof anyhow.  */
> >      -  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
> >      +  if (warn_cxx_compat
> >     -+      && (in_sizeof || in_typeof || in_alignof || in_nelementsof))
> >     ++      && (in_sizeof || in_typeof || in_alignof || in_lengthof))
> >           warning_at (loc, OPT_Wc___compat,
> >                     "defining type in %qs expression is invalid in C++",
> >                     (in_sizeof
> >     @@ gcc/c/c-decl.cc: start_struct (location_t loc, enum tree_code code, 
> > tree name,
> >      +                  ? "typeof"
> >      +                  : (in_alignof
> >      +                     ? "alignof"
> >     -+                     : "nelementsof"))));
> >     ++                     : "lengthof"))));
> >       
> >         if (in_underspecified_init)
> >           error_at (loc, "%qT defined in underspecified object 
> > initializer", ref);
> >     @@ gcc/c/c-decl.cc: finish_struct (location_t loc, tree t, tree 
> > fieldlist, tree att
> >             if (warn_cxx_compat
> >               && struct_parse_info != NULL
> >      -        && !in_sizeof && !in_typeof && !in_alignof)
> >     -+        && !in_sizeof && !in_typeof && !in_alignof && !in_nelementsof)
> >     ++        && !in_sizeof && !in_typeof && !in_alignof && !in_lengthof)
> >             struct_parse_info->struct_types.safe_push (t);
> >            }
> >       
> >     @@ gcc/c/c-decl.cc: start_enum (location_t loc, struct c_enum_contents 
> > *the_enum, t
> >            as C++ doesn't permit statement exprs within sizeof anyhow.  */
> >      -  if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof))
> >      +  if (warn_cxx_compat
> >     -+      && (in_sizeof || in_typeof || in_alignof || in_nelementsof))
> >     ++      && (in_sizeof || in_typeof || in_alignof || in_lengthof))
> >           warning_at (loc, OPT_Wc___compat,
> >                     "defining type in %qs expression is invalid in C++",
> >                     (in_sizeof
> >     @@ gcc/c/c-decl.cc: start_enum (location_t loc, struct c_enum_contents 
> > *the_enum, t
> >      +                  ? "typeof"
> >      +                  : (in_alignof
> >      +                     ? "alignof"
> >     -+                     : "nelementsof"))));
> >     ++                     : "lengthof"))));
> >       
> >         if (in_underspecified_init)
> >           error_at (loc, "%qT defined in underspecified object initializer",
> >     @@ gcc/c/c-decl.cc: finish_enum (tree enumtype, tree values, tree 
> > attributes)
> >         if (warn_cxx_compat
> >             && struct_parse_info != NULL
> >      -      && !in_sizeof && !in_typeof && !in_alignof)
> >     -+      && !in_sizeof && !in_typeof && !in_alignof && !in_nelementsof)
> >     ++      && !in_sizeof && !in_typeof && !in_alignof && !in_lengthof)
> >           struct_parse_info->struct_types.safe_push (enumtype);
> >       
> >         /* Check for consistency with previous definition */
> >     @@ gcc/c/c-parser.cc: along with GCC; see the file COPYING3.  If not see
> >      +
> >      +#define c_parser_sizeof_expression(parser)                            
> >         \
> >      +(                                                                     
> >         \
> >     -+  c_parser_sizeof_or_nelementsof_expression (parser, RID_SIZEOF)      
> >         \
> >     ++  c_parser_sizeof_or_lengthof_expression (parser, RID_SIZEOF)         
> >         \
> >      +)
> >       
> >     -+#define c_parser_nelementsof_expression(parser)                       
> >         \
> >     ++#define c_parser_lengthof_expression(parser)                          
> >         \
> >      +(                                                                     
> >         \
> >     -+  c_parser_sizeof_or_nelementsof_expression (parser, RID_NELEMENTSOF) 
> >         \
> >     ++  c_parser_sizeof_or_lengthof_expression (parser, RID_LENGTHOF)       
> >         \
> >      +)
> >      +
> >       /* We need to walk over decls with incomplete struct/union/enum types
> >     @@ gcc/c/c-parser.cc: static struct c_expr c_parser_binary_expression 
> > (c_parser *,
> >       static struct c_expr c_parser_cast_expression (c_parser *, struct 
> > c_expr *);
> >       static struct c_expr c_parser_unary_expression (c_parser *);
> >      -static struct c_expr c_parser_sizeof_expression (c_parser *);
> >     -+static struct c_expr c_parser_sizeof_or_nelementsof_expression 
> > (c_parser *,
> >     ++static struct c_expr c_parser_sizeof_or_lengthof_expression (c_parser 
> > *,
> >      +                                                              enum 
> > rid);
> >       static struct c_expr c_parser_alignof_expression (c_parser *);
> >       static struct c_expr c_parser_postfix_expression (c_parser *);
> >     @@ gcc/c/c-parser.cc: c_parser_unary_expression (c_parser *parser)
> >           case CPP_KEYWORD:
> >             switch (c_parser_peek_token (parser)->keyword)
> >             {
> >     -+      case RID_NELEMENTSOF:
> >     -+        return c_parser_nelementsof_expression (parser);
> >     ++      case RID_LENGTHOF:
> >     ++        return c_parser_lengthof_expression (parser);
> >             case RID_SIZEOF:
> >               return c_parser_sizeof_expression (parser);
> >             case RID_ALIGNOF:
> >     @@ gcc/c/c-parser.cc: c_parser_unary_expression (c_parser *parser)
> >       
> >       static struct c_expr
> >      -c_parser_sizeof_expression (c_parser *parser)
> >     -+c_parser_sizeof_or_nelementsof_expression (c_parser *parser, enum rid 
> > rid)
> >     ++c_parser_sizeof_or_lengthof_expression (c_parser *parser, enum rid 
> > rid)
> >       {
> >     -+  const char *op_name = (rid == RID_NELEMENTSOF) ? "nelementsof" : 
> > "sizeof";
> >     ++  const char *op_name = (rid == RID_LENGTHOF) ? "lengthof" : "sizeof";
> >         struct c_expr expr;
> >         struct c_expr result;
> >         location_t expr_loc;
> >     @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
> >         c_parser_consume_token (parser);
> >         c_inhibit_evaluation_warnings++;
> >      -  in_sizeof++;
> >     -+  if (rid == RID_NELEMENTSOF)
> >     -+    in_nelementsof++;
> >     ++  if (rid == RID_LENGTHOF)
> >     ++    in_lengthof++;
> >      +  else
> >      +    in_sizeof++;
> >         if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
> >     @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
> >               struct c_expr ret;
> >               c_inhibit_evaluation_warnings--;
> >      -        in_sizeof--;
> >     -+        if (rid == RID_NELEMENTSOF)
> >     -+          in_nelementsof--;
> >     ++        if (rid == RID_LENGTHOF)
> >     ++          in_lengthof--;
> >      +        else
> >      +          in_sizeof--;
> >               ret.set_error ();
> >     @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
> >             c_inhibit_evaluation_warnings--;
> >      -      in_sizeof--;
> >      -      result = c_expr_sizeof_type (expr_loc, type_name);
> >     -+      if (rid == RID_NELEMENTSOF)
> >     ++      if (rid == RID_LENGTHOF)
> >      +      {
> >     -+        in_nelementsof--;
> >     -+        result = c_expr_nelementsof_type (expr_loc, type_name);
> >     ++        in_lengthof--;
> >     ++        result = c_expr_lengthof_type (expr_loc, type_name);
> >      +      }
> >      +      else
> >      +      {
> >     @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
> >      +    Xof_expr:
> >             c_inhibit_evaluation_warnings--;
> >      -      in_sizeof--;
> >     -+      if (rid == RID_NELEMENTSOF)
> >     -+      in_nelementsof--;
> >     ++      if (rid == RID_LENGTHOF)
> >     ++      in_lengthof--;
> >      +      else
> >      +      in_sizeof--;
> >             mark_exp_read (expr.value);
> >     @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
> >      -      error_at (expr_loc, "%<sizeof%> applied to a bit-field");
> >      -      result = c_expr_sizeof_expr (expr_loc, expr);
> >      +      error_at (expr_loc, "%qs applied to a bit-field", op_name);
> >     -+      if (rid == RID_NELEMENTSOF)
> >     -+      result = c_expr_nelementsof_expr (expr_loc, expr);
> >     ++      if (rid == RID_LENGTHOF)
> >     ++      result = c_expr_lengthof_expr (expr_loc, expr);
> >      +      else
> >      +      result = c_expr_sizeof_expr (expr_loc, expr);
> >           }
> >     @@ gcc/c/c-tree.h: extern int c_type_dwarf_attribute (const_tree, int);
> >       /* in c-typeck.cc */
> >       extern int in_alignof;
> >       extern int in_sizeof;
> >     -+extern int in_nelementsof;
> >     ++extern int in_lengthof;
> >       extern int in_typeof;
> >       extern bool c_in_omp_for;
> >       extern bool c_omp_array_section_p;
> >     @@ gcc/c/c-tree.h: extern tree build_external_ref (location_t, tree, 
> > bool, tree *);
> >       extern void pop_maybe_used (bool);
> >       extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
> >       extern struct c_expr c_expr_sizeof_type (location_t, struct 
> > c_type_name *);
> >     -+extern struct c_expr c_expr_nelementsof_expr (location_t, struct 
> > c_expr);
> >     -+extern struct c_expr c_expr_nelementsof_type (location_t loc,
> >     ++extern struct c_expr c_expr_lengthof_expr (location_t, struct c_expr);
> >     ++extern struct c_expr c_expr_lengthof_type (location_t loc,
> >      +                                            struct c_type_name *);
> >       extern struct c_expr parser_build_unary_op (location_t, enum 
> > tree_code,
> >                                                 struct c_expr);
> >     @@ gcc/c/c-typeck.cc: int in_alignof;
> >       /* The level of nesting inside "sizeof".  */
> >       int in_sizeof;
> >       
> >     -+/* The level of nesting inside "nelementsof".  */
> >     -+int in_nelementsof;
> >     ++/* The level of nesting inside "lengthof".  */
> >     ++int in_lengthof;
> >      +
> >       /* The level of nesting inside "typeof".  */
> >       int in_typeof;
> >     @@ gcc/c/c-typeck.cc: build_external_ref (location_t loc, tree id, bool 
> > fun, tree *
> >         if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
> >           {
> >      -      if (!in_sizeof && !in_typeof)
> >     -+      if (!in_sizeof && !in_typeof && !in_nelementsof)
> >     ++      if (!in_sizeof && !in_typeof && !in_lengthof)
> >             C_DECL_USED (ref) = 1;
> >             else if (DECL_INITIAL (ref) == NULL_TREE
> >                    && DECL_EXTERNAL (ref)
> >     @@ gcc/c/c-typeck.cc: struct maybe_used_decl
> >         /* The decl.  */
> >         tree decl;
> >      -  /* The level seen at (in_sizeof + in_typeof).  */
> >     -+  /* The level seen at (in_sizeof + in_typeof + in_nelementsof).  */
> >     ++  /* The level seen at (in_sizeof + in_typeof + in_lengthof).  */
> >         int level;
> >         /* The next one at this level or above, or NULL.  */
> >         struct maybe_used_decl *next;
> >     @@ gcc/c/c-typeck.cc: record_maybe_used_decl (tree decl)
> >         struct maybe_used_decl *t = XOBNEW (&parser_obstack, struct 
> > maybe_used_decl);
> >         t->decl = decl;
> >      -  t->level = in_sizeof + in_typeof;
> >     -+  t->level = in_sizeof + in_typeof + in_nelementsof;
> >     ++  t->level = in_sizeof + in_typeof + in_lengthof;
> >         t->next = maybe_used_decls;
> >         maybe_used_decls = t;
> >       }
> >     @@ gcc/c/c-typeck.cc: void
> >       {
> >         struct maybe_used_decl *p = maybe_used_decls;
> >      -  int cur_level = in_sizeof + in_typeof;
> >     -+  int cur_level = in_sizeof + in_typeof + in_nelementsof;
> >     ++  int cur_level = in_sizeof + in_typeof + in_lengthof;
> >         while (p && p->level > cur_level)
> >           {
> >             if (used)
> >     @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct 
> > c_type_name *t)
> >      +  return var;
> >      +}
> >      +
> >     -+/* Return the result of nelementsof applied to EXPR.  */
> >     ++/* Return the result of lengthof applied to EXPR.  */
> >      +
> >      +struct c_expr
> >     -+c_expr_nelementsof_expr (location_t loc, struct c_expr expr)
> >     ++c_expr_lengthof_expr (location_t loc, struct c_expr expr)
> >      +{
> >      +  struct c_expr ret;
> >      +  if (expr.value == error_mark_node)
> >     @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct 
> > c_type_name *t)
> >      +
> >      +      tree folded_expr = c_fully_fold (expr.value, 
> > require_constant_value,
> >      +                                     &expr_const_operands);
> >     -+      ret.value = c_nelementsof_type (loc, TREE_TYPE (folded_expr));
> >     ++      ret.value = c_lengthof_type (loc, TREE_TYPE (folded_expr));
> >      +      c_last_sizeof_arg = expr.value;
> >      +      c_last_sizeof_loc = loc;
> >     -+      ret.original_code = NELEMENTSOF_EXPR;
> >     ++      ret.original_code = LENGTHOF_EXPR;
> >      +      ret.original_type = NULL;
> >      +      ret.m_decimal = 0;
> >      +      if (is_top_array_vla (TREE_TYPE (folded_expr)))
> >      +      {
> >     -+        /* nelementsof is evaluated when given a vla.  */
> >     ++        /* lengthof is evaluated when given a vla.  */
> >      +        ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
> >      +                            folded_expr, ret.value);
> >      +        C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = 
> > !expr_const_operands;
> >     @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct 
> > c_type_name *t)
> >      +  return ret;
> >      +}
> >      +
> >     -+/* Return the result of nelementsof applied to T, a structure for the 
> > type
> >     -+   name passed to nelementsof (rather than the type itself).  LOC is 
> > the
> >     ++/* Return the result of lengthof applied to T, a structure for the 
> > type
> >     ++   name passed to lengthof (rather than the type itself).  LOC is the
> >      +   location of the original expression.  */
> >      +
> >      +struct c_expr
> >     -+c_expr_nelementsof_type (location_t loc, struct c_type_name *t)
> >     ++c_expr_lengthof_type (location_t loc, struct c_type_name *t)
> >      +{
> >      +  tree type;
> >      +  struct c_expr ret;
> >      +  tree type_expr = NULL_TREE;
> >      +  bool type_expr_const = true;
> >      +  type = groktypename (t, &type_expr, &type_expr_const);
> >     -+  ret.value = c_nelementsof_type (loc, type);
> >     ++  ret.value = c_lengthof_type (loc, type);
> >      +  c_last_sizeof_arg = type;
> >      +  c_last_sizeof_loc = loc;
> >     -+  ret.original_code = NELEMENTSOF_EXPR;
> >     ++  ret.original_code = LENGTHOF_EXPR;
> >      +  ret.original_type = NULL;
> >      +  ret.m_decimal = 0;
> >      +  if (type == error_mark_node)
> >     @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct 
> > c_type_name *t)
> >      +    {
> >      +      /* If the type is a [*] array, it is a VLA but is represented as
> >      +       having a size of zero.  In such a case we must ensure that
> >     -+       the result of nelementsof does not get folded to a constant by
> >     ++       the result of lengthof does not get folded to a constant by
> >      +       c_fully_fold, because if the length is evaluated the result is
> >      +       not constant and so constraints on zero or negative size
> >     -+       arrays must not be applied when this nelementsof call is inside
> >     ++       arrays must not be applied when this lengthof call is inside
> >      +       another array declarator.  */
> >      +      if (!type_expr)
> >      +      type_expr = integer_zero_node;
> >     @@ gcc/cp/operators.def: DEF_OPERATOR ("co_await", CO_AWAIT_EXPR, "aw", 
> > OVL_OP_FLAG
> >       
> >       /* These are extensions.  */
> >       DEF_OPERATOR ("alignof", ALIGNOF_EXPR, "az", OVL_OP_FLAG_UNARY)
> >     -+DEF_OPERATOR ("__nelementsof__", NELEMENTSOF_EXPR, "lz", 
> > OVL_OP_FLAG_UNARY)
> >     ++DEF_OPERATOR ("__lengthof__", LENGTHOF_EXPR, "lz", OVL_OP_FLAG_UNARY)
> >       DEF_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 
> > OVL_OP_FLAG_UNARY)
> >       DEF_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 
> > OVL_OP_FLAG_UNARY)
> >       
> >     @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} 
> > expression is a fu
> >       the expression evaluates to the alignment of the function which may
> >       be specified by attribute @code{aligned} (@pxref{Common Function 
> > Attributes}).
> >       
> >     -+@node nelementsof
> >     ++@node lengthof
> >      +@section Determining the Number of Elements of Arrays
> >     -+@cindex nelementsof
> >     ++@cindex lengthof
> >      +@cindex number of elements
> >      +
> >     -+The keyword @code{__elemetsf__} determines the length of an array 
> > operand,
> >     ++The keyword @code{__lengthof__} determines the length of an array 
> > operand,
> >      +that is, the number of elements in the array.
> >      +Its syntax is similar to @code{sizeof}.
> >      +The operand must be
> >     @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} 
> > expression is a fu
> >      +
> >      +@smallexample
> >      +int a[n];
> >     -+__elemetsf__ (a);  // returns n
> >     -+__elemetsf__ (int [7][3]);  // returns 7
> >     ++__lengthof__ (a);  // returns n
> >     ++__lengthof__ (int [7][3]);  // returns 7
> >      +@end smallexample
> >      +
> >      +The result of this operator is an integer constant expression,
> >     @@ gcc/doc/extend.texi: If the operand of the @code{__alignof__} 
> > expression is a fu
> >      +For example:
> >      +
> >      +@smallexample
> >     -+__elemetsf__ (int [7][n++]);  // integer constant expression
> >     -+__elemetsf__ (int [n++][7]);  // run-time value; n++ is evaluated
> >     ++__lengthof__ (int [7][n++]);  // integer constant expression
> >     ++__lengthof__ (int [n++][7]);  // run-time value; n++ is evaluated
> >      +@end smallexample
> >      +
> >       @node Inline
> >     @@ gcc/target.h: enum type_context_kind {
> >         TCTX_ALIGNOF,
> >       
> >      +  /* Directly measuring the number of elements of array T.  */
> >     -+  TCTX_NELEMENTSOF,
> >     ++  TCTX_LENGTHOF,
> >      +
> >         /* Creating objects of type T with static storage duration.  */
> >         TCTX_STATIC_STORAGE,
> >     @@ gcc/testsuite/gcc.dg/nelementsof-compile.c (new)
> >      +static int w[] = {1, 2, 3};
> >      +
> >      +static int z[0];
> >     -+static int y[__nelementsof__(z)];
> >     ++static int y[__lengthof__(z)];
> >      +
> >      +void
> >      +automatic(void)
> >      +{
> >     -+  __nelementsof__ (w);
> >     ++  __lengthof__ (w);
> >      +}
> >      +
> >      +void
> >      +incomplete (int p[])
> >      +{
> >     -+  __nelementsof__ (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.  */
> >     -+  __nelementsof__ (p);  /* { dg-error "invalid" } */
> >     ++  __lengthof__ (p);  /* { dg-error "invalid" } */
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof-compile.c (new)
> >      +    int fam[];
> >      +  } s;
> >      +
> >     -+  __nelementsof__ (s.fam); /* { dg-error "incomplete" } */
> >     ++  __lengthof__ (s.fam); /* { dg-error "incomplete" } */
> >      +}
> >      +
> >     -+void fix_fix (int i, char (*a)[3][5], int (*x)[__nelementsof__ (*a)]);
> >     -+void fix_var (int i, char (*a)[3][i], int (*x)[__nelementsof__ (*a)]);
> >     -+void fix_uns (int i, char (*a)[3][*], int (*x)[__nelementsof__ (*a)]);
> >     ++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)
> >     @@ gcc/testsuite/gcc.dg/nelementsof-compile.c (new)
> >      +    int x[3];
> >      +  } s;
> >      +
> >     -+  __nelementsof__ (x); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (int); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (s); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (struct s); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (&x); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (p); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (int *); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (&s.x); /* { dg-error "invalid" } */
> >     -+  __nelementsof__ (int (*)[3]); /* { dg-error "invalid" } */
> >     ++  __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();
> >     @@ gcc/testsuite/gcc.dg/nelementsof-compile.c (new)
> >      +{
> >      +  int b[n][n];
> >      +
> >     -+  __nelementsof__ (a[f1()]);
> >     -+  __nelementsof__ (b[f2()]);
> >     ++  __lengthof__ (a[f1()]);
> >     ++  __lengthof__ (b[f2()]);
> >      +}
> >      +
> >      +void
> >      +no_parens(void)
> >      +{
> >     -+  __nelementsof__ a;
> >     -+  __nelementsof__ *a;
> >     -+  __nelementsof__ (int [3]) {};
> >     ++  __lengthof__ a;
> >     ++  __lengthof__ *a;
> >     ++  __lengthof__ (int [3]) {};
> >      +
> >     -+  __nelementsof__ int [3]; /* { dg-error "expected expression before" 
> > } */
> >     ++  __lengthof__ int [3]; /* { dg-error "expected expression before" } 
> > */
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof-compile.c (new)
> >      +{
> >      +  int n = 7;
> >      +
> >     -+  _Static_assert (__nelementsof__ (int [3][n]) == 3);
> >     -+  _Static_assert (__nelementsof__ (int [n][3]) == 7); /* { dg-error 
> > "not constant" } */
> >     -+  _Static_assert (__nelementsof__ (int [0][3]) == 0);
> >     -+  _Static_assert (__nelementsof__ (int [0]) == 0);
> >     ++  _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: nelementsof(int [0][n]) should result in a constant 
> > expression.  */
> >     -+  _Static_assert (__nelementsof__ (int [0][n]) == 0); /* { dg-error 
> > "not constant" } */
> >     ++  /* FIXME: lengthof(int [0][n]) should result in a constant 
> > expression.  */
> >     ++  _Static_assert (__lengthof__ (int [0][n]) == 0); /* { dg-error "not 
> > constant" } */
> >      +}
> >      
> >       ## gcc/testsuite/gcc.dg/nelementsof-vla.c (new) ##
> >     @@ gcc/testsuite/gcc.dg/nelementsof-vla.c (new)
> >      +
> >      +void fix_fix (int i,
> >      +            char (*a)[3][5],
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void fix_var (int i,
> >      +            char (*a)[3][i], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void fix_uns (int i,
> >      +            char (*a)[3][*],
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +
> >      +void zro_fix (int i,
> >      +            char (*a)[0][5],
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void zro_var (int i,
> >      +            char (*a)[0][i], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void zro_uns (int i,
> >      +            char (*a)[0][*],
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +
> >      +void var_fix (int i,
> >      +            char (*a)[i][5], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]); /* dg-warn "variable" */
> >     ++            int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
> >      +void var_var (int i,
> >      +            char (*a)[i][i], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]); /* dg-warn "variable" */
> >     ++            int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
> >      +void var_uns (int i,
> >      +            char (*a)[i][*], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]); /* dg-warn "variable" */
> >     ++            int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */
> >      +
> >      +void uns_fix (int i,
> >      +            char (*a)[*][5],
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void uns_var (int i,
> >      +            char (*a)[*][i], /* dg-warn "variable" */
> >     -+            int (*x)[__nelementsof__ (*a)]);
> >     ++            int (*x)[__lengthof__ (*a)]);
> >      +void uns_uns (int i,
> >      +            char (*a)[*][*],
> >     -+            int (*x)[__nelementsof__ (*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[__nelementsof__(z2)];
> >     ++//static int y2[__lengthof__(z2)];
> >      
> >       ## gcc/testsuite/gcc.dg/nelementsof.c (new) ##
> >      @@
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +{
> >      +  short a[7];
> >      +
> >     -+  static_assert (__nelementsof__ (a) == 7);
> >     -+  static_assert (__nelementsof__ (long [0]) == 0);
> >     -+  static_assert (__nelementsof__ (unsigned [99]) == 99);
> >     ++  static_assert (__lengthof__ (a) == 7);
> >     ++  static_assert (__lengthof__ (long [0]) == 0);
> >     ++  static_assert (__lengthof__ (unsigned [99]) == 99);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  int a[] = {1, 2, 3};
> >      +  int z[] = {};
> >      +
> >     -+  static_assert (__nelementsof__ (a) == 3);
> >     -+  static_assert (__nelementsof__ (z) == 0);
> >     ++  static_assert (__lengthof__ (a) == 3);
> >     ++  static_assert (__lengthof__ (z) == 0);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  unsigned n;
> >      +
> >      +  n = 99;
> >     -+  assert (__nelementsof__ (short [n - 10]) == 99 - 10);
> >     ++  assert (__lengthof__ (short [n - 10]) == 99 - 10);
> >      +
> >      +  int v[n / 2];
> >     -+  assert (__nelementsof__ (v) == 99 / 2);
> >     ++  assert (__lengthof__ (v) == 99 / 2);
> >      +
> >      +  n = 0;
> >      +  int z[n];
> >     -+  assert (__nelementsof__ (z) == 0);
> >     ++  assert (__lengthof__ (z) == 0);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +    int a[8];
> >      +  } s;
> >      +
> >     -+  static_assert (__nelementsof__ (s.a) == 8);
> >     ++  static_assert (__lengthof__ (s.a) == 8);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  int i;
> >      +
> >      +  i = 7;
> >     -+  assert (__nelementsof__ (struct {int x;}[i++]) == 7);
> >     ++  assert (__lengthof__ (struct {int x;}[i++]) == 7);
> >      +  assert (i == 7 + 1);
> >      +
> >      +  int v[i];
> >      +  int (*p)[i];
> >      +  p = &v;
> >     -+  assert (__nelementsof__ (*p++) == i);
> >     ++  assert (__lengthof__ (*p++) == i);
> >      +  assert (p - 1 == &v);
> >      +}
> >      +
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  int i;
> >      +
> >      +  i = 3;
> >     -+  static_assert (__nelementsof__ (struct {int x[i++];}[3]) == 3);
> >     ++  static_assert (__lengthof__ (struct {int x[i++];}[3]) == 3);
> >      +  assert (i == 3);
> >      +}
> >      +
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +array_noeval (void)
> >      +{
> >      +  long a[5];
> >     -+  long (*p)[__nelementsof__ (a)];
> >     ++  long (*p)[__lengthof__ (a)];
> >      +
> >      +  p = &a;
> >     -+  static_assert (__nelementsof__ (*p++) == 5);
> >     ++  static_assert (__lengthof__ (*p++) == 5);
> >      +  assert (p == &a);
> >      +}
> >      +
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +{
> >      +  int i;
> >      +
> >     -+  static_assert (__nelementsof__ (int [0][4]) == 0);
> >     ++  static_assert (__lengthof__ (int [0][4]) == 0);
> >      +  i = 3;
> >     -+  assert (__nelementsof__ (int [0][i]) == 0);
> >     ++  assert (__lengthof__ (int [0][i]) == 0);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +{
> >      +  int i;
> >      +
> >     -+  static_assert (__nelementsof__ (int [7][4]) == 7);
> >     ++  static_assert (__lengthof__ (int [7][4]) == 7);
> >      +  i = 3;
> >     -+  static_assert (__nelementsof__ (int [7][i]) == 7);
> >     ++  static_assert (__lengthof__ (int [7][i]) == 7);
> >      +}
> >      +
> >      +void
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  int i, j;
> >      +
> >      +  i = 7;
> >     -+  assert (__nelementsof__ (int [i++][4]) == 7);
> >     ++  assert (__lengthof__ (int [i++][4]) == 7);
> >      +  assert (i == 7 + 1);
> >      +
> >      +  i = 9;
> >      +  j = 3;
> >     -+  assert (__nelementsof__ (int [i++][j]) == 9);
> >     ++  assert (__lengthof__ (int [i++][j]) == 9);
> >      +  assert (i == 9 + 1);
> >      +}
> >      +
> >     @@ gcc/testsuite/gcc.dg/nelementsof.c (new)
> >      +  int a[7];
> >      +  int v[n];
> >      +
> >     -+  static_assert (__nelementsof__ a == 7); 
> >     -+  assert (__nelementsof__ v == 3); 
> >     ++  static_assert (__lengthof__ a == 7); 
> >     ++  assert (__lengthof__ v == 3); 
> >      +}
> >      +
> >      +int
> > 
> > -- 
> > 2.45.2
> > 
> 
> 
> 
> -- 
> <https://www.alejandro-colomar.es/>





-- 
<https://www.alejandro-colomar.es/>

Attachment: n3369.pdf
Description: Adobe PDF document

Attachment: signature.asc
Description: PGP signature

Reply via email to