Hi! v9:
- Rename s/lengthof/elementsof/ There are existing lengthof() functions in the wild, which are incompatible with (completely unrelated to) this operator. In the case of elementsof(), we only found macros that expand to the usual sizeof division (plus safety checks in some cases), so this one would be compatible. [Aaron] ISO C uses "number of elements" and "length" indistinctly for referring to the number of elements of an array, so this name should also be obvious. Also, lengthof() might induce to ambiguity in contexts where string lengths are used, due to the overload of the term length. elementsof() is free of that ambiguity. I guess elementsof() has slightly more chances of being later accepted into ISO C than lengthof(), due to backwards compatibility with those existing functions named lengthof(). - Cc: += Daniel, A., Eugene, Aaron, Paul I'll send as a reply the updated draft for a WG14 C2y proposal incorporating these changes. As usual, below is a range diff against v8. Have a lovely day! Alex Alejandro Colomar (3): gcc/: Rename array_type_nelts() => array_type_nelts_minus_one() Merge definitions of array_type_nelts_top() c: Add __elementsof__ operator 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 | 31 +++-- 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/elementsof-compile.c | 115 +++++++++++++++++ gcc/testsuite/gcc.dg/elementsof-vla.c | 46 +++++++ gcc/testsuite/gcc.dg/elementsof.c | 150 ++++++++++++++++++++++ gcc/tree.cc | 17 ++- gcc/tree.h | 3 +- 28 files changed, 599 insertions(+), 79 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/elementsof-compile.c create mode 100644 gcc/testsuite/gcc.dg/elementsof-vla.c create mode 100644 gcc/testsuite/gcc.dg/elementsof.c Range-diff against v8: 1: a6aa38c9013 = 1: a6aa38c9013 gcc/: Rename array_type_nelts() => array_type_nelts_minus_one() 2: 43300a17e4a ! 2: 4ce16ee4dfe Merge definitions of array_type_nelts_top() @@ Commit message Merge definitions of array_type_nelts_top() There were two identical definitions, and none of them are available - where they are needed for implementing __lengthof__. Merge them, and + where they are needed for implementing __elementsof__. Merge them, and provide the single definition in gcc/tree.{h,cc}, where it's available - for __lengthof__, which will be added in the following commit. + for __elementsof__, which will be added in the following commit. gcc/ChangeLog: 3: e6af87d54af ! 3: caae5dbecb3 c: Add __lengthof__ operator @@ Metadata Author: Alejandro Colomar <a...@kernel.org> ## Commit message ## - c: Add __lengthof__ operator + c: Add __elementsof__ operator This operator is similar to sizeof but can only be applied to an array, - and returns its length (number of elements). + and returns its number of elements. FUTURE DIRECTIONS: - We should make it work with array parameters to functions, - and somehow magically return the length designator of the array, + and somehow magically return the number of elements of the array, regardless of it being really a pointer. - Fix support for [0]. @@ Commit message Cc: Florian Weimer <fwei...@redhat.com> Cc: Andreas Schwab <sch...@linux-m68k.org> Cc: Timm Baeder <tbae...@redhat.com> + Cc: Daniel Plakosh <dplak...@cert.org> + Cc: "A. Jiang" <d...@live.cn> + Cc: Eugene Zelenko <eugene.zele...@gmail.com> + Cc: Aaron Ballman <aaron.ball...@intel.com> + Cc: Paul Koning <paulkon...@comcast.net> gcc/ChangeLog: - * doc/extend.texi: Document __lengthof__ operator. - * target.h (enum type_context_kind): Add __lengthof__ operator. + * doc/extend.texi: Document __elementsof__ operator. + * target.h (enum type_context_kind): Add __elementsof__ operator. gcc/c-family/ChangeLog: * c-common.h: * c-common.def: - * c-common.cc (c_lengthof_type): Add __lengthof__ operator. + * c-common.cc (c_elementsof_type): Add __elementsof__ operator. gcc/c/ChangeLog: * c-tree.h - (c_expr_lengthof_expr, c_expr_lengthof_type): + (c_expr_elementsof_expr, c_expr_elementsof_type): * c-decl.cc (start_struct, finish_struct): (start_enum, finish_enum): * c-parser.cc (c_parser_sizeof_expression): - (c_parser_lengthof_expression): - (c_parser_sizeof_or_lengthof_expression): + (c_parser_elementsof_expression): + (c_parser_sizeof_or_elementsof_expression): (c_parser_unary_expression): * c-typeck.cc (build_external_ref): (record_maybe_used_decl, pop_maybe_used): (is_top_array_vla): - (c_expr_lengthof_expr, c_expr_lengthof_type): - Add __lengthof__operator. + (c_expr_elementsof_expr, c_expr_elementsof_type): + Add __elementsof__operator. gcc/cp/ChangeLog: - * operators.def: Add __lengthof__ operator. + * operators.def: Add __elementsof__ operator. gcc/testsuite/ChangeLog: - * gcc.dg/lengthof-compile.c: - * gcc.dg/lengthof-vla.c: - * gcc.dg/lengthof.c: Add tests for __lengthof__ operator. + * gcc.dg/elementsof-compile.c: + * gcc.dg/elementsof-vla.c: + * gcc.dg/elementsof.c: Add tests for __elementsof__ operator. Link: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2529.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 }, -+ { "__lengthof__", RID_LENGTHOF, 0 }, ++ { "__elementsof__", RID_ELEMENTSOF, 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, -+ that is, the number of elements in the array. */ ++/* Implement the lementsof keyword: ++ Return the number of elements of an array. */ + +tree -+c_lengthof_type (location_t loc, tree type) ++c_elementsof_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 %<lengthof%> to type %qT", type); ++ error_at (loc, "invalid application of %<elementsof%> to type %qT", type); + return error_mark_node; + } + if (!COMPLETE_TYPE_P (type)) + { + error_at (loc, -+ "invalid application of %<lengthof%> to incomplete type %qT", ++ "invalid application of %<elementsof%> 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 'lengthof' expression. */ -+DEFTREECODE (LENGTHOF_EXPR, "lengthof_expr", tcc_expression, 1) ++/* Represents a 'elementsof' expression. */ ++DEFTREECODE (ELEMENTSOF_EXPR, "elementsof_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_LENGTHOF, ++ RID_ELEMENTSOF, 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_lengthof_type (location_t, tree); ++extern tree c_elementsof_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, 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)) ++ if (warn_cxx_compat ++ && (in_sizeof || in_typeof || in_alignof || in_elementsof)) 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" -+ : "lengthof")))); ++ : "elementsof")))); 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_lengthof) ++ && !in_sizeof && !in_typeof && !in_alignof && !in_elementsof) 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 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)) ++ if (warn_cxx_compat && (in_sizeof || in_typeof || in_alignof || in_elementsof)) 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" -+ : "lengthof")))); ++ : "elementsof")))); 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_lengthof) ++ && !in_sizeof && !in_typeof && !in_alignof && !in_elementsof) 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_lengthof_expression (parser, RID_SIZEOF) \ ++ c_parser_sizeof_or_elementsof_expression (parser, RID_SIZEOF) \ +) -+#define c_parser_lengthof_expression(parser) \ ++#define c_parser_elementsof_expression(parser) \ +( \ -+ c_parser_sizeof_or_lengthof_expression (parser, RID_LENGTHOF) \ ++ c_parser_sizeof_or_elementsof_expression (parser, RID_ELEMENTSOF) \ +) + /* 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_lengthof_expression (c_parser *, enum rid); ++static struct c_expr c_parser_sizeof_or_elementsof_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 *); static struct c_expr c_parser_postfix_expression_after_paren_type (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_LENGTHOF: -+ return c_parser_lengthof_expression (parser); ++ case RID_ELEMENTSOF: ++ return c_parser_elementsof_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_lengthof_expression (c_parser *parser, enum rid rid) ++c_parser_sizeof_or_elementsof_expression (c_parser *parser, enum rid rid) { -+ const char *op_name = (rid == RID_LENGTHOF) ? "lengthof" : "sizeof"; ++ const char *op_name = (rid == RID_ELEMENTSOF) ? "elementsof" : "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_LENGTHOF) -+ in_lengthof++; ++ if (rid == RID_ELEMENTSOF) ++ in_elementsof++; + 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_LENGTHOF) -+ in_lengthof--; ++ if (rid == RID_ELEMENTSOF) ++ in_elementsof--; + 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_LENGTHOF) ++ if (rid == RID_ELEMENTSOF) + { -+ in_lengthof--; -+ result = c_expr_lengthof_type (expr_loc, type_name); ++ in_elementsof--; ++ result = c_expr_elementsof_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_LENGTHOF) -+ in_lengthof--; ++ if (rid == RID_ELEMENTSOF) ++ in_elementsof--; + 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_LENGTHOF) -+ result = c_expr_lengthof_expr (expr_loc, expr); ++ if (rid == RID_ELEMENTSOF) ++ result = c_expr_elementsof_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_lengthof; ++extern int in_elementsof; 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_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 c_expr_elementsof_expr (location_t, struct c_expr); ++extern struct c_expr c_expr_elementsof_type (location_t loc, ++ struct c_type_name *); extern struct c_expr parser_build_unary_op (location_t, enum tree_code, struct c_expr); extern struct c_expr parser_build_binary_op (location_t, @@ gcc/c/c-typeck.cc: int in_alignof; /* The level of nesting inside "sizeof". */ int in_sizeof; -+/* The level of nesting inside "lengthof". */ -+int in_lengthof; ++/* The level of nesting inside "elementsof". */ ++int in_elementsof; + /* 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_lengthof) ++ if (!in_sizeof && !in_typeof && !in_elementsof) 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). */ ++ /* The level seen at (in_sizeof + in_typeof + in_elementsof). */ 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->level = in_sizeof + in_typeof + in_elementsof; 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_lengthof; ++ int cur_level = in_sizeof + in_typeof + in_elementsof; 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 lengthof applied to EXPR. */ ++/* Return the result of elementsof applied to EXPR. */ + +struct c_expr -+c_expr_lengthof_expr (location_t loc, struct c_expr expr) ++c_expr_elementsof_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_lengthof_type (loc, TREE_TYPE (folded_expr)); ++ ret.value = c_elementsof_type (loc, TREE_TYPE (folded_expr)); + c_last_sizeof_arg = expr.value; + c_last_sizeof_loc = loc; -+ ret.original_code = LENGTHOF_EXPR; ++ ret.original_code = ELEMENTSOF_EXPR; + ret.original_type = NULL; + ret.m_decimal = 0; + if (is_top_array_vla (TREE_TYPE (folded_expr))) + { -+ /* lengthof is evaluated when given a vla. */ ++ /* elementsof 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 -+ name passed to _lengthof (rather than the type itself). LOC is the ++/* Return the result of elementsof applied to T, a structure for the type ++ name passed to elementsof (rather than the type itself). LOC is the + location of the original expression. */ + +struct c_expr -+c_expr_lengthof_type (location_t loc, struct c_type_name *t) ++c_expr_elementsof_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_lengthof_type (loc, type); ++ ret.value = c_elementsof_type (loc, type); + c_last_sizeof_arg = type; + c_last_sizeof_loc = loc; -+ ret.original_code = LENGTHOF_EXPR; ++ ret.original_code = ELEMENTSOF_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 lengthof does not get folded to a constant by ++ the result of elementsof 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 elementsof 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 ("__elementsof__", ELEMENTSOF_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 Length -+@section Determining the Length of Arrays -+@cindex lengthof -+@cindex length -+@cindex array length ++@node elementsof ++@section Determining the Number of Elements of Arrays ++@cindex elementsof ++@cindex number of elements + -+The keyword @code{__lengthof__} determines the length of an array operand, ++The keyword @code{__elemetsf__} 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]; -+__lengthof__ (a); // returns n -+__lengthof__ (int [7][3]); // returns 7 ++__elemetsf__ (a); // returns n ++__elemetsf__ (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 -+__lengthof__ (int [7][n++]); // integer constant expression -+__lengthof__ (int [n++][7]); // run-time value; n++ is evaluated ++__elemetsf__ (int [7][n++]); // integer constant expression ++__elemetsf__ (int [n++][7]); // run-time value; n++ is evaluated +@end smallexample + @node Inline @@ gcc/target.h: enum type_context_kind { /* Directly measuring the alignment of T. */ TCTX_ALIGNOF, -+ /* Directly measuring the length of array T. */ -+ TCTX_LENGTHOF, ++ /* Directly measuring the number of elements of array T. */ ++ TCTX_ELEMENTSOF, + /* Creating objects of type T with static storage duration. */ TCTX_STATIC_STORAGE, - ## gcc/testsuite/gcc.dg/lengthof-compile.c (new) ## + ## gcc/testsuite/gcc.dg/elementsof-compile.c (new) ## @@ +/* { dg-do compile } */ +/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */ @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new) +static int w[] = {1, 2, 3}; + +static int z[0]; -+static int y[__lengthof__(z)]; ++static int y[__elementsof__(z)]; + +void +automatic(void) +{ -+ __lengthof__ (w); ++ __elementsof__ (w); +} + +void +incomplete (int p[]) +{ -+ __lengthof__ (x); /* { dg-error "incomplete" } */ ++ __elementsof__ (x); /* { dg-error "incomplete" } */ + + /* We want to support the following one in the future, + but for now it should fail. */ -+ __lengthof__ (p); /* { dg-error "invalid" } */ ++ __elementsof__ (p); /* { dg-error "invalid" } */ +} + +void @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new) + int fam[]; + } s; + -+ __lengthof__ (s.fam); /* { dg-error "incomplete" } */ ++ __elementsof__ (s.fam); /* { dg-error "incomplete" } */ +} + -+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 fix_fix (int i, char (*a)[3][5], int (*x)[__elementsof__ (*a)]); ++void fix_var (int i, char (*a)[3][i], int (*x)[__elementsof__ (*a)]); ++void fix_uns (int i, char (*a)[3][*], int (*x)[__elementsof__ (*a)]); + +void +func (void) @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new) + int x[3]; + } s; + -+ __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" } */ ++ __elementsof__ (x); /* { dg-error "invalid" } */ ++ __elementsof__ (int); /* { dg-error "invalid" } */ ++ __elementsof__ (s); /* { dg-error "invalid" } */ ++ __elementsof__ (struct s); /* { dg-error "invalid" } */ ++ __elementsof__ (&x); /* { dg-error "invalid" } */ ++ __elementsof__ (p); /* { dg-error "invalid" } */ ++ __elementsof__ (int *); /* { dg-error "invalid" } */ ++ __elementsof__ (&s.x); /* { dg-error "invalid" } */ ++ __elementsof__ (int (*)[3]); /* { dg-error "invalid" } */ +} + +static int f1(); @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new) +{ + int b[n][n]; + -+ __lengthof__ (a[f1()]); -+ __lengthof__ (b[f2()]); ++ __elementsof__ (a[f1()]); ++ __elementsof__ (b[f2()]); +} + +void +no_parens(void) +{ -+ __lengthof__ a; -+ __lengthof__ *a; -+ __lengthof__ (int [3]) {}; ++ __elementsof__ a; ++ __elementsof__ *a; ++ __elementsof__ (int [3]) {}; + -+ __lengthof__ int [3]; /* { dg-error "expected expression before" } */ ++ __elementsof__ int [3]; /* { dg-error "expected expression before" } */ +} + +void @@ gcc/testsuite/gcc.dg/lengthof-compile.c (new) +{ + int n = 7; + -+ _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); ++ _Static_assert (__elementsof__ (int [3][n]) == 3); ++ _Static_assert (__elementsof__ (int [n][3]) == 7); /* { dg-error "not constant" } */ ++ _Static_assert (__elementsof__ (int [0][3]) == 0); ++ _Static_assert (__elementsof__ (int [0]) == 0); + -+ /* FIXME: lengthof(int [0][n]) should result in a constant expression. */ -+ _Static_assert (__lengthof__ (int [0][n]) == 0); /* { dg-error "not constant" } */ ++ /* FIXME: elementsof(int [0][n]) should result in a constant expression. */ ++ _Static_assert (__elementsof__ (int [0][n]) == 0); /* { dg-error "not constant" } */ +} - ## gcc/testsuite/gcc.dg/lengthof-vla.c (new) ## + ## gcc/testsuite/gcc.dg/elementsof-vla.c (new) ## @@ +/* { dg-do compile } */ +/* { dg-options "-Wno-pedantic -Wvla-parameter" } */ + +void fix_fix (int i, + char (*a)[3][5], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void fix_var (int i, + char (*a)[3][i], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void fix_uns (int i, + char (*a)[3][*], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); + +void zro_fix (int i, + char (*a)[0][5], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void zro_var (int i, + char (*a)[0][i], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void zro_uns (int i, + char (*a)[0][*], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); + +void var_fix (int i, + char (*a)[i][5], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */ ++ int (*x)[__elementsof__ (*a)]); /* dg-warn "variable" */ +void var_var (int i, + char (*a)[i][i], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */ ++ int (*x)[__elementsof__ (*a)]); /* dg-warn "variable" */ +void var_uns (int i, + char (*a)[i][*], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); /* dg-warn "variable" */ ++ int (*x)[__elementsof__ (*a)]); /* dg-warn "variable" */ + +void uns_fix (int i, + char (*a)[*][5], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void uns_var (int i, + char (*a)[*][i], /* dg-warn "variable" */ -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); +void uns_uns (int i, + char (*a)[*][*], -+ int (*x)[__lengthof__ (*a)]); ++ int (*x)[__elementsof__ (*a)]); + +// Can't test due to bug: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116284> +//static int z2[0]; -+//static int y2[__lengthof__(z2)]; ++//static int y2[__elementsof__(z2)]; - ## gcc/testsuite/gcc.dg/lengthof.c (new) ## + ## gcc/testsuite/gcc.dg/elementsof.c (new) ## @@ +/* { dg-do run } */ +/* { dg-options "-Wno-declaration-after-statement -Wno-pedantic -Wno-vla" } */ @@ gcc/testsuite/gcc.dg/lengthof.c (new) +{ + short a[7]; + -+ static_assert (__lengthof__ (a) == 7); -+ static_assert (__lengthof__ (long [0]) == 0); -+ static_assert (__lengthof__ (unsigned [99]) == 99); ++ static_assert (__elementsof__ (a) == 7); ++ static_assert (__elementsof__ (long [0]) == 0); ++ static_assert (__elementsof__ (unsigned [99]) == 99); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int a[] = {1, 2, 3}; + int z[] = {}; + -+ static_assert (__lengthof__ (a) == 3); -+ static_assert (__lengthof__ (z) == 0); ++ static_assert (__elementsof__ (a) == 3); ++ static_assert (__elementsof__ (z) == 0); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) + unsigned n; + + n = 99; -+ assert (__lengthof__ (short [n - 10]) == 99 - 10); ++ assert (__elementsof__ (short [n - 10]) == 99 - 10); + + int v[n / 2]; -+ assert (__lengthof__ (v) == 99 / 2); ++ assert (__elementsof__ (v) == 99 / 2); + + n = 0; + int z[n]; -+ assert (__lengthof__ (z) == 0); ++ assert (__elementsof__ (z) == 0); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int a[8]; + } s; + -+ static_assert (__lengthof__ (s.a) == 8); ++ static_assert (__elementsof__ (s.a) == 8); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int i; + + i = 7; -+ assert (__lengthof__ (struct {int x;}[i++]) == 7); ++ assert (__elementsof__ (struct {int x;}[i++]) == 7); + assert (i == 7 + 1); + + int v[i]; + int (*p)[i]; + p = &v; -+ assert (__lengthof__ (*p++) == i); ++ assert (__elementsof__ (*p++) == i); + assert (p - 1 == &v); +} + @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int i; + + i = 3; -+ static_assert (__lengthof__ (struct {int x[i++];}[3]) == 3); ++ static_assert (__elementsof__ (struct {int x[i++];}[3]) == 3); + assert (i == 3); +} + @@ gcc/testsuite/gcc.dg/lengthof.c (new) +array_noeval (void) +{ + long a[5]; -+ long (*p)[__lengthof__ (a)]; ++ long (*p)[__elementsof__ (a)]; + + p = &a; -+ static_assert (__lengthof__ (*p++) == 5); ++ static_assert (__elementsof__ (*p++) == 5); + assert (p == &a); +} + @@ gcc/testsuite/gcc.dg/lengthof.c (new) +{ + int i; + -+ static_assert (__lengthof__ (int [0][4]) == 0); ++ static_assert (__elementsof__ (int [0][4]) == 0); + i = 3; -+ assert (__lengthof__ (int [0][i]) == 0); ++ assert (__elementsof__ (int [0][i]) == 0); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) +{ + int i; + -+ static_assert (__lengthof__ (int [7][4]) == 7); ++ static_assert (__elementsof__ (int [7][4]) == 7); + i = 3; -+ static_assert (__lengthof__ (int [7][i]) == 7); ++ static_assert (__elementsof__ (int [7][i]) == 7); +} + +void @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int i, j; + + i = 7; -+ assert (__lengthof__ (int [i++][4]) == 7); ++ assert (__elementsof__ (int [i++][4]) == 7); + assert (i == 7 + 1); + + i = 9; + j = 3; -+ assert (__lengthof__ (int [i++][j]) == 9); ++ assert (__elementsof__ (int [i++][j]) == 9); + assert (i == 9 + 1); +} + @@ gcc/testsuite/gcc.dg/lengthof.c (new) + int a[7]; + int v[n]; + -+ static_assert (__lengthof__ a == 7); -+ assert (__lengthof__ v == 3); ++ static_assert (__elementsof__ a == 7); ++ assert (__elementsof__ v == 3); +} + +int -- 2.45.2
signature.asc
Description: PGP signature