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 <[email protected]>
## 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 <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
- ## 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
signature.asc
Description: PGP signature
