Hi all, On Wed, Oct 02, 2024 at 08:29:26PM GMT, Alejandro Colomar wrote: > > 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.
FYI, this has been merged into C2y today, as _Lengthof. The paper that was merged was <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3369.pdf> with some trivial/editorial wording cosmetic changes amended on top of it. Have a lovely day! Alex > > > > > > 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/> -- <https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature