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

Attachment: signature.asc
Description: PGP signature

Reply via email to