v2:

-  Add a GNU extension first; not using ISO C-reserved names.  That is,
   add __lengthof__ instead of _Lengthof/lengthof.
-  Use 'in_lengthof' instead of 'in_sizeof'.

Alejandro Colomar (2):
  Merge definitions of array_type_nelts_top()
  c: Add __lengthof__() operator

 gcc/c-family/c-common.cc      | 19 +++++++
 gcc/c-family/c-common.def     |  3 ++
 gcc/c-family/c-common.h       |  2 +
 gcc/c/c-decl.cc               | 20 +++++---
 gcc/c/c-parser.cc             | 61 ++++++++++++++++------
 gcc/c/c-tree.h                |  4 ++
 gcc/c/c-typeck.cc             | 95 +++++++++++++++++++++++++++++++++--
 gcc/cp/cp-tree.h              |  1 -
 gcc/cp/operators.def          |  1 +
 gcc/cp/tree.cc                | 13 -----
 gcc/rust/backend/rust-tree.cc | 13 -----
 gcc/rust/backend/rust-tree.h  |  2 -
 gcc/target.h                  |  3 ++
 gcc/tree.cc                   | 13 +++++
 gcc/tree.h                    |  1 +
 15 files changed, 198 insertions(+), 53 deletions(-)

Range-diff against v1:
1:  507f5a51e17 = 1:  507f5a51e17 Merge definitions of array_type_nelts_top()
2:  e5835b982af ! 2:  6b48d48ecdd c: Add _Lengthof() operator
    @@ Metadata
     Author: Alejandro Colomar <a...@kernel.org>
     
      ## Commit message ##
    -    c: Add _Lengthof() operator
    +    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).
    @@ Commit message
         Cc: Joseph Myers <josmy...@redhat.com>
         Signed-off-by: Alejandro Colomar <a...@kernel.org>
     
    - ## gcc/Makefile.in ##
    -@@ gcc/Makefile.in: USER_H = $(srcdir)/ginclude/float.h \
    -    $(srcdir)/ginclude/stdalign.h \
    -    $(srcdir)/ginclude/stdatomic.h \
    -    $(srcdir)/ginclude/stdckdint.h \
    -+   $(srcdir)/ginclude/stdlength.h \
    -    $(EXTRA_HEADERS)
    - 
    - USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
    -
      ## gcc/c-family/c-common.cc ##
     @@ gcc/c-family/c-common.cc: const struct c_common_resword 
c_common_reswords[] =
    -   { "_Decimal64",       RID_DFLOAT64,  D_CONLY },
    -   { "_Decimal128",      RID_DFLOAT128, D_CONLY },
    -   { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
    -+  { "_Lengthof",        RID_LENGTHOF,  D_CONLY | D_EXT },
    -   { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
    -   { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
    -   { "_Static_assert",   RID_STATIC_ASSERT, D_CONLY },
    -@@ gcc/c-family/c-common.cc: const struct c_common_resword 
c_common_reswords[] =
    -   { "if",         RID_IF,         0 },
    -   { "inline",             RID_INLINE,     D_EXT89 },
    -   { "int",                RID_INT,        0 },
    -+  { "lengthof",           RID_LENGTHOF,   D_EXT },
    -   { "long",               RID_LONG,       0 },
    -   { "mutable",            RID_MUTABLE,    D_CXXONLY | D_CXXWARN },
    -   { "namespace",  RID_NAMESPACE,  D_CXXONLY | D_CXXWARN },
    +   { "__inline",           RID_INLINE,     0 },
    +   { "__inline__", RID_INLINE,     0 },
    +   { "__label__",  RID_LABEL,      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 fold_convert_loc (loc, size_type_node, t);
      }
     +
    -+/* Implement the _Lengthof keyword: Return the length of an array,
    ++/* Implement the lengthof keyword: Return the length of an array,
     +   that is, the number of elements in the array.  */
     +
     +tree
    @@ gcc/c-family/c-common.cc: c_alignof_expr (location_t loc, tree expr)
     +  type_code = TREE_CODE (type);
     +  if (type_code != ARRAY_TYPE)
     +    {
    -+      error_at (loc, "invalid application of %<_Lengthof%> to type %qT", 
type);
    ++      error_at (loc, "invalid application of %<lengthof%> to 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 'sizeof' expression during C++ template expansion,
    -+   or for the purpose of -Wsizeof-pointer-memaccess warning.  */
    ++/* Represents a 'lengthof' expression.  */
     +DEFTREECODE (LENGTHOF_EXPR, "lengthof_expr", tcc_expression, 1)
     +
      /* Represents a 'sizeof' expression during C++ template expansion,
    @@ gcc/c-family/c-common.h: extern tree c_common_truthvalue_conversion 
(location_t,
         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 ##
    +@@ gcc/c/c-decl.cc: start_struct (location_t loc, enum tree_code code, 
tree name,
    +      within a statement expr used within sizeof, et. al.  This is not
    +      terribly serious 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_lengthof))
    +     warning_at (loc, OPT_Wc___compat,
    +           "defining type in %qs expression is invalid in C++",
    +           (in_sizeof
    +            ? "sizeof"
    +-           : (in_typeof ? "typeof" : "alignof")));
    ++           : (in_typeof
    ++              ? "typeof"
    ++              : (in_alignof
    ++                 ? "alignof"
    ++                 : "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 attributes,
    +    struct_types.  */
    +       if (warn_cxx_compat
    +     && struct_parse_info != NULL
    +-    && !in_sizeof && !in_typeof && !in_alignof)
    ++    && !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, tree name,
    +   /* FIXME: This will issue a warning for a use of a type defined
    +      within sizeof in a statement expr.  This is not terribly serious
    +      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_lengthof))
    +     warning_at (loc, OPT_Wc___compat,
    +           "defining type in %qs expression is invalid in C++",
    +           (in_sizeof
    +            ? "sizeof"
    +-           : (in_typeof ? "typeof" : "alignof")));
    ++           : (in_typeof
    ++              ? "typeof"
    ++              : (in_alignof
    ++                 ? "alignof"
    ++                 : "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)
    +      struct_types.  */
    +   if (warn_cxx_compat
    +       && struct_parse_info != NULL
    +-      && !in_sizeof && !in_typeof && !in_alignof)
    ++      && !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 ##
     @@ gcc/c/c-parser.cc: along with GCC; see the file COPYING3.  If not see
      #include "bitmap.h"
    @@ gcc/c/c-parser.cc: c_parser_unary_expression (c_parser *parser)
     -c_parser_sizeof_expression (c_parser *parser)
     +c_parser_sizeof_or_lengthof_expression (c_parser *parser, enum rid rid)
      {
    -+  const char *op_name = (rid == RID_SIZEOF) ? "sizeof" : "_Lengthof";
    ++  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_unary_expression (c_parser *parser)
        location_t start;
        location_t finish = UNKNOWN_LOCATION;
     @@ 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_LENGTHOF)
    ++    in_lengthof++;
    ++  else
    ++    in_sizeof++;
    +   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
    +       && c_token_starts_compound_literal (c_parser_peek_2nd_token 
(parser)))
    +     {
    +@@ 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_LENGTHOF)
    ++      in_lengthof--;
    ++    else
    ++      in_sizeof--;
    +     ret.set_error ();
    +     ret.original_code = ERROR_MARK;
    +     ret.original_type = NULL;
    +@@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
    +                                                          type_name,
    +                                                          expr_loc);
    +     finish = expr.get_finish ();
    +-    goto sizeof_expr;
    ++    goto Xof_expr;
        }
            /* sizeof ( type-name ).  */
            if (scspecs)
    @@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
     -            "alignment specified for type name in %<sizeof%>");
     +            "alignment specified for type name in %qs", op_name);
            c_inhibit_evaluation_warnings--;
    -       in_sizeof--;
    +-      in_sizeof--;
     -      result = c_expr_sizeof_type (expr_loc, type_name);
     +      if (rid == RID_LENGTHOF)
    -+  result = c_expr_lengthof_type (expr_loc, type_name);
    ++  {
    ++    in_lengthof--;
    ++    result = c_expr_lengthof_type (expr_loc, type_name);
    ++  }
     +      else
    -+  result = c_expr_sizeof_type (expr_loc, type_name);
    ++  {
    ++    in_sizeof--;
    ++    result = c_expr_sizeof_type (expr_loc, type_name);
    ++  }
          }
        else
          {
    -@@ gcc/c/c-parser.cc: c_parser_sizeof_expression (c_parser *parser)
    +       expr_loc = c_parser_peek_token (parser)->location;
    +       expr = c_parser_unary_expression (parser);
    +       finish = expr.get_finish ();
    +-    sizeof_expr:
    ++    Xof_expr:
    +       c_inhibit_evaluation_warnings--;
    +-      in_sizeof--;
    ++      if (rid == RID_LENGTHOF)
    ++  in_lengthof--;
    ++      else
    ++  in_sizeof--;
            mark_exp_read (expr.value);
            if (TREE_CODE (expr.value) == COMPONENT_REF
          && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
    @@ gcc/c/c-tree.h: extern tree build_external_ref (location_t, tree, bool, 
tree *);
      extern struct c_expr parser_build_binary_op (location_t,
     
      ## gcc/c/c-typeck.cc ##
    +@@ gcc/c/c-typeck.cc: int in_alignof;
    + /* The level of nesting inside "sizeof".  */
    + int in_sizeof;
    + 
    ++/* The level of nesting inside "sizeof".  */
    ++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 *type)
    + 
    +   if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
    +     {
    +-      if (!in_sizeof && !in_typeof)
    ++      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_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_lengthof;
    +   t->next = maybe_used_decls;
    +   maybe_used_decls = t;
    + }
    +@@ gcc/c/c-typeck.cc: void
    + pop_maybe_used (bool used)
    + {
    +   struct maybe_used_decl *p = maybe_used_decls;
    +-  int cur_level = in_sizeof + in_typeof;
    ++  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 ret;
      }
      
    -+/* Return the result of _Lengthof applied to EXPR.  */
    ++/* Return the result of lengthof applied to EXPR.  */
     +
     +struct c_expr
     +c_expr_lengthof_expr (location_t loc, struct c_expr expr)
    @@ gcc/c/c-typeck.cc: c_expr_sizeof_type (location_t loc, struct 
c_type_name *t)
     +      ret.m_decimal = 0;
     +      if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)))
     +  {
    -+    /* _Lengthof 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 _Lengthof applied to T, a structure for the type
    ++/* 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.  */
     +
    @@ 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 _Lengthof 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 _Lengthof 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 ("lengthof", LENGTHOF_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/ginclude/stdlength.h (new) ##
    -@@
    -+/* Copyright (C) 2024 Free Software Foundation, Inc.
    -+
    -+This file is part of GCC.
    -+
    -+GCC is free software; you can redistribute it and/or modify
    -+it under the terms of the GNU General Public License as published by
    -+the Free Software Foundation; either version 3, or (at your option)
    -+any later version.
    -+
    -+GCC is distributed in the hope that it will be useful,
    -+but WITHOUT ANY WARRANTY; without even the implied warranty of
    -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    -+GNU General Public License for more details.
    -+
    -+Under Section 7 of GPL version 3, you are granted additional
    -+permissions described in the GCC Runtime Library Exception, version
    -+3.1, as published by the Free Software Foundation.
    -+
    -+You should have received a copy of the GNU General Public License and
    -+a copy of the GCC Runtime Library Exception along with this program;
    -+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    -+<http://www.gnu.org/licenses/>.  */
    -+
    -+#ifndef _STDLENGTH_H
    -+#define _STDLENGTH_H
    -+
    -+#if (!defined __cplusplus)
    -+
    -+#define lengthof _Lengthof
    -+
    -+#define __lengthof_is_defined 1
    -+
    -+#endif
    -+
    -+#endif    /* stdlength.h */
    -
      ## gcc/target.h ##
     @@ gcc/target.h: enum type_context_kind {
        /* Directly measuring the alignment of T.  */
-- 
2.45.2

Attachment: signature.asc
Description: PGP signature

Reply via email to