public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/5] misc: Sync cdefs.h with gnulib
@ 2021-01-13 16:58 Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH 2/5] malloc: Sync dynarray " Adhemerval Zanella
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 16:58 UTC (permalink / raw)
  To: libc-alpha

It adds __glibc_has_builtin, __glibc_has_extension, and
__attribute_maybe_unused__ alongsize with some fixes.

The only difference is:

--- ../../gnulib/gnulib-lib/lib/cdefs.h 2021-01-08 17:10:32.683471041 -0300
+++ misc/sys/cdefs.h    2021-01-13 13:34:46.409398805 -0300
@@ -483,7 +483,7 @@

 /* The #ifndef lets Gnulib avoid including these on non-glibc
    platforms, where the includes typically do not exist.  */
-#ifndef __WORDSIZE
+#ifdef __GLIBC__
 # include <bits/wordsize.h>
 # include <bits/long-double.h>
 #endif

Where __WORDSIZE does not play well with internal cdefs.h that also
uses __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI.

Checked on x86_64-linux-gnu.
---
 misc/sys/cdefs.h | 142 ++++++++++++++++++++++++++++-------------------
 1 file changed, 84 insertions(+), 58 deletions(-)

diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index 57ca262bdf..12a2f3c249 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -34,7 +34,27 @@
 #undef	__P
 #undef	__PMT
 
-#ifdef __GNUC__
+/* Compilers that lack __has_attribute may object to
+       #if defined __has_attribute && __has_attribute (...)
+   even though they do not need to evaluate the right-hand side of the &&.
+   Similarly for __has_builtin, etc.  */
+#ifdef __has_attribute
+# define __glibc_has_attribute(attr) __has_attribute (attr)
+#else
+# define __glibc_has_attribute(attr) 0
+#endif
+#ifdef __has_builtin
+# define __glibc_has_builtin(name) __has_builtin (name)
+#else
+# define __glibc_has_builtin(name) 0
+#endif
+#ifdef __has_extension
+# define __glibc_has_extension(ext) __has_extension (ext)
+#else
+# define __glibc_has_extension(ext) 0
+#endif
+
+#if defined __GNUC__ || defined __clang__
 
 /* All functions, except those with callbacks or those that
    synchronize memory, are leaf functions.  */
@@ -48,16 +68,17 @@
 
 /* GCC can always grok prototypes.  For C++ programs we add throw()
    to help it optimize the function calls.  But this only works with
-   gcc 2.8.x and egcs.  For gcc 3.2 and up we even mark C functions
+   gcc 2.8.x and egcs.  For gcc 3.4 and up we even mark C functions
    as non-throwing using a function attribute since programs can use
    the -fexceptions options for C code as well.  */
-# if !defined __cplusplus && __GNUC_PREREQ (3, 3)
+# if !defined __cplusplus \
+     && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
 #  define __THROW	__attribute__ ((__nothrow__ __LEAF))
 #  define __THROWNL	__attribute__ ((__nothrow__))
 #  define __NTH(fct)	__attribute__ ((__nothrow__ __LEAF)) fct
 #  define __NTHNL(fct)  __attribute__ ((__nothrow__)) fct
 # else
-#  if defined __cplusplus && __GNUC_PREREQ (2,8)
+#  if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4)
 #   if __cplusplus >= 201103L
 #    define __THROW	noexcept (true)
 #   else
@@ -74,7 +95,7 @@
 #  endif
 # endif
 
-#else	/* Not GCC.  */
+#else	/* Not GCC or clang.  */
 
 # if (defined __cplusplus						\
       || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
@@ -87,16 +108,7 @@
 # define __THROWNL
 # define __NTH(fct)	fct
 
-#endif	/* GCC.  */
-
-/* Compilers that are not clang may object to
-       #if defined __clang__ && __has_extension(...)
-   even though they do not need to evaluate the right-hand side of the &&.  */
-#if defined __clang__ && defined __has_extension
-# define __glibc_clang_has_extension(ext) __has_extension (ext)
-#else
-# define __glibc_clang_has_extension(ext) 0
-#endif
+#endif	/* GCC || clang.  */
 
 /* These two macros are not used in glibc anymore.  They are kept here
    only because some other projects expect the macros to be defined.  */
@@ -149,11 +161,11 @@
    Headers that should use flexible arrays only if they're "real"
    (e.g. only if they won't affect sizeof()) should test
    #if __glibc_c99_flexarr_available.  */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L && !defined __HP_cc
 # define __flexarr	[]
 # define __glibc_c99_flexarr_available 1
-#elif __GNUC_PREREQ (2,97)
-/* GCC 2.97 supports C99 flexible array members as an extension,
+#elif __GNUC_PREREQ (2,97) || defined __clang__
+/* GCC 2.97 and clang support C99 flexible array members as an extension,
    even when in C89 mode or compiling C++ (any version).  */
 # define __flexarr	[]
 # define __glibc_c99_flexarr_available 1
@@ -179,7 +191,7 @@
    Example:
    int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */
 
-#if defined __GNUC__ && __GNUC__ >= 2
+#if (defined __GNUC__ && __GNUC__ >= 2) || (__clang_major__ >= 4)
 
 # define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias))
 # ifdef __cplusplus
@@ -204,17 +216,17 @@
 */
 #endif
 
-/* GCC has various useful declarations that can be made with the
-   `__attribute__' syntax.  All of the ways we use this do fine if
-   they are omitted for compilers that don't understand it. */
-#if !defined __GNUC__ || __GNUC__ < 2
+/* GCC and clang have various useful declarations that can be made with
+   the '__attribute__' syntax.  All of the ways we use this do fine if
+   they are omitted for compilers that don't understand it.  */
+#if !(defined __GNUC__ || defined __clang__)
 # define __attribute__(xyz)	/* Ignore */
 #endif
 
 /* At some point during the gcc 2.96 development the `malloc' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96)
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
 # define __attribute_malloc__ __attribute__ ((__malloc__))
 #else
 # define __attribute_malloc__ /* Ignore */
@@ -232,23 +244,31 @@
 /* At some point during the gcc 2.96 development the `pure' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96)
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__)
 # define __attribute_pure__ __attribute__ ((__pure__))
 #else
 # define __attribute_pure__ /* Ignore */
 #endif
 
 /* This declaration tells the compiler that the value is constant.  */
-#if __GNUC_PREREQ (2,5)
+#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__)
 # define __attribute_const__ __attribute__ ((__const__))
 #else
 # define __attribute_const__ /* Ignore */
 #endif
 
+#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
+# define __attribute_maybe_unused__ [[__maybe_unused__]]
+#elif __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__)
+# define __attribute_maybe_unused__ __attribute__ ((__unused__))
+#else
+# define __attribute_maybe_unused__ /* Ignore */
+#endif
+
 /* At some point during the gcc 3.1 development the `used' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (3,1)
+#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__)
 # define __attribute_used__ __attribute__ ((__used__))
 # define __attribute_noinline__ __attribute__ ((__noinline__))
 #else
@@ -257,7 +277,7 @@
 #endif
 
 /* Since version 3.2, gcc allows marking deprecated functions.  */
-#if __GNUC_PREREQ (3,2)
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__)
 # define __attribute_deprecated__ __attribute__ ((__deprecated__))
 #else
 # define __attribute_deprecated__ /* Ignore */
@@ -267,7 +287,7 @@
    when a deprecated function is used.  clang claims to be gcc 4.2, but
    may also support this feature.  */
 #if __GNUC_PREREQ (4,5) \
-    || __glibc_clang_has_extension (__attribute_deprecated_with_message__)
+    || __glibc_has_extension (__attribute_deprecated_with_message__)
 # define __attribute_deprecated_msg__(msg) \
 	 __attribute__ ((__deprecated__ (msg)))
 #else
@@ -280,7 +300,7 @@
    If several `format_arg' attributes are given for the same function, in
    gcc-3.0 and older, all but the last one are ignored.  In newer gccs,
    all designated arguments are considered.  */
-#if __GNUC_PREREQ (2,8)
+#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__)
 # define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
 #else
 # define __attribute_format_arg__(x) /* Ignore */
@@ -290,27 +310,30 @@
    attribute for functions was introduced.  We don't want to use it
    unconditionally (although this would be possible) since it
    generates warnings.  */
-#if __GNUC_PREREQ (2,97)
+#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__)
 # define __attribute_format_strfmon__(a,b) \
   __attribute__ ((__format__ (__strfmon__, a, b)))
 #else
 # define __attribute_format_strfmon__(a,b) /* Ignore */
 #endif
 
-/* The nonull function attribute allows to mark pointer parameters which
-   must not be NULL.  */
-#if __GNUC_PREREQ (3,3)
-# define __nonnull(params) __attribute__ ((__nonnull__ params))
-#else
-# define __nonnull(params)
+/* The nonnull function attribute marks pointer parameters that
+   must not be NULL.  Do not define __nonnull if it is already defined,
+   for portability when this file is used in Gnulib.  */
+#ifndef __nonnull
+# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
+#  define __nonnull(params) __attribute__ ((__nonnull__ params))
+# else
+#  define __nonnull(params)
+# endif
 #endif
 
 /* If fortification mode, we warn about unused results of certain
    function calls which can lead to problems.  */
-#if __GNUC_PREREQ (3,4)
+#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__)
 # define __attribute_warn_unused_result__ \
    __attribute__ ((__warn_unused_result__))
-# if __USE_FORTIFY_LEVEL > 0
+# if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
 #  define __wur __attribute_warn_unused_result__
 # endif
 #else
@@ -321,7 +344,7 @@
 #endif
 
 /* Forces a function to be always inlined.  */
-#if __GNUC_PREREQ (3,2)
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__)
 /* The Linux kernel defines __always_inline in stddef.h (283d7573), and
    it conflicts with this definition.  Therefore undefine it first to
    allow either header to be included first.  */
@@ -334,7 +357,7 @@
 
 /* Associate error messages with the source location of the call site rather
    than with the source location inside the function.  */
-#if __GNUC_PREREQ (4,3)
+#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__)
 # define __attribute_artificial__ __attribute__ ((__artificial__))
 #else
 # define __attribute_artificial__ /* Ignore */
@@ -377,12 +400,14 @@
    run in pedantic mode if the uses are carefully marked using the
    `__extension__' keyword.  But this is not generally available before
    version 2.8.  */
-#if !__GNUC_PREREQ (2,8)
+#if !(__GNUC_PREREQ (2,8) || defined __clang__)
 # define __extension__		/* Ignore */
 #endif
 
-/* __restrict is known in EGCS 1.2 and above. */
-#if !__GNUC_PREREQ (2,92)
+/* __restrict is known in EGCS 1.2 and above, and in clang.
+   It works also in C++ mode (outside of arrays), but only when spelled
+   as '__restrict', not 'restrict'.  */
+#if !(__GNUC_PREREQ (2,92) || __clang_major__ >= 3)
 # if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
 #  define __restrict	restrict
 # else
@@ -392,8 +417,9 @@
 
 /* ISO C99 also allows to declare arrays as non-overlapping.  The syntax is
      array_name[restrict]
-   GCC 3.1 supports this.  */
-#if __GNUC_PREREQ (3,1) && !defined __GNUG__
+   GCC 3.1 and clang support this.
+   This syntax is not usable in C++ mode.  */
+#if (__GNUC_PREREQ (3,1) || __clang_major__ >= 3) && !defined __cplusplus
 # define __restrict_arr	__restrict
 #else
 # ifdef __GNUC__
@@ -408,7 +434,7 @@
 # endif
 #endif
 
-#if __GNUC__ >= 3
+#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect)
 # define __glibc_unlikely(cond)	__builtin_expect ((cond), 0)
 # define __glibc_likely(cond)	__builtin_expect ((cond), 1)
 #else
@@ -416,15 +442,10 @@
 # define __glibc_likely(cond)	(cond)
 #endif
 
-#ifdef __has_attribute
-# define __glibc_has_attribute(attr)	__has_attribute (attr)
-#else
-# define __glibc_has_attribute(attr)	0
-#endif
-
 #if (!defined _Noreturn \
      && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
-     &&  !__GNUC_PREREQ (4,7))
+     &&  !(__GNUC_PREREQ (4,7) \
+           || (3 < __clang_major__ + (5 <= __clang_minor__))))
 # if __GNUC_PREREQ (2,8)
 #  define _Noreturn __attribute__ ((__noreturn__))
 # else
@@ -453,14 +474,19 @@
 
 #if (!defined _Static_assert && !defined __cplusplus \
      && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
-     && (!__GNUC_PREREQ (4, 6) || defined __STRICT_ANSI__))
+     && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \
+         || defined __STRICT_ANSI__))
 # define _Static_assert(expr, diagnostic) \
     extern int (*__Static_assert_function (void)) \
       [!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
 #endif
 
-#include <bits/wordsize.h>
-#include <bits/long-double.h>
+/* The #ifndef lets Gnulib avoid including these on non-glibc
+   platforms, where the includes typically do not exist.  */
+#ifdef __GLIBC__
+# include <bits/wordsize.h>
+# include <bits/long-double.h>
+#endif
 
 #if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
 # ifdef __REDIRECT
@@ -550,7 +576,7 @@ _Static_assert (0, "IEEE 128-bits long double requires redirection on this platf
    check is required to enable the use of generic selection.  */
 #if !defined __cplusplus \
     && (__GNUC_PREREQ (4, 9) \
-	|| __glibc_clang_has_extension (c_generic_selections) \
+	|| __glibc_has_extension (c_generic_selections) \
 	|| (!defined __GNUC__ && defined __STDC_VERSION__ \
 	    && __STDC_VERSION__ >= 201112L))
 # define __HAVE_GENERIC_SELECTION 1
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/5] malloc: Sync dynarray with gnulib
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
@ 2021-01-13 16:58 ` Adhemerval Zanella
  2021-02-09 19:12   ` Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH v2 3/5] regex: remove alloca usage on regex set_regs Adhemerval Zanella
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 16:58 UTC (permalink / raw)
  To: libc-alpha

It syncs with gnulib version a8bac4d49.  The main changes are:

  - Remove the usage of anonymous union within DYNARRAY_STRUCT.
  - Use DYNARRAY_FREE instead of DYNARRAY_NAME (free) so that
    Gnulib does not change 'free' to 'rpl_free'.
  - Use __nonnull instead of __attribute__ ((nonnull ())).
  - Use __attribute_maybe_unused__ instead of
    __attribute__ ((unused, nonnull (1))).
  - Use of _Noreturn instead of _attribute__ ((noreturn)).

The only difference with gnulib is:

--- ../../gnulib/gnulib-lib/lib/malloc/dynarray_at_failure.c
+++ malloc/dynarray_at_failure.c
@@ -18,7 +18,6 @@

 #include <dynarray.h>
 #include <stdio.h>
-#include <stdlib.h>

 void
 __libc_dynarray_at_failure (size_t size, size_t index)
@@ -28,6 +27,7 @@
   __snprintf (buf, sizeof (buf), "Fatal glibc error: "
               "array index %zu not less than array length %zu\n",
               index, size);
+ __libc_fatal (buf);
 #else
  abort ();
 #endif

It seems a wrong sync from gnulib.

Checked on x86_64-linux-gnu.
---
 malloc/dynarray-skeleton.c        | 128 +++++++++++++++---------------
 malloc/dynarray.h                 |   3 +-
 malloc/dynarray_at_failure.c      |   4 +
 malloc/dynarray_emplace_enlarge.c |   3 +-
 malloc/dynarray_resize.c          |   3 +-
 malloc/dynarray_resize_clear.c    |   4 +-
 malloc/tst-dynarray-fail.c        |   8 +-
 malloc/tst-dynarray-shared.h      |   4 +-
 malloc/tst-dynarray.c             |  22 ++---
 9 files changed, 95 insertions(+), 84 deletions(-)

diff --git a/malloc/dynarray-skeleton.c b/malloc/dynarray-skeleton.c
index e552664bc5..5b9f37bdd6 100644
--- a/malloc/dynarray-skeleton.c
+++ b/malloc/dynarray-skeleton.c
@@ -135,7 +135,7 @@ struct DYNARRAY_STRUCT
       size_t allocated;
       DYNARRAY_ELEMENT *array;
     } dynarray_header;
-  };
+  } u;
 
 #if DYNARRAY_HAVE_SCRATCH
   /* Initial inline allocation.  */
@@ -150,6 +150,10 @@ struct DYNARRAY_STRUCT
 #define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
 #define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
 
+/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
+   so that Gnulib does not change 'free' to 'rpl_free'.  */
+#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
+
 /* Address of the scratch buffer if any.  */
 #if DYNARRAY_HAVE_SCRATCH
 # define DYNARRAY_SCRATCH(list) (list)->scratch
@@ -177,10 +181,10 @@ static inline void
 DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
 {
 #if DYNARRAY_HAVE_SCRATCH
-  if (list->dynarray_header.array != list->scratch)
-    free (list->dynarray_header.array);
+  if (list->u.dynarray_header.array != list->scratch)
+    free (list->u.dynarray_header.array);
 #else
-  free (list->dynarray_header.array);
+  free (list->u.dynarray_header.array);
 #endif
 }
 
@@ -188,86 +192,86 @@ DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
 
 /* Initialize a dynamic array object.  This must be called before any
    use of the object.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static void
 DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
 {
-  list->dynarray_header.used = 0;
-  list->dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
-  list->dynarray_header.array = DYNARRAY_SCRATCH (list);
+  list->u.dynarray_header.used = 0;
+  list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
+  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
 }
 
 /* Deallocate the dynamic array and its elements.  */
-__attribute__ ((unused, nonnull (1)))
+__attribute_maybe_unused__ __nonnull ((1))
 static void
-DYNARRAY_NAME (free) (struct DYNARRAY_STRUCT *list)
+DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
 {
   DYNARRAY_NAME (free__elements__)
-    (list->dynarray_header.array, list->dynarray_header.used);
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
   DYNARRAY_NAME (free__array__) (list);
   DYNARRAY_NAME (init) (list);
 }
 
 /* Return true if the dynamic array is in an error state.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static inline bool
 DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
 {
-  return list->dynarray_header.allocated == __dynarray_error_marker ();
+  return list->u.dynarray_header.allocated == __dynarray_error_marker ();
 }
 
 /* Mark the dynamic array as failed.  All elements are deallocated as
    a side effect.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static void
 DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
 {
   DYNARRAY_NAME (free__elements__)
-    (list->dynarray_header.array, list->dynarray_header.used);
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
   DYNARRAY_NAME (free__array__) (list);
-  list->dynarray_header.array = DYNARRAY_SCRATCH (list);
-  list->dynarray_header.used = 0;
-  list->dynarray_header.allocated = __dynarray_error_marker ();
+  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
+  list->u.dynarray_header.used = 0;
+  list->u.dynarray_header.allocated = __dynarray_error_marker ();
 }
 
 /* Return the number of elements which have been added to the dynamic
    array.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static inline size_t
 DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
 {
-  return list->dynarray_header.used;
+  return list->u.dynarray_header.used;
 }
 
 /* Return a pointer to the array element at INDEX.  Terminate the
    process if INDEX is out of bounds.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static inline DYNARRAY_ELEMENT *
 DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
 {
   if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
     __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
-  return list->dynarray_header.array + index;
+  return list->u.dynarray_header.array + index;
 }
 
 /* Return a pointer to the first array element, if any.  For a
    zero-length array, the pointer can be NULL even though the dynamic
    array has not entered the failure state.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static inline DYNARRAY_ELEMENT *
 DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
 {
-  return list->dynarray_header.array;
+  return list->u.dynarray_header.array;
 }
 
 /* Return a pointer one element past the last array element.  For a
    zero-length array, the pointer can be NULL even though the dynamic
    array has not entered the failure state.  */
-__attribute__ ((nonnull (1)))
+__nonnull ((1))
 static inline DYNARRAY_ELEMENT *
 DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
 {
-  return list->dynarray_header.array + list->dynarray_header.used;
+  return list->u.dynarray_header.array + list->u.dynarray_header.used;
 }
 
 /* Internal function.  Slow path for the add function below.  */
@@ -275,7 +279,7 @@ static void
 DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
 {
   if (__glibc_unlikely
-      (!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract,
+      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
                                          DYNARRAY_SCRATCH (list),
                                          sizeof (DYNARRAY_ELEMENT))))
     {
@@ -284,13 +288,13 @@ DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
     }
 
   /* Copy the new element and increase the array length.  */
-  list->dynarray_header.array[list->dynarray_header.used++] = item;
+  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
 }
 
 /* Add ITEM at the end of the array, enlarging it by one element.
    Mark *LIST as failed if the dynamic array allocation size cannot be
    increased.  */
-__attribute__ ((unused, nonnull (1)))
+__nonnull ((1))
 static inline void
 DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
 {
@@ -299,15 +303,15 @@ DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
     return;
 
   /* Enlarge the array if necessary.  */
-  if (__glibc_unlikely (list->dynarray_header.used
-                        == list->dynarray_header.allocated))
+  if (__glibc_unlikely (list->u.dynarray_header.used
+                        == list->u.dynarray_header.allocated))
     {
       DYNARRAY_NAME (add__) (list, item);
       return;
     }
 
   /* Copy the new element and increase the array length.  */
-  list->dynarray_header.array[list->dynarray_header.used++] = item;
+  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
 }
 
 /* Internal function.  Building block for the emplace functions below.
@@ -316,8 +320,8 @@ static inline DYNARRAY_ELEMENT *
 DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
 {
   DYNARRAY_ELEMENT *result
-    = &list->dynarray_header.array[list->dynarray_header.used];
-  ++list->dynarray_header.used;
+    = &list->u.dynarray_header.array[list->u.dynarray_header.used];
+  ++list->u.dynarray_header.used;
 #if defined (DYNARRAY_ELEMENT_INIT)
   DYNARRAY_ELEMENT_INIT (result);
 #elif defined (DYNARRAY_ELEMENT_FREE)
@@ -331,7 +335,7 @@ static DYNARRAY_ELEMENT *
 DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
 {
   if (__glibc_unlikely
-      (!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract,
+      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
                                          DYNARRAY_SCRATCH (list),
                                          sizeof (DYNARRAY_ELEMENT))))
     {
@@ -344,7 +348,7 @@ DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
 /* Allocate a place for a new element in *LIST and return a pointer to
    it.  The pointer can be NULL if the dynamic array cannot be
    enlarged due to a memory allocation failure.  */
-__attribute__ ((unused, warn_unused_result, nonnull (1)))
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
 static
 /* Avoid inlining with the larger initialization code.  */
 #if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
@@ -358,8 +362,8 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
     return NULL;
 
   /* Enlarge the array if necessary.  */
-  if (__glibc_unlikely (list->dynarray_header.used
-                        == list->dynarray_header.allocated))
+  if (__glibc_unlikely (list->u.dynarray_header.used
+                        == list->u.dynarray_header.allocated))
     return (DYNARRAY_NAME (emplace__) (list));
   return DYNARRAY_NAME (emplace__tail__) (list);
 }
@@ -368,32 +372,32 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
    existing size, new elements are added (which can be initialized).
    Otherwise, the list is truncated, and elements are freed.  Return
    false on memory allocation failure (and mark *LIST as failed).  */
-__attribute__ ((unused, nonnull (1)))
+__attribute_maybe_unused__ __nonnull ((1))
 static bool
 DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
 {
-  if (size > list->dynarray_header.used)
+  if (size > list->u.dynarray_header.used)
     {
       bool ok;
 #if defined (DYNARRAY_ELEMENT_INIT)
       /* The new elements have to be initialized.  */
-      size_t old_size = list->dynarray_header.used;
-      ok = __libc_dynarray_resize (&list->dynarray_abstract,
+      size_t old_size = list->u.dynarray_header.used;
+      ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
                                    size, DYNARRAY_SCRATCH (list),
                                    sizeof (DYNARRAY_ELEMENT));
       if (ok)
         for (size_t i = old_size; i < size; ++i)
           {
-            DYNARRAY_ELEMENT_INIT (&list->dynarray_header.array[i]);
+            DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
           }
 #elif defined (DYNARRAY_ELEMENT_FREE)
       /* Zero initialization is needed so that the elements can be
          safely freed.  */
       ok = __libc_dynarray_resize_clear
-        (&list->dynarray_abstract, size,
+        (&list->u.dynarray_abstract, size,
          DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
 #else
-      ok =  __libc_dynarray_resize (&list->dynarray_abstract,
+      ok =  __libc_dynarray_resize (&list->u.dynarray_abstract,
                                     size, DYNARRAY_SCRATCH (list),
                                     sizeof (DYNARRAY_ELEMENT));
 #endif
@@ -405,40 +409,40 @@ DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
     {
       /* The list has shrunk in size.  Free the removed elements.  */
       DYNARRAY_NAME (free__elements__)
-        (list->dynarray_header.array + size,
-         list->dynarray_header.used - size);
-      list->dynarray_header.used = size;
+        (list->u.dynarray_header.array + size,
+         list->u.dynarray_header.used - size);
+      list->u.dynarray_header.used = size;
       return true;
     }
 }
 
 /* Remove the last element of LIST if it is present.  */
-__attribute__ ((unused, nonnull (1)))
+__attribute_maybe_unused__ __nonnull ((1))
 static void
 DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
 {
   /* used > 0 implies that the array is the non-failed state.  */
-  if (list->dynarray_header.used > 0)
+  if (list->u.dynarray_header.used > 0)
     {
-      size_t new_length = list->dynarray_header.used - 1;
+      size_t new_length = list->u.dynarray_header.used - 1;
 #ifdef DYNARRAY_ELEMENT_FREE
-      DYNARRAY_ELEMENT_FREE (&list->dynarray_header.array[new_length]);
+      DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
 #endif
-      list->dynarray_header.used = new_length;
+      list->u.dynarray_header.used = new_length;
     }
 }
 
 /* Remove all elements from the list.  The elements are freed, but the
    list itself is not.  */
-__attribute__ ((unused, nonnull (1)))
+__attribute_maybe_unused__ __nonnull ((1))
 static void
 DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
 {
   /* free__elements__ does nothing if the list is in the failed
      state.  */
   DYNARRAY_NAME (free__elements__)
-    (list->dynarray_header.array, list->dynarray_header.used);
-  list->dynarray_header.used = 0;
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
+  list->u.dynarray_header.used = 0;
 }
 
 #ifdef DYNARRAY_FINAL_TYPE
@@ -448,13 +452,13 @@ DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
    stored in *RESULT if LIST refers to an empty list.  On success, the
    pointer in *RESULT is heap-allocated and must be deallocated using
    free.  */
-__attribute__ ((unused, warn_unused_result, nonnull (1, 2)))
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1, 2))
 static bool
 DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
                           DYNARRAY_FINAL_TYPE *result)
 {
   struct dynarray_finalize_result res;
-  if (__libc_dynarray_finalize (&list->dynarray_abstract,
+  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
                                 DYNARRAY_SCRATCH (list),
                                 sizeof (DYNARRAY_ELEMENT), &res))
     {
@@ -466,7 +470,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
   else
     {
       /* On error, we need to free all data.  */
-      DYNARRAY_NAME (free) (list);
+      DYNARRAY_FREE (list);
       errno = ENOMEM;
       return false;
     }
@@ -479,12 +483,12 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
    have a sentinel at the end).  If LENGTHP is not NULL, the array
    length is written to *LENGTHP.  *LIST is re-initialized and can be
    reused.  */
-__attribute__ ((unused, warn_unused_result, nonnull (1)))
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
 static DYNARRAY_ELEMENT *
 DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
 {
   struct dynarray_finalize_result res;
-  if (__libc_dynarray_finalize (&list->dynarray_abstract,
+  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
                                 DYNARRAY_SCRATCH (list),
                                 sizeof (DYNARRAY_ELEMENT), &res))
     {
@@ -497,7 +501,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
   else
     {
       /* On error, we need to free all data.  */
-      DYNARRAY_NAME (free) (list);
+      DYNARRAY_FREE (list);
       errno = ENOMEM;
       return NULL;
     }
diff --git a/malloc/dynarray.h b/malloc/dynarray.h
index 24ca1620d2..638c33f986 100644
--- a/malloc/dynarray.h
+++ b/malloc/dynarray.h
@@ -165,8 +165,7 @@ bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
 /* Internal function.  Terminate the process after an index error.
    SIZE is the number of elements of the dynamic array.  INDEX is the
    lookup index which triggered the failure.  */
-void __libc_dynarray_at_failure (size_t size, size_t index)
-  __attribute__ ((noreturn));
+_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
 
 #ifndef _ISOMAC
 libc_hidden_proto (__libc_dynarray_emplace_enlarge)
diff --git a/malloc/dynarray_at_failure.c b/malloc/dynarray_at_failure.c
index d27c0aebbc..88d9ee7f50 100644
--- a/malloc/dynarray_at_failure.c
+++ b/malloc/dynarray_at_failure.c
@@ -22,10 +22,14 @@
 void
 __libc_dynarray_at_failure (size_t size, size_t index)
 {
+#ifdef _LIBC
   char buf[200];
   __snprintf (buf, sizeof (buf), "Fatal glibc error: "
               "array index %zu not less than array length %zu\n",
               index, size);
  __libc_fatal (buf);
+#else
+ abort ();
+#endif
 }
 libc_hidden_def (__libc_dynarray_at_failure)
diff --git a/malloc/dynarray_emplace_enlarge.c b/malloc/dynarray_emplace_enlarge.c
index f98b0328df..ddfe306fcd 100644
--- a/malloc/dynarray_emplace_enlarge.c
+++ b/malloc/dynarray_emplace_enlarge.c
@@ -18,6 +18,7 @@
 
 #include <dynarray.h>
 #include <errno.h>
+#include <intprops.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -51,7 +52,7 @@ __libc_dynarray_emplace_enlarge (struct dynarray_header *list,
     }
 
   size_t new_size;
-  if (__builtin_mul_overflow (new_allocated, element_size, &new_size))
+  if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size))
     return false;
   void *new_array;
   if (list->array == scratch)
diff --git a/malloc/dynarray_resize.c b/malloc/dynarray_resize.c
index bb50e32f9a..5c60927f37 100644
--- a/malloc/dynarray_resize.c
+++ b/malloc/dynarray_resize.c
@@ -18,6 +18,7 @@
 
 #include <dynarray.h>
 #include <errno.h>
+#include <intprops.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -37,7 +38,7 @@ __libc_dynarray_resize (struct dynarray_header *list, size_t size,
      over-allocation here.  */
 
   size_t new_size_bytes;
-  if (__builtin_mul_overflow (size, element_size, &new_size_bytes))
+  if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes))
     {
       /* Overflow.  */
       __set_errno (ENOMEM);
diff --git a/malloc/dynarray_resize_clear.c b/malloc/dynarray_resize_clear.c
index 51d64fea5c..e893d1d58e 100644
--- a/malloc/dynarray_resize_clear.c
+++ b/malloc/dynarray_resize_clear.c
@@ -17,7 +17,6 @@
    <https://www.gnu.org/licenses/>.  */
 
 #include <dynarray.h>
-#include <stdlib.h>
 #include <string.h>
 
 bool
@@ -28,7 +27,8 @@ __libc_dynarray_resize_clear (struct dynarray_header *list, size_t size,
   if (!__libc_dynarray_resize (list, size, scratch, element_size))
     return false;
   /* __libc_dynarray_resize already checked for overflow.  */
-  memset (list->array + (old_size * element_size), 0,
+  char *array = list->array;
+  memset (array + (old_size * element_size), 0,
           (size - old_size) * element_size);
   return true;
 }
diff --git a/malloc/tst-dynarray-fail.c b/malloc/tst-dynarray-fail.c
index 1db3a00b34..9252586e79 100644
--- a/malloc/tst-dynarray-fail.c
+++ b/malloc/tst-dynarray-fail.c
@@ -249,9 +249,9 @@ test_str_fail (void)
         else
           dynarray_str_free (&dyn);
         TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
-        TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch);
+        TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
         TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
-        TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0);
+        TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
       }
 
   /* Exercise failure in finalize.  */
@@ -278,9 +278,9 @@ test_str_fail (void)
       TEST_VERIFY_EXIT (result.array == (char **) (uintptr_t) -1);
       TEST_VERIFY_EXIT (result.length == (size_t) -1);
       TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
-      TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch);
+      TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
       TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
-      TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0);
+      TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
       free_fill_heap (heap_filler);
     }
 
diff --git a/malloc/tst-dynarray-shared.h b/malloc/tst-dynarray-shared.h
index fbbbef2eab..c3d63c87c6 100644
--- a/malloc/tst-dynarray-shared.h
+++ b/malloc/tst-dynarray-shared.h
@@ -48,9 +48,9 @@ struct str_array
   ({                                                            \
     TEST_VERIFY_EXIT (!dynarray_##type##_has_failed (dyn));     \
     TEST_VERIFY_EXIT (dynarray_##type##_size (dyn) == 0);       \
-    TEST_VERIFY_EXIT ((dyn)->dynarray_header.array              \
+    TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.array            \
                       == (dyn)->scratch);                       \
-    TEST_VERIFY_EXIT ((dyn)->dynarray_header.allocated > 0);    \
+    TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.allocated > 0);  \
     (void) 0;                                                   \
   })
 
diff --git a/malloc/tst-dynarray.c b/malloc/tst-dynarray.c
index 6c6437b12a..c33505711f 100644
--- a/malloc/tst-dynarray.c
+++ b/malloc/tst-dynarray.c
@@ -110,10 +110,10 @@ test_int (void)
                   TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
                   TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == i + 1);
                   TEST_VERIFY_EXIT (dynarray_int_size (&dyn)
-                                    <= dyn.dynarray_header.allocated);
+                                    <= dyn.u.dynarray_header.allocated);
                 }
               TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count);
-              TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated);
+              TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
               if (count > 0)
                 {
                   TEST_VERIFY (dynarray_int_begin (&dyn)
@@ -122,7 +122,7 @@ test_int (void)
                                == dynarray_int_at (&dyn, count - 1) + 1);
                 }
               unsigned final_count;
-              bool heap_array = dyn.dynarray_header.array != dyn.scratch;
+              bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
               if (do_remove_last)
                 {
                   dynarray_int_remove_last (&dyn);
@@ -146,10 +146,11 @@ test_int (void)
                   final_count = 0;
                 }
               TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
-              TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch)
+              TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
                                 == heap_array);
               TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count);
-              TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count);
+              TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
+				>= final_count);
               if (!do_clear)
                 for (unsigned int i = 0; i < final_count; ++i)
                   TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i);
@@ -238,10 +239,10 @@ test_str (void)
                   TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
                   TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == i + 1);
                   TEST_VERIFY_EXIT (dynarray_str_size (&dyn)
-                                    <= dyn.dynarray_header.allocated);
+                                    <= dyn.u.dynarray_header.allocated);
                 }
               TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count);
-              TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated);
+              TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
               if (count > 0)
                 {
                   TEST_VERIFY (dynarray_str_begin (&dyn)
@@ -250,7 +251,7 @@ test_str (void)
                                == dynarray_str_at (&dyn, count - 1) + 1);
                 }
               unsigned final_count;
-              bool heap_array = dyn.dynarray_header.array != dyn.scratch;
+              bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
               if (do_remove_last)
                 {
                   dynarray_str_remove_last (&dyn);
@@ -274,10 +275,11 @@ test_str (void)
                   final_count = 0;
                 }
               TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
-              TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch)
+              TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
                                 == heap_array);
               TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count);
-              TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count);
+              TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
+				>= final_count);
               if (!do_clear)
                 for (unsigned int i = 0; i < count - do_remove_last; ++i)
                   {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 3/5] regex: remove alloca usage on regex set_regs
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH 2/5] malloc: Sync dynarray " Adhemerval Zanella
@ 2021-01-13 16:58 ` Adhemerval Zanella
  2021-02-09 19:12   ` Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH v2 4/5] regexec: remove alloca usage in build_trtable Adhemerval Zanella
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 16:58 UTC (permalink / raw)
  To: libc-alpha

It syncs with gnulib version b6207ab38.  It replaces the regmatch_t
with a dynarray list.

Checked on x86_64-linux-gnu.
---
 posix/regexec.c | 40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/posix/regexec.c b/posix/regexec.c
index b083342f77..889b10be9c 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -1355,6 +1355,12 @@ pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
   return fs->stack[num].node;
 }
 
+
+#define DYNARRAY_STRUCT  regmatch_list
+#define DYNARRAY_ELEMENT regmatch_t
+#define DYNARRAY_PREFIX  regmatch_list_
+#include <malloc/dynarray-skeleton.c>
+
 /* Set the positions where the subexpressions are starts/ends to registers
    PMATCH.
    Note: We assume that pmatch[0] is already set, and
@@ -1370,8 +1376,8 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
   re_node_set eps_via_nodes;
   struct re_fail_stack_t *fs;
   struct re_fail_stack_t fs_body = { 0, 2, NULL };
-  regmatch_t *prev_idx_match;
-  bool prev_idx_match_malloced = false;
+  struct regmatch_list prev_match;
+  regmatch_list_init (&prev_match);
 
   DEBUG_ASSERT (nmatch > 1);
   DEBUG_ASSERT (mctx->state_log != NULL);
@@ -1388,18 +1394,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
   cur_node = dfa->init_node;
   re_node_set_init_empty (&eps_via_nodes);
 
-  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
-    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
-  else
+  if (!regmatch_list_resize (&prev_match, nmatch))
     {
-      prev_idx_match = re_malloc (regmatch_t, nmatch);
-      if (prev_idx_match == NULL)
-	{
-	  free_fail_stack_return (fs);
-	  return REG_ESPACE;
-	}
-      prev_idx_match_malloced = true;
+      regmatch_list_free (&prev_match);
+      free_fail_stack_return (fs);
+      return REG_ESPACE;
     }
+  regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match);
   memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
 
   for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
@@ -1417,8 +1418,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
 	      if (reg_idx == nmatch)
 		{
 		  re_node_set_free (&eps_via_nodes);
-		  if (prev_idx_match_malloced)
-		    re_free (prev_idx_match);
+		  regmatch_list_free (&prev_match);
 		  return free_fail_stack_return (fs);
 		}
 	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
@@ -1427,8 +1427,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
 	  else
 	    {
 	      re_node_set_free (&eps_via_nodes);
-	      if (prev_idx_match_malloced)
-		re_free (prev_idx_match);
+	      regmatch_list_free (&prev_match);
 	      return REG_NOERROR;
 	    }
 	}
@@ -1442,8 +1441,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
 	  if (__glibc_unlikely (cur_node == -2))
 	    {
 	      re_node_set_free (&eps_via_nodes);
-	      if (prev_idx_match_malloced)
-		re_free (prev_idx_match);
+	      regmatch_list_free (&prev_match);
 	      free_fail_stack_return (fs);
 	      return REG_ESPACE;
 	    }
@@ -1453,15 +1451,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
 	  else
 	    {
 	      re_node_set_free (&eps_via_nodes);
-	      if (prev_idx_match_malloced)
-		re_free (prev_idx_match);
+	      regmatch_list_free (&prev_match);
 	      return REG_NOMATCH;
 	    }
 	}
     }
   re_node_set_free (&eps_via_nodes);
-  if (prev_idx_match_malloced)
-    re_free (prev_idx_match);
+  regmatch_list_free (&prev_match);
   return free_fail_stack_return (fs);
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 4/5] regexec: remove alloca usage in build_trtable
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH 2/5] malloc: Sync dynarray " Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH v2 3/5] regex: remove alloca usage on regex set_regs Adhemerval Zanella
@ 2021-01-13 16:58 ` Adhemerval Zanella
  2021-02-09 19:12   ` Adhemerval Zanella
  2021-01-13 16:58 ` [PATCH v2 5/5] regex: stop using alloca Adhemerval Zanella
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 16:58 UTC (permalink / raw)
  To: libc-alpha

It syncs with gnulib version 1731fef3d.  On build_trtable prevent
inlining, so that it doesn’t bloat the caller’s stack and use auto
variables instead of alloca/malloc.

After these changes, build_trtable’s total stack allocation is
only 20 KiB on a 64-bit machine, and this is less than glibc’s 64
KiB cutoff so there’s little point to using alloca to shrink it.

Checked on x86_64-linux-gnu.
---
 posix/regexec.c | 75 +++++++++----------------------------------------
 1 file changed, 13 insertions(+), 62 deletions(-)

diff --git a/posix/regexec.c b/posix/regexec.c
index 889b10be9c..f7b4f9cfc3 100644
--- a/posix/regexec.c
+++ b/posix/regexec.c
@@ -3247,7 +3247,7 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
 /* Build transition table for the state.
    Return true if successful.  */
 
-static bool
+static bool __attribute_noinline__
 build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
 {
   reg_errcode_t err;
@@ -3255,36 +3255,20 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
   int ch;
   bool need_word_trtable = false;
   bitset_word_t elem, mask;
-  bool dests_node_malloced = false;
-  bool dest_states_malloced = false;
   Idx ndests; /* Number of the destination states from 'state'.  */
   re_dfastate_t **trtable;
-  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
-  re_node_set follows, *dests_node;
-  bitset_t *dests_ch;
+  re_dfastate_t *dest_states[SBC_MAX];
+  re_dfastate_t *dest_states_word[SBC_MAX];
+  re_dfastate_t *dest_states_nl[SBC_MAX];
+  re_node_set follows;
   bitset_t acceptable;
 
-  struct dests_alloc
-  {
-    re_node_set dests_node[SBC_MAX];
-    bitset_t dests_ch[SBC_MAX];
-  } *dests_alloc;
-
   /* We build DFA states which corresponds to the destination nodes
      from 'state'.  'dests_node[i]' represents the nodes which i-th
      destination state contains, and 'dests_ch[i]' represents the
      characters which i-th destination state accepts.  */
-  if (__libc_use_alloca (sizeof (struct dests_alloc)))
-    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
-  else
-    {
-      dests_alloc = re_malloc (struct dests_alloc, 1);
-      if (__glibc_unlikely (dests_alloc == NULL))
-	return false;
-      dests_node_malloced = true;
-    }
-  dests_node = dests_alloc->dests_node;
-  dests_ch = dests_alloc->dests_ch;
+  re_node_set dests_node[SBC_MAX];
+  bitset_t dests_ch[SBC_MAX];
 
   /* Initialize transition table.  */
   state->word_trtable = state->trtable = NULL;
@@ -3294,8 +3278,6 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
   ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
   if (__glibc_unlikely (ndests <= 0))
     {
-      if (dests_node_malloced)
-	re_free (dests_alloc);
       /* Return false in case of an error, true otherwise.  */
       if (ndests == 0)
 	{
@@ -3310,38 +3292,14 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
 
   err = re_node_set_alloc (&follows, ndests + 1);
   if (__glibc_unlikely (err != REG_NOERROR))
-    goto out_free;
-
-  /* Avoid arithmetic overflow in size calculation.  */
-  size_t ndests_max
-    = ((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
-       / (3 * sizeof (re_dfastate_t *)));
-  if (__glibc_unlikely (ndests_max < ndests))
-    goto out_free;
-
-  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
-			 + ndests * 3 * sizeof (re_dfastate_t *)))
-    dest_states = (re_dfastate_t **)
-      alloca (ndests * 3 * sizeof (re_dfastate_t *));
-  else
     {
-      dest_states = re_malloc (re_dfastate_t *, ndests * 3);
-      if (__glibc_unlikely (dest_states == NULL))
-	{
-out_free:
-	  if (dest_states_malloced)
-	    re_free (dest_states);
-	  re_node_set_free (&follows);
-	  for (i = 0; i < ndests; ++i)
-	    re_node_set_free (dests_node + i);
-	  if (dests_node_malloced)
-	    re_free (dests_alloc);
-	  return false;
-	}
-      dest_states_malloced = true;
+    out_free:
+      re_node_set_free (&follows);
+      for (i = 0; i < ndests; ++i)
+	re_node_set_free (dests_node + i);
+      return false;
     }
-  dest_states_word = dest_states + ndests;
-  dest_states_nl = dest_states_word + ndests;
+
   bitset_empty (acceptable);
 
   /* Then build the states for all destinations.  */
@@ -3466,16 +3424,9 @@ out_free:
 	  }
     }
 
-  if (dest_states_malloced)
-    re_free (dest_states);
-
   re_node_set_free (&follows);
   for (i = 0; i < ndests; ++i)
     re_node_set_free (dests_node + i);
-
-  if (dests_node_malloced)
-    re_free (dests_alloc);
-
   return true;
 }
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 5/5] regex: stop using alloca
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2021-01-13 16:58 ` [PATCH v2 4/5] regexec: remove alloca usage in build_trtable Adhemerval Zanella
@ 2021-01-13 16:58 ` Adhemerval Zanella
  2021-02-09 19:12   ` Adhemerval Zanella
  2021-01-13 18:09 ` [PATCH 1/5] misc: Sync cdefs.h with gnulib Joseph Myers
  2021-01-13 19:19 ` Paul Eggert
  5 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 16:58 UTC (permalink / raw)
  To: libc-alpha

It syncs with gnulib version 87ed1f9c4.  No functional changes is
expected.

Checked on x86_64-linux-gnu.
---
 posix/regex_internal.h | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/posix/regex_internal.h b/posix/regex_internal.h
index e31ac92674..641b27e2b1 100644
--- a/posix/regex_internal.h
+++ b/posix/regex_internal.h
@@ -444,25 +444,6 @@ typedef struct re_dfa_t re_dfa_t;
 #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
 #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
 
-#if defined _LIBC || HAVE_ALLOCA
-# include <alloca.h>
-#endif
-
-#ifndef _LIBC
-# if HAVE_ALLOCA
-/* The OS usually guarantees only one guard page at the bottom of the stack,
-   and a page size can be as small as 4096 bytes.  So we cannot safely
-   allocate anything larger than 4096 bytes.  Also care for the possibility
-   of a few compiler-allocated temporary stack slots.  */
-#  define __libc_use_alloca(n) ((n) < 4032)
-# else
-/* alloca is implemented with malloc, so just use malloc.  */
-#  define __libc_use_alloca(n) 0
-#  undef alloca
-#  define alloca(n) malloc (n)
-# endif
-#endif
-
 #ifdef _LIBC
 # define MALLOC_0_IS_NONNULL 1
 #elif !defined MALLOC_0_IS_NONNULL
-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] misc: Sync cdefs.h with gnulib
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2021-01-13 16:58 ` [PATCH v2 5/5] regex: stop using alloca Adhemerval Zanella
@ 2021-01-13 18:09 ` Joseph Myers
  2021-01-13 18:30   ` Adhemerval Zanella
  2021-01-13 19:19 ` Paul Eggert
  5 siblings, 1 reply; 14+ messages in thread
From: Joseph Myers @ 2021-01-13 18:09 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 13 Jan 2021, Adhemerval Zanella via Libc-alpha wrote:

> +#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
> +# define __attribute_maybe_unused__ [[__maybe_unused__]]

I don't think that will work with GCC 9 -std=c2x or -std=gnu2x (support 
for [[]] attributes was added in GCC 10).  This macro isn't used at all in 
glibc, what compilers and options are expected to be supported for it in 
gnulib?

If you compare __STDC_VERSION__ with the version for the previous 
standard, and intend to support compilers such as GCC 9 -std=gnu2x, you 
need to deal with incomplete implementations using placeholder values 
(202000L in this case).  (You might have incomplete implementations even 
comparing with the final value used for C23, but they're less likely to be 
so incomplete.)

When you're supporting [[__maybe_unused__]] you might want to support it 
for C++17 as well as C2x.  Or is this macro in gnulib only intended to be 
used in C code, not C++?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] misc: Sync cdefs.h with gnulib
  2021-01-13 18:09 ` [PATCH 1/5] misc: Sync cdefs.h with gnulib Joseph Myers
@ 2021-01-13 18:30   ` Adhemerval Zanella
  2021-02-09 14:07     ` Adhemerval Zanella
  0 siblings, 1 reply; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 18:30 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Paul Eggert



On 13/01/2021 15:09, Joseph Myers wrote:
> On Wed, 13 Jan 2021, Adhemerval Zanella via Libc-alpha wrote:
> 
>> +#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
>> +# define __attribute_maybe_unused__ [[__maybe_unused__]]
> 
> I don't think that will work with GCC 9 -std=c2x or -std=gnu2x (support 
> for [[]] attributes was added in GCC 10).  This macro isn't used at all in 
> glibc, what compilers and options are expected to be supported for it in 
> gnulib?
> 
> If you compare __STDC_VERSION__ with the version for the previous 
> standard, and intend to support compilers such as GCC 9 -std=gnu2x, you 
> need to deal with incomplete implementations using placeholder values 
> (202000L in this case).  (You might have incomplete implementations even 
> comparing with the final value used for C23, but they're less likely to be 
> so incomplete.)
> 
> When you're supporting [[__maybe_unused__]] you might want to support it 
> for C++17 as well as C2x.  Or is this macro in gnulib only intended to be 
> used in C code, not C++?
> 

It is only used on C code, more specially for lib/malloc/dynarray-skeleton.c.
And I am no sure if gnulib has active support -std=c2x or -std=gnu2x and
I think Paul can give us a better idea on how to support this better on
gnulib side.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] misc: Sync cdefs.h with gnulib
  2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2021-01-13 18:09 ` [PATCH 1/5] misc: Sync cdefs.h with gnulib Joseph Myers
@ 2021-01-13 19:19 ` Paul Eggert
  2021-01-13 19:21   ` Adhemerval Zanella
  5 siblings, 1 reply; 14+ messages in thread
From: Paul Eggert @ 2021-01-13 19:19 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

Thanks, I'll try to take a look at these.

Also, I've been trying to pry free some time to review the patches you 
proposed earlier for fnmatch and glob. I'll respond on those threads 
with what I have now. I'm assuming that those patches won't get into 
glibc 2.33 due to its slushy freeze.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] misc: Sync cdefs.h with gnulib
  2021-01-13 19:19 ` Paul Eggert
@ 2021-01-13 19:21   ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-01-13 19:21 UTC (permalink / raw)
  To: Paul Eggert; +Cc: libc-alpha



On 13/01/2021 16:19, Paul Eggert wrote:
> Thanks, I'll try to take a look at these.
> 
> Also, I've been trying to pry free some time to review the patches you proposed earlier for fnmatch and glob. I'll respond on those threads with what I have now. I'm assuming that those patches won't get into glibc 2.33 due to its slushy freeze.

Thanks and my plan for these patches is for next release (2.34).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5] misc: Sync cdefs.h with gnulib
  2021-01-13 18:30   ` Adhemerval Zanella
@ 2021-02-09 14:07     ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-02-09 14:07 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha, Paul Eggert



On 13/01/2021 15:30, Adhemerval Zanella wrote:
> 
> 
> On 13/01/2021 15:09, Joseph Myers wrote:
>> On Wed, 13 Jan 2021, Adhemerval Zanella via Libc-alpha wrote:
>>
>>> +#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
>>> +# define __attribute_maybe_unused__ [[__maybe_unused__]]
>>
>> I don't think that will work with GCC 9 -std=c2x or -std=gnu2x (support 
>> for [[]] attributes was added in GCC 10).  This macro isn't used at all in 
>> glibc, what compilers and options are expected to be supported for it in 
>> gnulib?
>>
>> If you compare __STDC_VERSION__ with the version for the previous 
>> standard, and intend to support compilers such as GCC 9 -std=gnu2x, you 
>> need to deal with incomplete implementations using placeholder values 
>> (202000L in this case).  (You might have incomplete implementations even 
>> comparing with the final value used for C23, but they're less likely to be 
>> so incomplete.)
>>
>> When you're supporting [[__maybe_unused__]] you might want to support it 
>> for C++17 as well as C2x.  Or is this macro in gnulib only intended to be 
>> used in C code, not C++?
>>
> 
> It is only used on C code, more specially for lib/malloc/dynarray-skeleton.c.
> And I am no sure if gnulib has active support -std=c2x or -std=gnu2x and
> I think Paul can give us a better idea on how to support this better on
> gnulib side.
> 

I won't sync the '[[__maybe_unused__]]' definition and I will check with gnulib
developers how we can safely enable it with newer gcc and -std definitions.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] malloc: Sync dynarray with gnulib
  2021-01-13 16:58 ` [PATCH 2/5] malloc: Sync dynarray " Adhemerval Zanella
@ 2021-02-09 19:12   ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-02-09 19:12 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 13/01/2021 13:58, Adhemerval Zanella wrote:
> It syncs with gnulib version a8bac4d49.  The main changes are:
> 
>   - Remove the usage of anonymous union within DYNARRAY_STRUCT.
>   - Use DYNARRAY_FREE instead of DYNARRAY_NAME (free) so that
>     Gnulib does not change 'free' to 'rpl_free'.
>   - Use __nonnull instead of __attribute__ ((nonnull ())).
>   - Use __attribute_maybe_unused__ instead of
>     __attribute__ ((unused, nonnull (1))).
>   - Use of _Noreturn instead of _attribute__ ((noreturn)).
> 
> The only difference with gnulib is:
> 
> --- ../../gnulib/gnulib-lib/lib/malloc/dynarray_at_failure.c
> +++ malloc/dynarray_at_failure.c
> @@ -18,7 +18,6 @@
> 
>  #include <dynarray.h>
>  #include <stdio.h>
> -#include <stdlib.h>
> 
>  void
>  __libc_dynarray_at_failure (size_t size, size_t index)
> @@ -28,6 +27,7 @@
>    __snprintf (buf, sizeof (buf), "Fatal glibc error: "
>                "array index %zu not less than array length %zu\n",
>                index, size);
> + __libc_fatal (buf);
>  #else
>   abort ();
>  #endif
> 
> It seems a wrong sync from gnulib.
> 
> Checked on x86_64-linux-gnu.
> ---
>  malloc/dynarray-skeleton.c        | 128 +++++++++++++++---------------
>  malloc/dynarray.h                 |   3 +-
>  malloc/dynarray_at_failure.c      |   4 +
>  malloc/dynarray_emplace_enlarge.c |   3 +-
>  malloc/dynarray_resize.c          |   3 +-
>  malloc/dynarray_resize_clear.c    |   4 +-
>  malloc/tst-dynarray-fail.c        |   8 +-
>  malloc/tst-dynarray-shared.h      |   4 +-
>  malloc/tst-dynarray.c             |  22 ++---
>  9 files changed, 95 insertions(+), 84 deletions(-)
> 
> diff --git a/malloc/dynarray-skeleton.c b/malloc/dynarray-skeleton.c
> index e552664bc5..5b9f37bdd6 100644
> --- a/malloc/dynarray-skeleton.c
> +++ b/malloc/dynarray-skeleton.c
> @@ -135,7 +135,7 @@ struct DYNARRAY_STRUCT
>        size_t allocated;
>        DYNARRAY_ELEMENT *array;
>      } dynarray_header;
> -  };
> +  } u;
>  
>  #if DYNARRAY_HAVE_SCRATCH
>    /* Initial inline allocation.  */
> @@ -150,6 +150,10 @@ struct DYNARRAY_STRUCT
>  #define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
>  #define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
>  
> +/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
> +   so that Gnulib does not change 'free' to 'rpl_free'.  */
> +#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
> +
>  /* Address of the scratch buffer if any.  */
>  #if DYNARRAY_HAVE_SCRATCH
>  # define DYNARRAY_SCRATCH(list) (list)->scratch
> @@ -177,10 +181,10 @@ static inline void
>  DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
>  {
>  #if DYNARRAY_HAVE_SCRATCH
> -  if (list->dynarray_header.array != list->scratch)
> -    free (list->dynarray_header.array);
> +  if (list->u.dynarray_header.array != list->scratch)
> +    free (list->u.dynarray_header.array);
>  #else
> -  free (list->dynarray_header.array);
> +  free (list->u.dynarray_header.array);
>  #endif
>  }
>  
> @@ -188,86 +192,86 @@ DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
>  
>  /* Initialize a dynamic array object.  This must be called before any
>     use of the object.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static void
>  DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
>  {
> -  list->dynarray_header.used = 0;
> -  list->dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
> -  list->dynarray_header.array = DYNARRAY_SCRATCH (list);
> +  list->u.dynarray_header.used = 0;
> +  list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
> +  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
>  }
>  
>  /* Deallocate the dynamic array and its elements.  */
> -__attribute__ ((unused, nonnull (1)))
> +__attribute_maybe_unused__ __nonnull ((1))
>  static void
> -DYNARRAY_NAME (free) (struct DYNARRAY_STRUCT *list)
> +DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
>  {
>    DYNARRAY_NAME (free__elements__)
> -    (list->dynarray_header.array, list->dynarray_header.used);
> +    (list->u.dynarray_header.array, list->u.dynarray_header.used);
>    DYNARRAY_NAME (free__array__) (list);
>    DYNARRAY_NAME (init) (list);
>  }
>  
>  /* Return true if the dynamic array is in an error state.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static inline bool
>  DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
>  {
> -  return list->dynarray_header.allocated == __dynarray_error_marker ();
> +  return list->u.dynarray_header.allocated == __dynarray_error_marker ();
>  }
>  
>  /* Mark the dynamic array as failed.  All elements are deallocated as
>     a side effect.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static void
>  DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
>  {
>    DYNARRAY_NAME (free__elements__)
> -    (list->dynarray_header.array, list->dynarray_header.used);
> +    (list->u.dynarray_header.array, list->u.dynarray_header.used);
>    DYNARRAY_NAME (free__array__) (list);
> -  list->dynarray_header.array = DYNARRAY_SCRATCH (list);
> -  list->dynarray_header.used = 0;
> -  list->dynarray_header.allocated = __dynarray_error_marker ();
> +  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
> +  list->u.dynarray_header.used = 0;
> +  list->u.dynarray_header.allocated = __dynarray_error_marker ();
>  }
>  
>  /* Return the number of elements which have been added to the dynamic
>     array.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static inline size_t
>  DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
>  {
> -  return list->dynarray_header.used;
> +  return list->u.dynarray_header.used;
>  }
>  
>  /* Return a pointer to the array element at INDEX.  Terminate the
>     process if INDEX is out of bounds.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static inline DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
>  {
>    if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
>      __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
> -  return list->dynarray_header.array + index;
> +  return list->u.dynarray_header.array + index;
>  }
>  
>  /* Return a pointer to the first array element, if any.  For a
>     zero-length array, the pointer can be NULL even though the dynamic
>     array has not entered the failure state.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static inline DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
>  {
> -  return list->dynarray_header.array;
> +  return list->u.dynarray_header.array;
>  }
>  
>  /* Return a pointer one element past the last array element.  For a
>     zero-length array, the pointer can be NULL even though the dynamic
>     array has not entered the failure state.  */
> -__attribute__ ((nonnull (1)))
> +__nonnull ((1))
>  static inline DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
>  {
> -  return list->dynarray_header.array + list->dynarray_header.used;
> +  return list->u.dynarray_header.array + list->u.dynarray_header.used;
>  }
>  
>  /* Internal function.  Slow path for the add function below.  */
> @@ -275,7 +279,7 @@ static void
>  DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
>  {
>    if (__glibc_unlikely
> -      (!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract,
> +      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
>                                           DYNARRAY_SCRATCH (list),
>                                           sizeof (DYNARRAY_ELEMENT))))
>      {
> @@ -284,13 +288,13 @@ DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
>      }
>  
>    /* Copy the new element and increase the array length.  */
> -  list->dynarray_header.array[list->dynarray_header.used++] = item;
> +  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
>  }
>  
>  /* Add ITEM at the end of the array, enlarging it by one element.
>     Mark *LIST as failed if the dynamic array allocation size cannot be
>     increased.  */
> -__attribute__ ((unused, nonnull (1)))
> +__nonnull ((1))
>  static inline void
>  DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
>  {
> @@ -299,15 +303,15 @@ DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
>      return;
>  
>    /* Enlarge the array if necessary.  */
> -  if (__glibc_unlikely (list->dynarray_header.used
> -                        == list->dynarray_header.allocated))
> +  if (__glibc_unlikely (list->u.dynarray_header.used
> +                        == list->u.dynarray_header.allocated))
>      {
>        DYNARRAY_NAME (add__) (list, item);
>        return;
>      }
>  
>    /* Copy the new element and increase the array length.  */
> -  list->dynarray_header.array[list->dynarray_header.used++] = item;
> +  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
>  }
>  
>  /* Internal function.  Building block for the emplace functions below.
> @@ -316,8 +320,8 @@ static inline DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
>  {
>    DYNARRAY_ELEMENT *result
> -    = &list->dynarray_header.array[list->dynarray_header.used];
> -  ++list->dynarray_header.used;
> +    = &list->u.dynarray_header.array[list->u.dynarray_header.used];
> +  ++list->u.dynarray_header.used;
>  #if defined (DYNARRAY_ELEMENT_INIT)
>    DYNARRAY_ELEMENT_INIT (result);
>  #elif defined (DYNARRAY_ELEMENT_FREE)
> @@ -331,7 +335,7 @@ static DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
>  {
>    if (__glibc_unlikely
> -      (!__libc_dynarray_emplace_enlarge (&list->dynarray_abstract,
> +      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
>                                           DYNARRAY_SCRATCH (list),
>                                           sizeof (DYNARRAY_ELEMENT))))
>      {
> @@ -344,7 +348,7 @@ DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
>  /* Allocate a place for a new element in *LIST and return a pointer to
>     it.  The pointer can be NULL if the dynamic array cannot be
>     enlarged due to a memory allocation failure.  */
> -__attribute__ ((unused, warn_unused_result, nonnull (1)))
> +__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
>  static
>  /* Avoid inlining with the larger initialization code.  */
>  #if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
> @@ -358,8 +362,8 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
>      return NULL;
>  
>    /* Enlarge the array if necessary.  */
> -  if (__glibc_unlikely (list->dynarray_header.used
> -                        == list->dynarray_header.allocated))
> +  if (__glibc_unlikely (list->u.dynarray_header.used
> +                        == list->u.dynarray_header.allocated))
>      return (DYNARRAY_NAME (emplace__) (list));
>    return DYNARRAY_NAME (emplace__tail__) (list);
>  }
> @@ -368,32 +372,32 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
>     existing size, new elements are added (which can be initialized).
>     Otherwise, the list is truncated, and elements are freed.  Return
>     false on memory allocation failure (and mark *LIST as failed).  */
> -__attribute__ ((unused, nonnull (1)))
> +__attribute_maybe_unused__ __nonnull ((1))
>  static bool
>  DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
>  {
> -  if (size > list->dynarray_header.used)
> +  if (size > list->u.dynarray_header.used)
>      {
>        bool ok;
>  #if defined (DYNARRAY_ELEMENT_INIT)
>        /* The new elements have to be initialized.  */
> -      size_t old_size = list->dynarray_header.used;
> -      ok = __libc_dynarray_resize (&list->dynarray_abstract,
> +      size_t old_size = list->u.dynarray_header.used;
> +      ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
>                                     size, DYNARRAY_SCRATCH (list),
>                                     sizeof (DYNARRAY_ELEMENT));
>        if (ok)
>          for (size_t i = old_size; i < size; ++i)
>            {
> -            DYNARRAY_ELEMENT_INIT (&list->dynarray_header.array[i]);
> +            DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
>            }
>  #elif defined (DYNARRAY_ELEMENT_FREE)
>        /* Zero initialization is needed so that the elements can be
>           safely freed.  */
>        ok = __libc_dynarray_resize_clear
> -        (&list->dynarray_abstract, size,
> +        (&list->u.dynarray_abstract, size,
>           DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
>  #else
> -      ok =  __libc_dynarray_resize (&list->dynarray_abstract,
> +      ok =  __libc_dynarray_resize (&list->u.dynarray_abstract,
>                                      size, DYNARRAY_SCRATCH (list),
>                                      sizeof (DYNARRAY_ELEMENT));
>  #endif
> @@ -405,40 +409,40 @@ DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
>      {
>        /* The list has shrunk in size.  Free the removed elements.  */
>        DYNARRAY_NAME (free__elements__)
> -        (list->dynarray_header.array + size,
> -         list->dynarray_header.used - size);
> -      list->dynarray_header.used = size;
> +        (list->u.dynarray_header.array + size,
> +         list->u.dynarray_header.used - size);
> +      list->u.dynarray_header.used = size;
>        return true;
>      }
>  }
>  
>  /* Remove the last element of LIST if it is present.  */
> -__attribute__ ((unused, nonnull (1)))
> +__attribute_maybe_unused__ __nonnull ((1))
>  static void
>  DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
>  {
>    /* used > 0 implies that the array is the non-failed state.  */
> -  if (list->dynarray_header.used > 0)
> +  if (list->u.dynarray_header.used > 0)
>      {
> -      size_t new_length = list->dynarray_header.used - 1;
> +      size_t new_length = list->u.dynarray_header.used - 1;
>  #ifdef DYNARRAY_ELEMENT_FREE
> -      DYNARRAY_ELEMENT_FREE (&list->dynarray_header.array[new_length]);
> +      DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
>  #endif
> -      list->dynarray_header.used = new_length;
> +      list->u.dynarray_header.used = new_length;
>      }
>  }
>  
>  /* Remove all elements from the list.  The elements are freed, but the
>     list itself is not.  */
> -__attribute__ ((unused, nonnull (1)))
> +__attribute_maybe_unused__ __nonnull ((1))
>  static void
>  DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
>  {
>    /* free__elements__ does nothing if the list is in the failed
>       state.  */
>    DYNARRAY_NAME (free__elements__)
> -    (list->dynarray_header.array, list->dynarray_header.used);
> -  list->dynarray_header.used = 0;
> +    (list->u.dynarray_header.array, list->u.dynarray_header.used);
> +  list->u.dynarray_header.used = 0;
>  }
>  
>  #ifdef DYNARRAY_FINAL_TYPE
> @@ -448,13 +452,13 @@ DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
>     stored in *RESULT if LIST refers to an empty list.  On success, the
>     pointer in *RESULT is heap-allocated and must be deallocated using
>     free.  */
> -__attribute__ ((unused, warn_unused_result, nonnull (1, 2)))
> +__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1, 2))
>  static bool
>  DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
>                            DYNARRAY_FINAL_TYPE *result)
>  {
>    struct dynarray_finalize_result res;
> -  if (__libc_dynarray_finalize (&list->dynarray_abstract,
> +  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
>                                  DYNARRAY_SCRATCH (list),
>                                  sizeof (DYNARRAY_ELEMENT), &res))
>      {
> @@ -466,7 +470,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
>    else
>      {
>        /* On error, we need to free all data.  */
> -      DYNARRAY_NAME (free) (list);
> +      DYNARRAY_FREE (list);
>        errno = ENOMEM;
>        return false;
>      }
> @@ -479,12 +483,12 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
>     have a sentinel at the end).  If LENGTHP is not NULL, the array
>     length is written to *LENGTHP.  *LIST is re-initialized and can be
>     reused.  */
> -__attribute__ ((unused, warn_unused_result, nonnull (1)))
> +__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
>  static DYNARRAY_ELEMENT *
>  DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
>  {
>    struct dynarray_finalize_result res;
> -  if (__libc_dynarray_finalize (&list->dynarray_abstract,
> +  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
>                                  DYNARRAY_SCRATCH (list),
>                                  sizeof (DYNARRAY_ELEMENT), &res))
>      {
> @@ -497,7 +501,7 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
>    else
>      {
>        /* On error, we need to free all data.  */
> -      DYNARRAY_NAME (free) (list);
> +      DYNARRAY_FREE (list);
>        errno = ENOMEM;
>        return NULL;
>      }
> diff --git a/malloc/dynarray.h b/malloc/dynarray.h
> index 24ca1620d2..638c33f986 100644
> --- a/malloc/dynarray.h
> +++ b/malloc/dynarray.h
> @@ -165,8 +165,7 @@ bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
>  /* Internal function.  Terminate the process after an index error.
>     SIZE is the number of elements of the dynamic array.  INDEX is the
>     lookup index which triggered the failure.  */
> -void __libc_dynarray_at_failure (size_t size, size_t index)
> -  __attribute__ ((noreturn));
> +_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
>  
>  #ifndef _ISOMAC
>  libc_hidden_proto (__libc_dynarray_emplace_enlarge)
> diff --git a/malloc/dynarray_at_failure.c b/malloc/dynarray_at_failure.c
> index d27c0aebbc..88d9ee7f50 100644
> --- a/malloc/dynarray_at_failure.c
> +++ b/malloc/dynarray_at_failure.c
> @@ -22,10 +22,14 @@
>  void
>  __libc_dynarray_at_failure (size_t size, size_t index)
>  {
> +#ifdef _LIBC
>    char buf[200];
>    __snprintf (buf, sizeof (buf), "Fatal glibc error: "
>                "array index %zu not less than array length %zu\n",
>                index, size);
>   __libc_fatal (buf);
> +#else
> + abort ();
> +#endif
>  }
>  libc_hidden_def (__libc_dynarray_at_failure)
> diff --git a/malloc/dynarray_emplace_enlarge.c b/malloc/dynarray_emplace_enlarge.c
> index f98b0328df..ddfe306fcd 100644
> --- a/malloc/dynarray_emplace_enlarge.c
> +++ b/malloc/dynarray_emplace_enlarge.c
> @@ -18,6 +18,7 @@
>  
>  #include <dynarray.h>
>  #include <errno.h>
> +#include <intprops.h>
>  #include <stdlib.h>
>  #include <string.h>
>  
> @@ -51,7 +52,7 @@ __libc_dynarray_emplace_enlarge (struct dynarray_header *list,
>      }
>  
>    size_t new_size;
> -  if (__builtin_mul_overflow (new_allocated, element_size, &new_size))
> +  if (INT_MULTIPLY_WRAPV (new_allocated, element_size, &new_size))
>      return false;
>    void *new_array;
>    if (list->array == scratch)
> diff --git a/malloc/dynarray_resize.c b/malloc/dynarray_resize.c
> index bb50e32f9a..5c60927f37 100644
> --- a/malloc/dynarray_resize.c
> +++ b/malloc/dynarray_resize.c
> @@ -18,6 +18,7 @@
>  
>  #include <dynarray.h>
>  #include <errno.h>
> +#include <intprops.h>
>  #include <stdlib.h>
>  #include <string.h>
>  
> @@ -37,7 +38,7 @@ __libc_dynarray_resize (struct dynarray_header *list, size_t size,
>       over-allocation here.  */
>  
>    size_t new_size_bytes;
> -  if (__builtin_mul_overflow (size, element_size, &new_size_bytes))
> +  if (INT_MULTIPLY_WRAPV (size, element_size, &new_size_bytes))
>      {
>        /* Overflow.  */
>        __set_errno (ENOMEM);
> diff --git a/malloc/dynarray_resize_clear.c b/malloc/dynarray_resize_clear.c
> index 51d64fea5c..e893d1d58e 100644
> --- a/malloc/dynarray_resize_clear.c
> +++ b/malloc/dynarray_resize_clear.c
> @@ -17,7 +17,6 @@
>     <https://www.gnu.org/licenses/>.  */
>  
>  #include <dynarray.h>
> -#include <stdlib.h>
>  #include <string.h>
>  
>  bool
> @@ -28,7 +27,8 @@ __libc_dynarray_resize_clear (struct dynarray_header *list, size_t size,
>    if (!__libc_dynarray_resize (list, size, scratch, element_size))
>      return false;
>    /* __libc_dynarray_resize already checked for overflow.  */
> -  memset (list->array + (old_size * element_size), 0,
> +  char *array = list->array;
> +  memset (array + (old_size * element_size), 0,
>            (size - old_size) * element_size);
>    return true;
>  }
> diff --git a/malloc/tst-dynarray-fail.c b/malloc/tst-dynarray-fail.c
> index 1db3a00b34..9252586e79 100644
> --- a/malloc/tst-dynarray-fail.c
> +++ b/malloc/tst-dynarray-fail.c
> @@ -249,9 +249,9 @@ test_str_fail (void)
>          else
>            dynarray_str_free (&dyn);
>          TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
> -        TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch);
> +        TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
>          TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
> -        TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0);
> +        TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
>        }
>  
>    /* Exercise failure in finalize.  */
> @@ -278,9 +278,9 @@ test_str_fail (void)
>        TEST_VERIFY_EXIT (result.array == (char **) (uintptr_t) -1);
>        TEST_VERIFY_EXIT (result.length == (size_t) -1);
>        TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
> -      TEST_VERIFY_EXIT (dyn.dynarray_header.array == dyn.scratch);
> +      TEST_VERIFY_EXIT (dyn.u.dynarray_header.array == dyn.scratch);
>        TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == 0);
> -      TEST_VERIFY_EXIT (dyn.dynarray_header.allocated > 0);
> +      TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated > 0);
>        free_fill_heap (heap_filler);
>      }
>  
> diff --git a/malloc/tst-dynarray-shared.h b/malloc/tst-dynarray-shared.h
> index fbbbef2eab..c3d63c87c6 100644
> --- a/malloc/tst-dynarray-shared.h
> +++ b/malloc/tst-dynarray-shared.h
> @@ -48,9 +48,9 @@ struct str_array
>    ({                                                            \
>      TEST_VERIFY_EXIT (!dynarray_##type##_has_failed (dyn));     \
>      TEST_VERIFY_EXIT (dynarray_##type##_size (dyn) == 0);       \
> -    TEST_VERIFY_EXIT ((dyn)->dynarray_header.array              \
> +    TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.array            \
>                        == (dyn)->scratch);                       \
> -    TEST_VERIFY_EXIT ((dyn)->dynarray_header.allocated > 0);    \
> +    TEST_VERIFY_EXIT ((dyn)->u.dynarray_header.allocated > 0);  \
>      (void) 0;                                                   \
>    })
>  
> diff --git a/malloc/tst-dynarray.c b/malloc/tst-dynarray.c
> index 6c6437b12a..c33505711f 100644
> --- a/malloc/tst-dynarray.c
> +++ b/malloc/tst-dynarray.c
> @@ -110,10 +110,10 @@ test_int (void)
>                    TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
>                    TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == i + 1);
>                    TEST_VERIFY_EXIT (dynarray_int_size (&dyn)
> -                                    <= dyn.dynarray_header.allocated);
> +                                    <= dyn.u.dynarray_header.allocated);
>                  }
>                TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == count);
> -              TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated);
> +              TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
>                if (count > 0)
>                  {
>                    TEST_VERIFY (dynarray_int_begin (&dyn)
> @@ -122,7 +122,7 @@ test_int (void)
>                                 == dynarray_int_at (&dyn, count - 1) + 1);
>                  }
>                unsigned final_count;
> -              bool heap_array = dyn.dynarray_header.array != dyn.scratch;
> +              bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
>                if (do_remove_last)
>                  {
>                    dynarray_int_remove_last (&dyn);
> @@ -146,10 +146,11 @@ test_int (void)
>                    final_count = 0;
>                  }
>                TEST_VERIFY_EXIT (!dynarray_int_has_failed (&dyn));
> -              TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch)
> +              TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
>                                  == heap_array);
>                TEST_VERIFY_EXIT (dynarray_int_size (&dyn) == final_count);
> -              TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count);
> +              TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
> +				>= final_count);
>                if (!do_clear)
>                  for (unsigned int i = 0; i < final_count; ++i)
>                    TEST_VERIFY_EXIT (*dynarray_int_at (&dyn, i) == base + i);
> @@ -238,10 +239,10 @@ test_str (void)
>                    TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
>                    TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == i + 1);
>                    TEST_VERIFY_EXIT (dynarray_str_size (&dyn)
> -                                    <= dyn.dynarray_header.allocated);
> +                                    <= dyn.u.dynarray_header.allocated);
>                  }
>                TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == count);
> -              TEST_VERIFY_EXIT (count <= dyn.dynarray_header.allocated);
> +              TEST_VERIFY_EXIT (count <= dyn.u.dynarray_header.allocated);
>                if (count > 0)
>                  {
>                    TEST_VERIFY (dynarray_str_begin (&dyn)
> @@ -250,7 +251,7 @@ test_str (void)
>                                 == dynarray_str_at (&dyn, count - 1) + 1);
>                  }
>                unsigned final_count;
> -              bool heap_array = dyn.dynarray_header.array != dyn.scratch;
> +              bool heap_array = dyn.u.dynarray_header.array != dyn.scratch;
>                if (do_remove_last)
>                  {
>                    dynarray_str_remove_last (&dyn);
> @@ -274,10 +275,11 @@ test_str (void)
>                    final_count = 0;
>                  }
>                TEST_VERIFY_EXIT (!dynarray_str_has_failed (&dyn));
> -              TEST_VERIFY_EXIT ((dyn.dynarray_header.array != dyn.scratch)
> +              TEST_VERIFY_EXIT ((dyn.u.dynarray_header.array != dyn.scratch)
>                                  == heap_array);
>                TEST_VERIFY_EXIT (dynarray_str_size (&dyn) == final_count);
> -              TEST_VERIFY_EXIT (dyn.dynarray_header.allocated >= final_count);
> +              TEST_VERIFY_EXIT (dyn.u.dynarray_header.allocated
> +				>= final_count);
>                if (!do_clear)
>                  for (unsigned int i = 0; i < count - do_remove_last; ++i)
>                    {
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 3/5] regex: remove alloca usage on regex set_regs
  2021-01-13 16:58 ` [PATCH v2 3/5] regex: remove alloca usage on regex set_regs Adhemerval Zanella
@ 2021-02-09 19:12   ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-02-09 19:12 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 13/01/2021 13:58, Adhemerval Zanella wrote:
> It syncs with gnulib version b6207ab38.  It replaces the regmatch_t
> with a dynarray list.
> 
> Checked on x86_64-linux-gnu.
> ---
>  posix/regexec.c | 40 ++++++++++++++++++----------------------
>  1 file changed, 18 insertions(+), 22 deletions(-)
> 
> diff --git a/posix/regexec.c b/posix/regexec.c
> index b083342f77..889b10be9c 100644
> --- a/posix/regexec.c
> +++ b/posix/regexec.c
> @@ -1355,6 +1355,12 @@ pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
>    return fs->stack[num].node;
>  }
>  
> +
> +#define DYNARRAY_STRUCT  regmatch_list
> +#define DYNARRAY_ELEMENT regmatch_t
> +#define DYNARRAY_PREFIX  regmatch_list_
> +#include <malloc/dynarray-skeleton.c>
> +
>  /* Set the positions where the subexpressions are starts/ends to registers
>     PMATCH.
>     Note: We assume that pmatch[0] is already set, and
> @@ -1370,8 +1376,8 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>    re_node_set eps_via_nodes;
>    struct re_fail_stack_t *fs;
>    struct re_fail_stack_t fs_body = { 0, 2, NULL };
> -  regmatch_t *prev_idx_match;
> -  bool prev_idx_match_malloced = false;
> +  struct regmatch_list prev_match;
> +  regmatch_list_init (&prev_match);
>  
>    DEBUG_ASSERT (nmatch > 1);
>    DEBUG_ASSERT (mctx->state_log != NULL);
> @@ -1388,18 +1394,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>    cur_node = dfa->init_node;
>    re_node_set_init_empty (&eps_via_nodes);
>  
> -  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
> -    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
> -  else
> +  if (!regmatch_list_resize (&prev_match, nmatch))
>      {
> -      prev_idx_match = re_malloc (regmatch_t, nmatch);
> -      if (prev_idx_match == NULL)
> -	{
> -	  free_fail_stack_return (fs);
> -	  return REG_ESPACE;
> -	}
> -      prev_idx_match_malloced = true;
> +      regmatch_list_free (&prev_match);
> +      free_fail_stack_return (fs);
> +      return REG_ESPACE;
>      }
> +  regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match);
>    memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
>  
>    for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
> @@ -1417,8 +1418,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>  	      if (reg_idx == nmatch)
>  		{
>  		  re_node_set_free (&eps_via_nodes);
> -		  if (prev_idx_match_malloced)
> -		    re_free (prev_idx_match);
> +		  regmatch_list_free (&prev_match);
>  		  return free_fail_stack_return (fs);
>  		}
>  	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
> @@ -1427,8 +1427,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>  	  else
>  	    {
>  	      re_node_set_free (&eps_via_nodes);
> -	      if (prev_idx_match_malloced)
> -		re_free (prev_idx_match);
> +	      regmatch_list_free (&prev_match);
>  	      return REG_NOERROR;
>  	    }
>  	}
> @@ -1442,8 +1441,7 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>  	  if (__glibc_unlikely (cur_node == -2))
>  	    {
>  	      re_node_set_free (&eps_via_nodes);
> -	      if (prev_idx_match_malloced)
> -		re_free (prev_idx_match);
> +	      regmatch_list_free (&prev_match);
>  	      free_fail_stack_return (fs);
>  	      return REG_ESPACE;
>  	    }
> @@ -1453,15 +1451,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
>  	  else
>  	    {
>  	      re_node_set_free (&eps_via_nodes);
> -	      if (prev_idx_match_malloced)
> -		re_free (prev_idx_match);
> +	      regmatch_list_free (&prev_match);
>  	      return REG_NOMATCH;
>  	    }
>  	}
>      }
>    re_node_set_free (&eps_via_nodes);
> -  if (prev_idx_match_malloced)
> -    re_free (prev_idx_match);
> +  regmatch_list_free (&prev_match);
>    return free_fail_stack_return (fs);
>  }
>  
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 4/5] regexec: remove alloca usage in build_trtable
  2021-01-13 16:58 ` [PATCH v2 4/5] regexec: remove alloca usage in build_trtable Adhemerval Zanella
@ 2021-02-09 19:12   ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-02-09 19:12 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 13/01/2021 13:58, Adhemerval Zanella wrote:
> It syncs with gnulib version 1731fef3d.  On build_trtable prevent
> inlining, so that it doesn’t bloat the caller’s stack and use auto
> variables instead of alloca/malloc.
> 
> After these changes, build_trtable’s total stack allocation is
> only 20 KiB on a 64-bit machine, and this is less than glibc’s 64
> KiB cutoff so there’s little point to using alloca to shrink it.
> 
> Checked on x86_64-linux-gnu.
> ---
>  posix/regexec.c | 75 +++++++++----------------------------------------
>  1 file changed, 13 insertions(+), 62 deletions(-)
> 
> diff --git a/posix/regexec.c b/posix/regexec.c
> index 889b10be9c..f7b4f9cfc3 100644
> --- a/posix/regexec.c
> +++ b/posix/regexec.c
> @@ -3247,7 +3247,7 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
>  /* Build transition table for the state.
>     Return true if successful.  */
>  
> -static bool
> +static bool __attribute_noinline__
>  build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
>  {
>    reg_errcode_t err;
> @@ -3255,36 +3255,20 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
>    int ch;
>    bool need_word_trtable = false;
>    bitset_word_t elem, mask;
> -  bool dests_node_malloced = false;
> -  bool dest_states_malloced = false;
>    Idx ndests; /* Number of the destination states from 'state'.  */
>    re_dfastate_t **trtable;
> -  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
> -  re_node_set follows, *dests_node;
> -  bitset_t *dests_ch;
> +  re_dfastate_t *dest_states[SBC_MAX];
> +  re_dfastate_t *dest_states_word[SBC_MAX];
> +  re_dfastate_t *dest_states_nl[SBC_MAX];
> +  re_node_set follows;
>    bitset_t acceptable;
>  
> -  struct dests_alloc
> -  {
> -    re_node_set dests_node[SBC_MAX];
> -    bitset_t dests_ch[SBC_MAX];
> -  } *dests_alloc;
> -
>    /* We build DFA states which corresponds to the destination nodes
>       from 'state'.  'dests_node[i]' represents the nodes which i-th
>       destination state contains, and 'dests_ch[i]' represents the
>       characters which i-th destination state accepts.  */
> -  if (__libc_use_alloca (sizeof (struct dests_alloc)))
> -    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
> -  else
> -    {
> -      dests_alloc = re_malloc (struct dests_alloc, 1);
> -      if (__glibc_unlikely (dests_alloc == NULL))
> -	return false;
> -      dests_node_malloced = true;
> -    }
> -  dests_node = dests_alloc->dests_node;
> -  dests_ch = dests_alloc->dests_ch;
> +  re_node_set dests_node[SBC_MAX];
> +  bitset_t dests_ch[SBC_MAX];
>  
>    /* Initialize transition table.  */
>    state->word_trtable = state->trtable = NULL;
> @@ -3294,8 +3278,6 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
>    ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
>    if (__glibc_unlikely (ndests <= 0))
>      {
> -      if (dests_node_malloced)
> -	re_free (dests_alloc);
>        /* Return false in case of an error, true otherwise.  */
>        if (ndests == 0)
>  	{
> @@ -3310,38 +3292,14 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
>  
>    err = re_node_set_alloc (&follows, ndests + 1);
>    if (__glibc_unlikely (err != REG_NOERROR))
> -    goto out_free;
> -
> -  /* Avoid arithmetic overflow in size calculation.  */
> -  size_t ndests_max
> -    = ((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
> -       / (3 * sizeof (re_dfastate_t *)));
> -  if (__glibc_unlikely (ndests_max < ndests))
> -    goto out_free;
> -
> -  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
> -			 + ndests * 3 * sizeof (re_dfastate_t *)))
> -    dest_states = (re_dfastate_t **)
> -      alloca (ndests * 3 * sizeof (re_dfastate_t *));
> -  else
>      {
> -      dest_states = re_malloc (re_dfastate_t *, ndests * 3);
> -      if (__glibc_unlikely (dest_states == NULL))
> -	{
> -out_free:
> -	  if (dest_states_malloced)
> -	    re_free (dest_states);
> -	  re_node_set_free (&follows);
> -	  for (i = 0; i < ndests; ++i)
> -	    re_node_set_free (dests_node + i);
> -	  if (dests_node_malloced)
> -	    re_free (dests_alloc);
> -	  return false;
> -	}
> -      dest_states_malloced = true;
> +    out_free:
> +      re_node_set_free (&follows);
> +      for (i = 0; i < ndests; ++i)
> +	re_node_set_free (dests_node + i);
> +      return false;
>      }
> -  dest_states_word = dest_states + ndests;
> -  dest_states_nl = dest_states_word + ndests;
> +
>    bitset_empty (acceptable);
>  
>    /* Then build the states for all destinations.  */
> @@ -3466,16 +3424,9 @@ out_free:
>  	  }
>      }
>  
> -  if (dest_states_malloced)
> -    re_free (dest_states);
> -
>    re_node_set_free (&follows);
>    for (i = 0; i < ndests; ++i)
>      re_node_set_free (dests_node + i);
> -
> -  if (dests_node_malloced)
> -    re_free (dests_alloc);
> -
>    return true;
>  }
>  
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 5/5] regex: stop using alloca
  2021-01-13 16:58 ` [PATCH v2 5/5] regex: stop using alloca Adhemerval Zanella
@ 2021-02-09 19:12   ` Adhemerval Zanella
  0 siblings, 0 replies; 14+ messages in thread
From: Adhemerval Zanella @ 2021-02-09 19:12 UTC (permalink / raw)
  To: libc-alpha

I will commit this shortly if no one opposes it.

On 13/01/2021 13:58, Adhemerval Zanella wrote:
> It syncs with gnulib version 87ed1f9c4.  No functional changes is
> expected.
> 
> Checked on x86_64-linux-gnu.
> ---
>  posix/regex_internal.h | 19 -------------------
>  1 file changed, 19 deletions(-)
> 
> diff --git a/posix/regex_internal.h b/posix/regex_internal.h
> index e31ac92674..641b27e2b1 100644
> --- a/posix/regex_internal.h
> +++ b/posix/regex_internal.h
> @@ -444,25 +444,6 @@ typedef struct re_dfa_t re_dfa_t;
>  #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
>  #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
>  
> -#if defined _LIBC || HAVE_ALLOCA
> -# include <alloca.h>
> -#endif
> -
> -#ifndef _LIBC
> -# if HAVE_ALLOCA
> -/* The OS usually guarantees only one guard page at the bottom of the stack,
> -   and a page size can be as small as 4096 bytes.  So we cannot safely
> -   allocate anything larger than 4096 bytes.  Also care for the possibility
> -   of a few compiler-allocated temporary stack slots.  */
> -#  define __libc_use_alloca(n) ((n) < 4032)
> -# else
> -/* alloca is implemented with malloc, so just use malloc.  */
> -#  define __libc_use_alloca(n) 0
> -#  undef alloca
> -#  define alloca(n) malloc (n)
> -# endif
> -#endif
> -
>  #ifdef _LIBC
>  # define MALLOC_0_IS_NONNULL 1
>  #elif !defined MALLOC_0_IS_NONNULL
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2021-02-09 19:12 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-13 16:58 [PATCH 1/5] misc: Sync cdefs.h with gnulib Adhemerval Zanella
2021-01-13 16:58 ` [PATCH 2/5] malloc: Sync dynarray " Adhemerval Zanella
2021-02-09 19:12   ` Adhemerval Zanella
2021-01-13 16:58 ` [PATCH v2 3/5] regex: remove alloca usage on regex set_regs Adhemerval Zanella
2021-02-09 19:12   ` Adhemerval Zanella
2021-01-13 16:58 ` [PATCH v2 4/5] regexec: remove alloca usage in build_trtable Adhemerval Zanella
2021-02-09 19:12   ` Adhemerval Zanella
2021-01-13 16:58 ` [PATCH v2 5/5] regex: stop using alloca Adhemerval Zanella
2021-02-09 19:12   ` Adhemerval Zanella
2021-01-13 18:09 ` [PATCH 1/5] misc: Sync cdefs.h with gnulib Joseph Myers
2021-01-13 18:30   ` Adhemerval Zanella
2021-02-09 14:07     ` Adhemerval Zanella
2021-01-13 19:19 ` Paul Eggert
2021-01-13 19:21   ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).