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
signature.asc
Description: PGP signature