Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] libiberty: sync with gcc
@ 2024-06-29 17:17 Sam James
  2024-07-12  7:55 ` Sam James
  0 siblings, 1 reply; 14+ messages in thread
From: Sam James @ 2024-06-29 17:17 UTC (permalink / raw)
  To: binutils, gdb-patches; +Cc: Sam James

This imports the following commits from GCC as of r15-1722-g7682d115402743:
	ca2f7c84927f libiberty: Invoke D demangler when --format=auto
	94792057ad4a Fix up duplicated words mostly in comments, part 1
	20e57660e64e libiberty: Fix error return value in pex_unix_exec_child [PR113957].
	52ac4c6be866 [libiberty] remove TBAA violation in iterative_hash, improve code-gen
	53bb7145135c libiberty: Fix up libiberty_vprintf_buffer_size
	65388b28656d c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal
---
 libiberty/ChangeLog                     | 45 +++++++++++++++++
 libiberty/cplus-dem.c                   |  2 +-
 libiberty/dyn-string.c                  |  2 +-
 libiberty/functions.texi                | 14 +++---
 libiberty/hashtab.c                     | 23 ++++-----
 libiberty/pex-unix.c                    |  2 +
 libiberty/regex.c                       |  2 +-
 libiberty/testsuite/d-demangle-expected |  5 ++
 libiberty/vprintf-support.c             | 65 ++++++++++++++++++++++---
 9 files changed, 131 insertions(+), 29 deletions(-)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 884c8b70f87..cdcd4b3ced8 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,48 @@
+2024-04-02  Tom Tromey  <tom@tromey.com>
+
+	* cplus-dem.c (cplus_demangle): Try the D demangler with
+	"auto" format.
+	* testsuite/d-demangle-expected: Add --format=auto test.
+
+2024-04-02  Jakub Jelinek  <jakub@redhat.com>
+
+	* regex.c (byte_re_match_2_internal): Fix duplicated words in comment;
+	next next -> next.
+	* dyn-string.c (dyn_string_init): Fix duplicated words in comment;
+	of of -> of.
+
+2024-02-19  Iain Sandoe  <iain@sandoe.co.uk>
+
+	PR other/113957
+	* pex-unix.c (pex_unix_exec_child): Set pid = -1 in the error
+	paths, since that is used to signal an erroneous outcome for
+	the routine.
+
+2024-02-15  Richard Biener  <rguenther@suse.de>
+
+	* hashtab.c (iterative_hash): Remove TBAA violating handling
+	of aligned little-endian case in favor of just keeping the
+	aligned case special-cased.  Use | for composing a larger word.
+
+2024-02-12  Jakub Jelinek  <jakub@redhat.com>
+
+	* vprintf-support.c (libiberty_vprintf_buffer_size): Handle
+	properly l, ll, z, t or on _WIN32 I64 modifiers for diouxX
+	and L modifier for fFgGeE.
+
+2024-01-13  Jakub Jelinek  <jakub@redhat.com>
+
+	* cp-demangle.c (FNQUAL_COMPONENT_CASE): Add case for
+	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
+	(d_dump): Handle DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
+	(d_nested_name): Parse H after N in nested name.
+	(d_count_templates_scopes): Handle
+	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
+	(d_print_mod): Likewise.
+	(d_print_function_type): Likewise.
+	* testsuite/demangle-expected: Add tests for explicit object
+	member functions.
+
 2023-12-05  Jakub Jelinek  <jakub@redhat.com>
 
 	* configure.ac (HAVE_X86_SHA1_HW_SUPPORT): Verify __get_cpuid and
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 8b92946981f..ee9e84f5d6b 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -186,7 +186,7 @@ cplus_demangle (const char *mangled, int options)
   if (GNAT_DEMANGLING)
     return ada_demangle (mangled, options);
 
-  if (DLANG_DEMANGLING)
+  if (DLANG_DEMANGLING || AUTO_DEMANGLING)
     {
       ret = dlang_demangle (mangled, options);
       if (ret)
diff --git a/libiberty/dyn-string.c b/libiberty/dyn-string.c
index ecd8c069984..5805c0b4ff8 100644
--- a/libiberty/dyn-string.c
+++ b/libiberty/dyn-string.c
@@ -47,7 +47,7 @@ Boston, MA 02110-1301, USA.  */
 
 /* Performs in-place initialization of a dyn_string struct.  This
    function can be used with a dyn_string struct on the stack or
-   embedded in another object.  The contents of of the string itself
+   embedded in another object.  The contents of the string itself
    are still dynamically allocated.  The string initially is capable
    of holding at least SPACE characeters, including the terminating
    NUL.  If SPACE is 0, it will silently be increated to 1.  
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index 651b169b040..b56b02e0686 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -165,7 +165,7 @@ not recommended.
 
 @end deftypefn
 
-@c make-temp-file.c:108
+@c make-temp-file.c:95
 @deftypefn Replacement const char* choose_tmpdir ()
 
 Returns a pointer to a directory path suitable for creating temporary
@@ -192,7 +192,7 @@ Concatenate zero or more of strings and return the result in freshly
 
 @end deftypefn
 
-@c argv.c:485
+@c argv.c:495
 @deftypefn Extension int countargv (char * const *@var{argv})
 
 Return the number of elements in @var{argv}.
@@ -257,7 +257,7 @@ symbolic name or message.
 
 @end deftypefn
 
-@c argv.c:339
+@c argv.c:352
 @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
 
 The @var{argcp} and @code{argvp} arguments are pointers to the usual
@@ -726,7 +726,7 @@ relative prefix can be found, return @code{NULL}.
 
 @end deftypefn
 
-@c make-temp-file.c:185
+@c make-temp-file.c:173
 @deftypefn Replacement char* make_temp_file (const char *@var{suffix})
 
 Return a temporary file name (as a string) or @code{NULL} if unable to
@@ -1747,7 +1747,7 @@ that the converted value is unsigned.
 @c strtoll.c:33
 @deftypefn Supplemental {long long int} strtoll (const char *@var{string}, @
   char **@var{endptr}, int @var{base})
-@deftypefnx Supplemental {unsigned long long int} strtoul (@
+@deftypefnx Supplemental {unsigned long long int} strtoull (@
   const char *@var{string}, char **@var{endptr}, int @var{base})
 
 The @code{strtoll} function converts the string in @var{string} to a
@@ -1938,8 +1938,8 @@ does the return value.  The third argument is unused in @libib{}.
 @deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
 
 Write each member of ARGV, handling all necessary quoting, to the file
-associated with FILE, separated by whitespace.  Return 0 on success,
-non-zero if an error occurred while writing to FILE.
+named by FILE, separated by whitespace.  Return 0 on success, non-zero
+if an error occurred while writing to FILE.
 
 @end deftypefn
 
diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c
index 48f28078114..e3a07256a30 100644
--- a/libiberty/hashtab.c
+++ b/libiberty/hashtab.c
@@ -940,26 +940,23 @@ iterative_hash (const void *k_in /* the key */,
   c = initval;           /* the previous hash value */
 
   /*---------------------------------------- handle most of the key */
-#ifndef WORDS_BIGENDIAN
-  /* On a little-endian machine, if the data is 4-byte aligned we can hash
-     by word for better speed.  This gives nondeterministic results on
-     big-endian machines.  */
-  if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
-    while (len >= 12)    /* aligned */
+  /* Provide specialization for the aligned case for targets that cannot
+     efficiently perform misaligned loads of a merged access.  */
+  if ((((size_t)k)&3) == 0)
+    while (len >= 12)
       {
-	a += *(hashval_t *)(k+0);
-	b += *(hashval_t *)(k+4);
-	c += *(hashval_t *)(k+8);
+	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
+	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
+	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
 	mix(a,b,c);
 	k += 12; len -= 12;
       }
   else /* unaligned */
-#endif
     while (len >= 12)
       {
-	a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
-	b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
-	c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
+	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
+	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
+	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
 	mix(a,b,c);
 	k += 12; len -= 12;
       }
diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c
index af98062a94c..f3a1cc95ada 100644
--- a/libiberty/pex-unix.c
+++ b/libiberty/pex-unix.c
@@ -695,6 +695,7 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
 	{
 	  *err = ret;
 	  *errmsg = "posix_spawnp";
+	  pid = -1; /* The value of pid is unspecified on failure.  */
 	  goto exit;
 	}
     }
@@ -705,6 +706,7 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
 	{
 	  *err = ret;
 	  *errmsg = "posix_spawn";
+	  pid = -1;
 	  goto exit;
 	}
     }
diff --git a/libiberty/regex.c b/libiberty/regex.c
index 4841c5a08f9..67747e6ce5a 100644
--- a/libiberty/regex.c
+++ b/libiberty/regex.c
@@ -5597,7 +5597,7 @@ byte_re_match_2_internal (struct re_pattern_buffer *bufp,
      to resume scanning the pattern; the second one is where to resume
      scanning the strings.  If the latter is zero, the failure point is
      a ``dummy''; if a failure happens and the failure point is a dummy,
-     it gets discarded and the next next one is tried.  */
+     it gets discarded and the next one is tried.  */
 #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
   PREFIX(fail_stack_type) fail_stack;
 #endif
diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected
index 47b059c4298..cfbdf2a52cb 100644
--- a/libiberty/testsuite/d-demangle-expected
+++ b/libiberty/testsuite/d-demangle-expected
@@ -1470,3 +1470,8 @@ demangle.anonymous
 --format=dlang
 _D8demangle9anonymous03fooZ
 demangle.anonymous.foo
+#
+# Test that 'auto' works.
+--format=auto
+_D8demangle9anonymous03fooZ
+demangle.anonymous.foo
diff --git a/libiberty/vprintf-support.c b/libiberty/vprintf-support.c
index b590e5ab034..0543ec0554e 100644
--- a/libiberty/vprintf-support.c
+++ b/libiberty/vprintf-support.c
@@ -56,6 +56,7 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
     {
       if (*p++ == '%')
 	{
+	  int prec = 0;
 	  while (strchr ("-+ #0", *p))
 	    ++p;
 	  if (*p == '*')
@@ -76,8 +77,43 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
 	      else
 	      total_width += strtoul (p, (char **) &p, 10);
 	    }
-	  while (strchr ("hlL", *p))
-	    ++p;
+	  do
+	    {
+	      switch (*p)
+		{
+		case 'h':
+		  ++p;
+		  continue;
+		case 'l':
+		case 'L':
+		  ++prec;
+		  ++p;
+		  continue;
+		case 'z':
+		  prec = 3;
+		  ++p;
+		  continue;
+		case 't':
+		  prec = 4;
+		  ++p;
+		  continue;
+#ifdef _WIN32
+		case 'I':
+		  if (p[1] == '6' && p[2] == '4')
+		    {
+		      prec = 2;
+		      p += 3;
+		      continue;
+		    }
+		  break;
+#endif
+		default:
+		  break;
+		}
+	      break;
+	    }
+	  while (1);
+
 	  /* Should be big enough for any format specifier except %s and floats.  */
 	  total_width += 30;
 	  switch (*p)
@@ -88,6 +124,15 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
 	    case 'u':
 	    case 'x':
 	    case 'X':
+	      switch (prec)
+		{
+		case 0: (void) va_arg (ap, int); break;
+		case 1: (void) va_arg (ap, long int); break;
+		case 2: (void) va_arg (ap, long long int); break;
+		case 3: (void) va_arg (ap, size_t); break;
+		case 4: (void) va_arg (ap, ptrdiff_t); break;
+		}
+	      break;
 	    case 'c':
 	      (void) va_arg (ap, int);
 	      break;
@@ -96,10 +141,18 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
 	    case 'E':
 	    case 'g':
 	    case 'G':
-	      (void) va_arg (ap, double);
-	      /* Since an ieee double can have an exponent of 307, we'll
-		 make the buffer wide enough to cover the gross case. */
-	      total_width += 307;
+	      if (!prec)
+		{
+		  (void) va_arg (ap, double);
+		  /* Since an ieee double can have an exponent of 308, we'll
+		     make the buffer wide enough to cover the gross case. */
+		  total_width += 308;
+		}
+	      else
+		{
+		  (void) va_arg (ap, long double);
+		  total_width += 4932;
+		}
 	      break;
 	    case 's':
 	      total_width += strlen (va_arg (ap, char *));
-- 
2.45.2


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

* Re: [PATCH] libiberty: sync with gcc
  2024-06-29 17:17 [PATCH] libiberty: sync with gcc Sam James
@ 2024-07-12  7:55 ` Sam James
  2024-07-12  8:06   ` Nick Clifton
  0 siblings, 1 reply; 14+ messages in thread
From: Sam James @ 2024-07-12  7:55 UTC (permalink / raw)
  To: binutils; +Cc: gdb-patches, Nick Clifton

[-- Attachment #1: Type: text/plain, Size: 13190 bytes --]

Sam James <sam@gentoo.org> writes:

> This imports the following commits from GCC as of r15-1722-g7682d115402743:
> 	ca2f7c84927f libiberty: Invoke D demangler when --format=auto
> 	94792057ad4a Fix up duplicated words mostly in comments, part 1
> 	20e57660e64e libiberty: Fix error return value in pex_unix_exec_child [PR113957].
> 	52ac4c6be866 [libiberty] remove TBAA violation in iterative_hash, improve code-gen
> 	53bb7145135c libiberty: Fix up libiberty_vprintf_buffer_size
> 	65388b28656d c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal
> ---

ping. It might be nice for this to get in for binutils-2.43 branching
given the UB fix for hashing.

>  libiberty/ChangeLog                     | 45 +++++++++++++++++
>  libiberty/cplus-dem.c                   |  2 +-
>  libiberty/dyn-string.c                  |  2 +-
>  libiberty/functions.texi                | 14 +++---
>  libiberty/hashtab.c                     | 23 ++++-----
>  libiberty/pex-unix.c                    |  2 +
>  libiberty/regex.c                       |  2 +-
>  libiberty/testsuite/d-demangle-expected |  5 ++
>  libiberty/vprintf-support.c             | 65 ++++++++++++++++++++++---
>  9 files changed, 131 insertions(+), 29 deletions(-)
>
> diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
> index 884c8b70f87..cdcd4b3ced8 100644
> --- a/libiberty/ChangeLog
> +++ b/libiberty/ChangeLog
> @@ -1,3 +1,48 @@
> +2024-04-02  Tom Tromey  <tom@tromey.com>
> +
> +	* cplus-dem.c (cplus_demangle): Try the D demangler with
> +	"auto" format.
> +	* testsuite/d-demangle-expected: Add --format=auto test.
> +
> +2024-04-02  Jakub Jelinek  <jakub@redhat.com>
> +
> +	* regex.c (byte_re_match_2_internal): Fix duplicated words in comment;
> +	next next -> next.
> +	* dyn-string.c (dyn_string_init): Fix duplicated words in comment;
> +	of of -> of.
> +
> +2024-02-19  Iain Sandoe  <iain@sandoe.co.uk>
> +
> +	PR other/113957
> +	* pex-unix.c (pex_unix_exec_child): Set pid = -1 in the error
> +	paths, since that is used to signal an erroneous outcome for
> +	the routine.
> +
> +2024-02-15  Richard Biener  <rguenther@suse.de>
> +
> +	* hashtab.c (iterative_hash): Remove TBAA violating handling
> +	of aligned little-endian case in favor of just keeping the
> +	aligned case special-cased.  Use | for composing a larger word.
> +
> +2024-02-12  Jakub Jelinek  <jakub@redhat.com>
> +
> +	* vprintf-support.c (libiberty_vprintf_buffer_size): Handle
> +	properly l, ll, z, t or on _WIN32 I64 modifiers for diouxX
> +	and L modifier for fFgGeE.
> +
> +2024-01-13  Jakub Jelinek  <jakub@redhat.com>
> +
> +	* cp-demangle.c (FNQUAL_COMPONENT_CASE): Add case for
> +	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> +	(d_dump): Handle DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> +	(d_nested_name): Parse H after N in nested name.
> +	(d_count_templates_scopes): Handle
> +	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> +	(d_print_mod): Likewise.
> +	(d_print_function_type): Likewise.
> +	* testsuite/demangle-expected: Add tests for explicit object
> +	member functions.
> +
>  2023-12-05  Jakub Jelinek  <jakub@redhat.com>
>  
>  	* configure.ac (HAVE_X86_SHA1_HW_SUPPORT): Verify __get_cpuid and
> diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
> index 8b92946981f..ee9e84f5d6b 100644
> --- a/libiberty/cplus-dem.c
> +++ b/libiberty/cplus-dem.c
> @@ -186,7 +186,7 @@ cplus_demangle (const char *mangled, int options)
>    if (GNAT_DEMANGLING)
>      return ada_demangle (mangled, options);
>  
> -  if (DLANG_DEMANGLING)
> +  if (DLANG_DEMANGLING || AUTO_DEMANGLING)
>      {
>        ret = dlang_demangle (mangled, options);
>        if (ret)
> diff --git a/libiberty/dyn-string.c b/libiberty/dyn-string.c
> index ecd8c069984..5805c0b4ff8 100644
> --- a/libiberty/dyn-string.c
> +++ b/libiberty/dyn-string.c
> @@ -47,7 +47,7 @@ Boston, MA 02110-1301, USA.  */
>  
>  /* Performs in-place initialization of a dyn_string struct.  This
>     function can be used with a dyn_string struct on the stack or
> -   embedded in another object.  The contents of of the string itself
> +   embedded in another object.  The contents of the string itself
>     are still dynamically allocated.  The string initially is capable
>     of holding at least SPACE characeters, including the terminating
>     NUL.  If SPACE is 0, it will silently be increated to 1.  
> diff --git a/libiberty/functions.texi b/libiberty/functions.texi
> index 651b169b040..b56b02e0686 100644
> --- a/libiberty/functions.texi
> +++ b/libiberty/functions.texi
> @@ -165,7 +165,7 @@ not recommended.
>  
>  @end deftypefn
>  
> -@c make-temp-file.c:108
> +@c make-temp-file.c:95
>  @deftypefn Replacement const char* choose_tmpdir ()
>  
>  Returns a pointer to a directory path suitable for creating temporary
> @@ -192,7 +192,7 @@ Concatenate zero or more of strings and return the result in freshly
>  
>  @end deftypefn
>  
> -@c argv.c:485
> +@c argv.c:495
>  @deftypefn Extension int countargv (char * const *@var{argv})
>  
>  Return the number of elements in @var{argv}.
> @@ -257,7 +257,7 @@ symbolic name or message.
>  
>  @end deftypefn
>  
> -@c argv.c:339
> +@c argv.c:352
>  @deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
>  
>  The @var{argcp} and @code{argvp} arguments are pointers to the usual
> @@ -726,7 +726,7 @@ relative prefix can be found, return @code{NULL}.
>  
>  @end deftypefn
>  
> -@c make-temp-file.c:185
> +@c make-temp-file.c:173
>  @deftypefn Replacement char* make_temp_file (const char *@var{suffix})
>  
>  Return a temporary file name (as a string) or @code{NULL} if unable to
> @@ -1747,7 +1747,7 @@ that the converted value is unsigned.
>  @c strtoll.c:33
>  @deftypefn Supplemental {long long int} strtoll (const char *@var{string}, @
>    char **@var{endptr}, int @var{base})
> -@deftypefnx Supplemental {unsigned long long int} strtoul (@
> +@deftypefnx Supplemental {unsigned long long int} strtoull (@
>    const char *@var{string}, char **@var{endptr}, int @var{base})
>  
>  The @code{strtoll} function converts the string in @var{string} to a
> @@ -1938,8 +1938,8 @@ does the return value.  The third argument is unused in @libib{}.
>  @deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
>  
>  Write each member of ARGV, handling all necessary quoting, to the file
> -associated with FILE, separated by whitespace.  Return 0 on success,
> -non-zero if an error occurred while writing to FILE.
> +named by FILE, separated by whitespace.  Return 0 on success, non-zero
> +if an error occurred while writing to FILE.
>  
>  @end deftypefn
>  
> diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c
> index 48f28078114..e3a07256a30 100644
> --- a/libiberty/hashtab.c
> +++ b/libiberty/hashtab.c
> @@ -940,26 +940,23 @@ iterative_hash (const void *k_in /* the key */,
>    c = initval;           /* the previous hash value */
>  
>    /*---------------------------------------- handle most of the key */
> -#ifndef WORDS_BIGENDIAN
> -  /* On a little-endian machine, if the data is 4-byte aligned we can hash
> -     by word for better speed.  This gives nondeterministic results on
> -     big-endian machines.  */
> -  if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
> -    while (len >= 12)    /* aligned */
> +  /* Provide specialization for the aligned case for targets that cannot
> +     efficiently perform misaligned loads of a merged access.  */
> +  if ((((size_t)k)&3) == 0)
> +    while (len >= 12)
>        {
> -	a += *(hashval_t *)(k+0);
> -	b += *(hashval_t *)(k+4);
> -	c += *(hashval_t *)(k+8);
> +	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
> +	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
> +	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
>  	mix(a,b,c);
>  	k += 12; len -= 12;
>        }
>    else /* unaligned */
> -#endif
>      while (len >= 12)
>        {
> -	a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
> -	b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
> -	c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
> +	a += (k[0] | ((hashval_t)k[1]<<8) | ((hashval_t)k[2]<<16) | ((hashval_t)k[3]<<24));
> +	b += (k[4] | ((hashval_t)k[5]<<8) | ((hashval_t)k[6]<<16) | ((hashval_t)k[7]<<24));
> +	c += (k[8] | ((hashval_t)k[9]<<8) | ((hashval_t)k[10]<<16)| ((hashval_t)k[11]<<24));
>  	mix(a,b,c);
>  	k += 12; len -= 12;
>        }
> diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c
> index af98062a94c..f3a1cc95ada 100644
> --- a/libiberty/pex-unix.c
> +++ b/libiberty/pex-unix.c
> @@ -695,6 +695,7 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
>  	{
>  	  *err = ret;
>  	  *errmsg = "posix_spawnp";
> +	  pid = -1; /* The value of pid is unspecified on failure.  */
>  	  goto exit;
>  	}
>      }
> @@ -705,6 +706,7 @@ pex_unix_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED,
>  	{
>  	  *err = ret;
>  	  *errmsg = "posix_spawn";
> +	  pid = -1;
>  	  goto exit;
>  	}
>      }
> diff --git a/libiberty/regex.c b/libiberty/regex.c
> index 4841c5a08f9..67747e6ce5a 100644
> --- a/libiberty/regex.c
> +++ b/libiberty/regex.c
> @@ -5597,7 +5597,7 @@ byte_re_match_2_internal (struct re_pattern_buffer *bufp,
>       to resume scanning the pattern; the second one is where to resume
>       scanning the strings.  If the latter is zero, the failure point is
>       a ``dummy''; if a failure happens and the failure point is a dummy,
> -     it gets discarded and the next next one is tried.  */
> +     it gets discarded and the next one is tried.  */
>  #ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global.  */
>    PREFIX(fail_stack_type) fail_stack;
>  #endif
> diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected
> index 47b059c4298..cfbdf2a52cb 100644
> --- a/libiberty/testsuite/d-demangle-expected
> +++ b/libiberty/testsuite/d-demangle-expected
> @@ -1470,3 +1470,8 @@ demangle.anonymous
>  --format=dlang
>  _D8demangle9anonymous03fooZ
>  demangle.anonymous.foo
> +#
> +# Test that 'auto' works.
> +--format=auto
> +_D8demangle9anonymous03fooZ
> +demangle.anonymous.foo
> diff --git a/libiberty/vprintf-support.c b/libiberty/vprintf-support.c
> index b590e5ab034..0543ec0554e 100644
> --- a/libiberty/vprintf-support.c
> +++ b/libiberty/vprintf-support.c
> @@ -56,6 +56,7 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
>      {
>        if (*p++ == '%')
>  	{
> +	  int prec = 0;
>  	  while (strchr ("-+ #0", *p))
>  	    ++p;
>  	  if (*p == '*')
> @@ -76,8 +77,43 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
>  	      else
>  	      total_width += strtoul (p, (char **) &p, 10);
>  	    }
> -	  while (strchr ("hlL", *p))
> -	    ++p;
> +	  do
> +	    {
> +	      switch (*p)
> +		{
> +		case 'h':
> +		  ++p;
> +		  continue;
> +		case 'l':
> +		case 'L':
> +		  ++prec;
> +		  ++p;
> +		  continue;
> +		case 'z':
> +		  prec = 3;
> +		  ++p;
> +		  continue;
> +		case 't':
> +		  prec = 4;
> +		  ++p;
> +		  continue;
> +#ifdef _WIN32
> +		case 'I':
> +		  if (p[1] == '6' && p[2] == '4')
> +		    {
> +		      prec = 2;
> +		      p += 3;
> +		      continue;
> +		    }
> +		  break;
> +#endif
> +		default:
> +		  break;
> +		}
> +	      break;
> +	    }
> +	  while (1);
> +
>  	  /* Should be big enough for any format specifier except %s and floats.  */
>  	  total_width += 30;
>  	  switch (*p)
> @@ -88,6 +124,15 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
>  	    case 'u':
>  	    case 'x':
>  	    case 'X':
> +	      switch (prec)
> +		{
> +		case 0: (void) va_arg (ap, int); break;
> +		case 1: (void) va_arg (ap, long int); break;
> +		case 2: (void) va_arg (ap, long long int); break;
> +		case 3: (void) va_arg (ap, size_t); break;
> +		case 4: (void) va_arg (ap, ptrdiff_t); break;
> +		}
> +	      break;
>  	    case 'c':
>  	      (void) va_arg (ap, int);
>  	      break;
> @@ -96,10 +141,18 @@ libiberty_vprintf_buffer_size (const char *format, va_list args)
>  	    case 'E':
>  	    case 'g':
>  	    case 'G':
> -	      (void) va_arg (ap, double);
> -	      /* Since an ieee double can have an exponent of 307, we'll
> -		 make the buffer wide enough to cover the gross case. */
> -	      total_width += 307;
> +	      if (!prec)
> +		{
> +		  (void) va_arg (ap, double);
> +		  /* Since an ieee double can have an exponent of 308, we'll
> +		     make the buffer wide enough to cover the gross case. */
> +		  total_width += 308;
> +		}
> +	      else
> +		{
> +		  (void) va_arg (ap, long double);
> +		  total_width += 4932;
> +		}
>  	      break;
>  	    case 's':
>  	      total_width += strlen (va_arg (ap, char *));

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 377 bytes --]

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

* Re: [PATCH] libiberty: sync with gcc
  2024-07-12  7:55 ` Sam James
@ 2024-07-12  8:06   ` Nick Clifton
  2024-07-12 21:49     ` Sam James
  0 siblings, 1 reply; 14+ messages in thread
From: Nick Clifton @ 2024-07-12  8:06 UTC (permalink / raw)
  To: Sam James, binutils; +Cc: gdb-patches

Hi Sam,

> Sam James <sam@gentoo.org> writes:
> 
>> This imports the following commits from GCC as of r15-1722-g7682d115402743:
>> 	ca2f7c84927f libiberty: Invoke D demangler when --format=auto
>> 	94792057ad4a Fix up duplicated words mostly in comments, part 1
>> 	20e57660e64e libiberty: Fix error return value in pex_unix_exec_child [PR113957].
>> 	52ac4c6be866 [libiberty] remove TBAA violation in iterative_hash, improve code-gen
>> 	53bb7145135c libiberty: Fix up libiberty_vprintf_buffer_size
>> 	65388b28656d c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal
>> ---
> 
> ping. It might be nice for this to get in for binutils-2.43 branching
> given the UB fix for hashing.

Yes you are right - please commit as soon as you can! :-)

Thanks for the reminder.

Cheers
   Nick


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

* Re: [PATCH] libiberty: sync with gcc
  2024-07-12  8:06   ` Nick Clifton
@ 2024-07-12 21:49     ` Sam James
  0 siblings, 0 replies; 14+ messages in thread
From: Sam James @ 2024-07-12 21:49 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils, gdb-patches

Nick Clifton <nickc@redhat.com> writes:

> Hi Sam,

Hi Nick,

>
>> Sam James <sam@gentoo.org> writes:
>> 
>>> This imports the following commits from GCC as of r15-1722-g7682d115402743:
>>> 	ca2f7c84927f libiberty: Invoke D demangler when --format=auto
>>> 	94792057ad4a Fix up duplicated words mostly in comments, part 1
>>> 	20e57660e64e libiberty: Fix error return value in pex_unix_exec_child [PR113957].
>>> 	52ac4c6be866 [libiberty] remove TBAA violation in iterative_hash, improve code-gen
>>> 	53bb7145135c libiberty: Fix up libiberty_vprintf_buffer_size
>>> 	65388b28656d c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal
>>> ---
>> ping. It might be nice for this to get in for binutils-2.43
>> branching
>> given the UB fix for hashing.
>
> Yes you are right - please commit as soon as you can! :-)
>
> Thanks for the reminder.
>

Pushed -- thank you! :)

> Cheers
>   Nick

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

* Re: [PATCH] libiberty: sync with gcc
  2025-07-23 17:36 ` Tom Tromey
@ 2025-07-25  9:17   ` Matthieu Longo
  0 siblings, 0 replies; 14+ messages in thread
From: Matthieu Longo @ 2025-07-25  9:17 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 2025-07-23 18:36, Tom Tromey wrote:
>>>>>> "Matthieu" == Matthieu Longo <matthieu.longo@arm.com> writes:
> 
> Matthieu> Import the following commits from GCC as of r16-2170-g2f2e9bcfb0fd9c:
> Matthieu> 	0fd98b6f9f2 libiberty: add routines to handle type-sensitive doubly linked lists
> 
> Thanks, this is ok.
> 
> Perhaps you wanted to CC the binutils list on this, since I don't think
> we'll be using this in gdb.
> 
> Tom

It was done here :)
https://inbox.sourceware.org/binutils/20250710132927.1612503-1-matthieu.longo@arm.com/

Matthieu


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

* Re: [PATCH] libiberty: sync with gcc
  2025-07-10 13:30 Matthieu Longo
@ 2025-07-23 17:36 ` Tom Tromey
  2025-07-25  9:17   ` Matthieu Longo
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2025-07-23 17:36 UTC (permalink / raw)
  To: Matthieu Longo; +Cc: gdb-patches

>>>>> "Matthieu" == Matthieu Longo <matthieu.longo@arm.com> writes:

Matthieu> Import the following commits from GCC as of r16-2170-g2f2e9bcfb0fd9c:
Matthieu> 	0fd98b6f9f2 libiberty: add routines to handle type-sensitive doubly linked lists

Thanks, this is ok.

Perhaps you wanted to CC the binutils list on this, since I don't think
we'll be using this in gdb.

Tom

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

* [PATCH] libiberty: sync with gcc
@ 2025-07-10 13:30 Matthieu Longo
  2025-07-23 17:36 ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Matthieu Longo @ 2025-07-10 13:30 UTC (permalink / raw)
  To: gdb-patches; +Cc: Matthieu Longo

Import the following commits from GCC as of r16-2170-g2f2e9bcfb0fd9c:
	0fd98b6f9f2 libiberty: add routines to handle type-sensitive doubly linked lists
---
 include/doubly-linked-list.h                  | 447 ++++++++++++++++++
 libiberty/Makefile.in                         |   1 +
 libiberty/testsuite/Makefile.in               |  12 +-
 libiberty/testsuite/test-doubly-linked-list.c | 269 +++++++++++
 4 files changed, 728 insertions(+), 1 deletion(-)
 create mode 100644 include/doubly-linked-list.h
 create mode 100644 libiberty/testsuite/test-doubly-linked-list.c

diff --git a/include/doubly-linked-list.h b/include/doubly-linked-list.h
new file mode 100644
index 00000000000..3f5ea2808f9
--- /dev/null
+++ b/include/doubly-linked-list.h
@@ -0,0 +1,447 @@
+/* Manipulate doubly linked lists.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifndef _DOUBLY_LINKED_LIST_H
+#define _DOUBLY_LINKED_LIST_H
+
+/* Doubly linked list implementation enforcing typing.
+
+   This implementation of doubly linked list tries to achieve the enforcement of
+   typing similarly to C++ templates, but without encapsulation.
+
+   All the functions are prefixed with the type of the value: "AType_xxx".
+   Some functions are prefixed with "_AType_xxx" and are not part of the public
+   API, so should not be used, except for _##LTYPE##_merge_sort with a caveat
+   (see note above its definition).
+
+   Each function (### is a placeholder for method name) has a macro for:
+   (1) its invocation LINKED_LIST_###(LTYPE).
+   (2) its prototype LINKED_LIST_DECL_###(A, A2, scope). To add in a header
+       file, or a source file for forward declaration. 'scope' should be set
+       respectively to 'extern', or 'static'.
+   (3) its definition LINKED_LIST_DEFN_###(A, A2, scope). To add in a source
+       file with the 'scope' set respectively to nothing, or 'static' depending
+       on (2).
+
+   Data structures requirements:
+   - LTYPE corresponds to the node of a doubly linked list. It needs to define
+     attributes 'prev' and 'next' which are pointers on the type of a node.
+     For instance:
+       struct my_list_node
+       {
+	 T value;
+	 struct my_list_node *prev;
+	 struct my_list_node *next;
+       };
+   - LWRAPPERTYPE is a structure wrapping the nodes and others metadata (first,
+     last, size).
+ */
+
+\f
+/* Mutative operations:
+    - append
+    - prepend
+    - insert_before
+    - pop_front
+    - pop_back
+    - remove
+    - swap
+   The header and body of each of those operation can be declared individually,
+   or as a whole via LINKED_LIST_MUTATIVE_OPS_PROTOTYPE for the prototypes, and
+   LINKED_LIST_MUTATIVE_OPS_DECL for the implementations.  */
+
+/* Append the given node new_ to the exising list.
+   Precondition: prev and next of new_ must be NULL.  */
+#define LINKED_LIST_APPEND(LTYPE)		LTYPE##_append
+
+#define LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT void								\
+  LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_)
+
+#define LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT void								\
+LTYPE##_append (LWRAPPERTYPE *wrapper, LTYPE *new_)			\
+{									\
+  if (wrapper->last == NULL)						\
+    wrapper->first = new_;						\
+  else									\
+    {									\
+      new_->prev = wrapper->last;					\
+      wrapper->last->next = new_;					\
+    }									\
+  wrapper->last = new_;							\
+  ++wrapper->size;							\
+}
+
+/* Prepend the given node new_ to the existing list.
+   Precondition: prev and next of new_ must be NULL.  */
+#define LINKED_LIST_PREPEND(LTYPE)		LTYPE##_prepend
+
+#define LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT void								\
+  LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_)
+
+#define LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT void								\
+LTYPE##_prepend (LWRAPPERTYPE *wrapper, LTYPE *new_)			\
+{									\
+  if (wrapper->first == NULL)						\
+    wrapper->last = new_;						\
+  else									\
+    {									\
+      new_->next = wrapper->first;					\
+      wrapper->first->prev = new_;					\
+    }									\
+  wrapper->first = new_;						\
+  ++wrapper->size;							\
+}
+
+/* Insert the given node new_ before 'where' in the existing list.
+   If where == NULL, the insertion is equivalent to an append.
+   If where == first, the insertion is equivalent to a prepend.  */
+#define LINKED_LIST_INSERT_BEFORE(LTYPE)	LTYPE##_insert_before
+
+#define LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT)	\
+  EXPORT void								\
+  LTYPE##_insert_before (LWRAPPERTYPE *wrapper,				\
+			 LTYPE *new_,					\
+			 LTYPE *where)
+
+#define LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT)	\
+EXPORT void								\
+LTYPE##_insert_before (LWRAPPERTYPE *wrapper,				\
+		       LTYPE *new_,					\
+		       LTYPE *where)					\
+{									\
+  if (where == wrapper->first)						\
+    LTYPE##_prepend (wrapper, new_);					\
+  else if (where == NULL)						\
+    LTYPE##_append (wrapper, new_);					\
+  else									\
+    {									\
+      where->prev->next = new_;						\
+      new_->prev = where->prev;						\
+      where->prev = new_;						\
+      new_->next = where;						\
+      ++wrapper->size;							\
+    }									\
+}
+
+/* Pop the first node of the list.  */
+#define LINKED_LIST_POP_FRONT(LTYPE)		LTYPE##_pop_front
+
+#define LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT LTYPE *							\
+  LTYPE##_pop_front (LWRAPPERTYPE *wrapper)
+
+#define LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT LTYPE *								\
+LTYPE##_pop_front (LWRAPPERTYPE *wrapper)				\
+{									\
+  LTYPE *front_node = wrapper->first;					\
+  if (front_node != NULL)						\
+    {									\
+      wrapper->first = front_node->next;				\
+      if (wrapper->last == front_node)					\
+	wrapper->last = NULL;						\
+      else								\
+	{								\
+	  front_node->next->prev = NULL;				\
+	  front_node->next = NULL;					\
+	}								\
+      front_node->next = NULL;						\
+      --wrapper->size;							\
+    }									\
+  return front_node;							\
+}
+
+/* Pop the last node of the list.  */
+#define LINKED_LIST_POP_BACK(LTYPE)		LTYPE##_pop_back
+
+#define LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT LTYPE *							\
+  LTYPE##_pop_back (LWRAPPERTYPE *wrapper)
+
+#define LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT LTYPE *								\
+LTYPE##_pop_back (LWRAPPERTYPE *wrapper)				\
+{									\
+  LTYPE *back_node = wrapper->last;					\
+  if (back_node != NULL)						\
+    {									\
+      wrapper->last = back_node->prev;					\
+      if (wrapper->first == back_node)					\
+	wrapper->first = NULL;						\
+      else								\
+	{								\
+	  back_node->prev->next = NULL;					\
+	  back_node->prev = NULL;					\
+	}								\
+      back_node->prev = NULL;						\
+      --wrapper->size;							\
+    }									\
+  return back_node;							\
+}
+
+/* Remove the given node from the existing list, and return the previous
+   node.  */
+#define LINKED_LIST_REMOVE(LTYPE)		LTYPE##_remove
+
+#define LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT LTYPE *							\
+  LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node)
+
+#define LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT LTYPE *								\
+LTYPE##_remove (LWRAPPERTYPE *wrapper, LTYPE *node)			\
+{									\
+  LTYPE *previous = NULL;						\
+									\
+  if (node->prev != NULL)						\
+    {									\
+      node->prev->next = node->next;					\
+      if (node->next == NULL)						\
+	wrapper->last = node->prev;					\
+      else								\
+	node->next->prev = node->prev;					\
+      previous = node->prev;						\
+      node->next = NULL;						\
+      node->prev = NULL;						\
+      --wrapper->size;							\
+    }									\
+  else									\
+    LTYPE##_pop_front (wrapper);					\
+									\
+  return previous;							\
+}
+
+/* Generic swap.  */
+#define LINKED_LIST_SWAP(LTYPE)			LTYPE##_swap
+
+#define LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  EXPORT void								\
+  LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2)
+
+/* Swap two nodes in a list.  */
+#define LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT)		\
+EXPORT void								\
+LTYPE##_swap (LWRAPPERTYPE *wrapper, LTYPE *node1, LTYPE *node2)	\
+{									\
+  LTYPE *prev1 = node1->prev;						\
+  LTYPE *next1 = node1->next;						\
+  LTYPE *prev2 = node2->prev;						\
+  LTYPE *next2 = node2->next;						\
+									\
+  if (prev1 != NULL)							\
+    prev1->next = node2;						\
+  else									\
+    wrapper->first = node2;						\
+  if (prev2 != NULL)							\
+    prev2->next = node1;						\
+  else									\
+    wrapper->first = node1;						\
+									\
+  if (next1 != NULL)							\
+    next1->prev = node2;						\
+  else									\
+    wrapper->last = node2;						\
+  if (next2 != NULL)							\
+    next2->prev = node1;						\
+  else									\
+    wrapper->last = node1;						\
+									\
+  {									\
+    LTYPE *temp = node1->next;						\
+    node1->next = node2->next;						\
+    node2->next = temp;							\
+  }									\
+  {									\
+    LTYPE *temp = node1->prev;						\
+    node1->prev = node2->prev;						\
+    node2->prev = temp;							\
+  }									\
+}
+
+/* Note: all the mutative operations below also update the data in the wrapper,
+   i.e. first, last and size.  */
+#define LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT)	\
+  LINKED_LIST_DECL_APPEND(LWRAPPERTYPE, LTYPE, EXPORT);			\
+  LINKED_LIST_DECL_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT);		\
+  LINKED_LIST_DECL_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT);		\
+  LINKED_LIST_DECL_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT);		\
+  LINKED_LIST_DECL_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT);		\
+  LINKED_LIST_DECL_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT);			\
+  LINKED_LIST_DECL_SWAP(LWRAPPERTYPE, LTYPE, EXPORT)
+
+#define LINKED_LIST_MUTATIVE_OPS_DECL(LWRAPPERTYPE, LTYPE, EXPORT)	\
+  LINKED_LIST_DEFN_APPEND(LWRAPPERTYPE, LTYPE, EXPORT)			\
+  LINKED_LIST_DEFN_PREPEND(LWRAPPERTYPE, LTYPE, EXPORT)			\
+  LINKED_LIST_DEFN_INSERT_BEFORE(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  LINKED_LIST_DEFN_POP_FRONT(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  LINKED_LIST_DEFN_POP_BACK(LWRAPPERTYPE, LTYPE, EXPORT)		\
+  LINKED_LIST_DEFN_REMOVE(LWRAPPERTYPE, LTYPE, EXPORT)			\
+  LINKED_LIST_DEFN_SWAP(LWRAPPERTYPE, LTYPE, EXPORT)
+
+\f
+/* Sorting.  */
+
+#define LINKED_LIST_MERGE_SORT_(LTYPE)	LTYPE##_merge_sort_
+
+#define LINKED_LIST_MERGE_SORT(LTYPE)	LTYPE##_merge_sort
+
+#define LINKED_LIST_MERGE_SORT_PROTOTYPE_(LTYPE, EXPORT)		\
+  EXPORT LTYPE *							\
+  LTYPE##_merge_sort_ (LTYPE *node,					\
+		       int (*fn_cmp) (const LTYPE *, const LTYPE *))
+
+#define LINKED_LIST_MERGE_SORT_PROTOTYPE(LWRAPPERTYPE, LTYPE, EXPORT)	\
+  EXPORT void								\
+  LTYPE##_merge_sort (LWRAPPERTYPE *wrapper,				\
+		      int (*fn_cmp) (const LTYPE *, const LTYPE *))
+
+/* Note: all the functions and macros below starting with "_" should be
+   considered private.  */
+
+/* Compute the middle element of the list based on the turtle and hare
+   approach, i.e. the hare runs twice faster than the turtle.  */
+#define _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE)				\
+static inline LTYPE *							\
+LTYPE##_merge_sort_compute_turtle_ (LTYPE *node)			\
+{									\
+  if (node == NULL)							\
+    return node;							\
+									\
+  LTYPE *turtle = node, *hare = node->next;				\
+  while (hare != NULL && hare->next != NULL)				\
+    {									\
+      turtle = turtle->next;						\
+      hare = hare->next->next;						\
+    }									\
+  return turtle;							\
+}
+
+/* Append n at the end of l_out, and return the next node after n.
+   l_out and l_last should be ideally encapsulated into a list structure
+   but this is overkill for what we need here.  */
+#define _MERGE_SORT_IMPL_OUT_APPEND(LTYPE)				\
+static inline LTYPE *							\
+LTYPE##_merge_sort_out_append_ (LTYPE **l_out, LTYPE **l_last,		\
+				LTYPE *n)				\
+{									\
+  if (*l_last == NULL)							\
+    {									\
+      *l_last = n;							\
+      *l_out = n;							\
+      n->prev = NULL;							\
+    }									\
+  else									\
+    {									\
+      (*l_last)->next = n;						\
+      n->prev = *l_last;						\
+      *l_last = n;							\
+    }									\
+									\
+  return n->next;							\
+}
+
+/* Merge two sorted lists together.
+   The returned value corresponds to the first element of the list.
+   Note: both input lists are invalidated after the call.  */
+#define _MERGE_SORT_IMPL_MERGE(LTYPE)					\
+static inline LTYPE *							\
+LTYPE##_merge_sort_merge_ (LTYPE *l_left, LTYPE *l_right,		\
+			   int (*fn_cmp) (const LTYPE *, const LTYPE *))\
+{									\
+  if (l_left == NULL)							\
+    return l_right;							\
+  else if (l_right == NULL)						\
+    return l_left;							\
+									\
+  LTYPE *l_out = NULL, *l_last = NULL;					\
+									\
+  LTYPE *l_l = l_left, *l_r = l_right;					\
+  while (l_l != NULL && l_r != NULL)					\
+    {									\
+      int cmp = fn_cmp (l_l, l_r);					\
+      if (cmp <= 0)							\
+	l_l = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_l);	\
+      else								\
+	l_r = LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_r);	\
+    }									\
+									\
+  LTYPE *l_remaining = (l_l != NULL) ? l_l : l_r;			\
+  while (l_remaining != NULL)						\
+    l_remaining =							\
+      LTYPE##_merge_sort_out_append_ (&l_out, &l_last, l_remaining);	\
+									\
+  return l_out;								\
+}
+
+/* Merge sort implementation taking the first node of the list to sort,
+   and the comparison function. Returns the first node of the sorted list.
+   Note: use this if you don't care about updating the information in the
+   wrapper.  */
+#define _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT)				\
+EXPORT LTYPE *								\
+LTYPE##_merge_sort_ (LTYPE *node,					\
+		     int (*fn_cmp)(const LTYPE *, const LTYPE *))	\
+{									\
+  if (node == NULL)							\
+    return NULL;							\
+  else if (node->next == NULL)						\
+    return node;							\
+									\
+  LTYPE *left_end = LTYPE##_merge_sort_compute_turtle_ (node);		\
+  LTYPE *left_begin = node;						\
+  LTYPE *right_begin = left_end->next;					\
+  /* break the list. */							\
+  left_end->next = NULL;						\
+  right_begin->prev = NULL;						\
+									\
+  left_begin = LTYPE##_merge_sort_ (left_begin, fn_cmp);		\
+  right_begin = LTYPE##_merge_sort_ (right_begin, fn_cmp);		\
+  return LTYPE##_merge_sort_merge_ (left_begin, right_begin, fn_cmp);	\
+}
+
+/* Merge sort wrapper that the end-user should be using as it updates the
+   first and last metadata of the list in wrapper as well.
+   If the user does not want to pay the cost of the update of the data,
+   it can directly use _##LTYPE##_merge_sort_merge.  */
+#define _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT)	\
+EXPORT void								\
+LTYPE##_merge_sort (LWRAPPERTYPE *wrapper,				\
+		    int (*fn_cmp) (const LTYPE *, const LTYPE *))	\
+{									\
+  wrapper->first = LTYPE##_merge_sort_ (wrapper->first, fn_cmp);	\
+									\
+  if (wrapper->first == NULL || wrapper->first->next == NULL)		\
+    wrapper->last = wrapper->first;					\
+  else									\
+    for (LTYPE *node = wrapper->first;					\
+	 node != NULL;							\
+	 node = node->next)						\
+      wrapper->last = node;						\
+}
+
+#define LINKED_LIST_MERGE_SORT_DECL(LWRAPPERTYPE, LTYPE, EXPORT)	\
+  _MERGE_SORT_IMPL_COMPUTE_TURTLE(LTYPE)				\
+  _MERGE_SORT_IMPL_OUT_APPEND(LTYPE)					\
+  _MERGE_SORT_IMPL_MERGE(LTYPE)						\
+  _MERGE_SORT_DEFN_SORT(LTYPE, EXPORT)					\
+  _MERGE_SORT_DEFN_WRAPPER_SORT(LWRAPPERTYPE, LTYPE, EXPORT)
+
+#endif /* _DOUBLY_LINKED_LIST_H */
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index 387975daf58..d507f27a9ef 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -237,6 +237,7 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./atexit.$(objext)		\
 INSTALLED_HEADERS =                                                     \
 	$(INCDIR)/ansidecl.h                                            \
 	$(INCDIR)/demangle.h                                            \
+	$(INCDIR)/doubly-linked-list.h                                  \
 	$(INCDIR)/dyn-string.h                                          \
 	$(INCDIR)/fibheap.h                                             \
 	$(INCDIR)/floatformat.h                                         \
diff --git a/libiberty/testsuite/Makefile.in b/libiberty/testsuite/Makefile.in
index 2b0883c7630..ef549ca910a 100644
--- a/libiberty/testsuite/Makefile.in
+++ b/libiberty/testsuite/Makefile.in
@@ -45,7 +45,8 @@ all:
 check: @CHECK@
 
 really-check: check-cplus-dem check-d-demangle check-rust-demangle \
-		check-pexecute check-expandargv check-strtol
+		check-pexecute check-expandargv check-strtol \
+		check-doubly-linked-list
 
 # Run some tests of the demangler.
 check-cplus-dem: test-demangle $(srcdir)/demangle-expected
@@ -69,6 +70,10 @@ check-expandargv: test-expandargv
 check-strtol: test-strtol
 	./test-strtol
 
+# Check the linked list functionality
+check-doubly-linked-list: test-doubly-linked-list
+	./test-doubly-linked-list
+
 # Run the demangler fuzzer
 fuzz-demangler: demangler-fuzzer
 	./demangler-fuzzer
@@ -90,6 +95,10 @@ test-strtol: $(srcdir)/test-strtol.c ../libiberty.a
 	$(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-strtol \
 		$(srcdir)/test-strtol.c ../libiberty.a
 
+test-doubly-linked-list: $(srcdir)/test-doubly-linked-list.c
+	$(TEST_COMPILE) -DHAVE_CONFIG_H -I.. -o test-doubly-linked-list \
+		$(srcdir)/test-doubly-linked-list.c
+
 demangler-fuzzer: $(srcdir)/demangler-fuzzer.c ../libiberty.a
 	$(TEST_COMPILE) -o demangler-fuzzer \
 		$(srcdir)/demangler-fuzzer.c ../libiberty.a
@@ -104,6 +113,7 @@ mostlyclean:
 	rm -f test-pexecute
 	rm -f test-expandargv
 	rm -f test-strtol
+	rm -f test-doubly-linked-list
 	rm -f demangler-fuzzer
 	rm -f core
 clean: mostlyclean
diff --git a/libiberty/testsuite/test-doubly-linked-list.c b/libiberty/testsuite/test-doubly-linked-list.c
new file mode 100644
index 00000000000..1e1fc637653
--- /dev/null
+++ b/libiberty/testsuite/test-doubly-linked-list.c
@@ -0,0 +1,269 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "doubly-linked-list.h"
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+/* Implementation */
+
+typedef int T;
+
+typedef struct ListNodeType
+{
+  T value;
+  struct ListNodeType *next;
+  struct ListNodeType *prev;
+} ListNodeType;
+
+ListNodeType * l_new_node (T value)
+{
+  ListNodeType *n = malloc (sizeof (ListNodeType));
+  n->next = NULL;
+  n->prev = NULL;
+  n->value = value;
+  return n;
+}
+
+typedef struct LinkedListWrapperType
+{
+  ListNodeType *first;
+  ListNodeType *last;
+  size_t size;
+} LinkedListWrapperType;
+
+int compare_nodes (const ListNodeType *n1, const ListNodeType *n2)
+{
+  if (n1->value == n2->value)
+    return 0;
+  else if (n1->value < n2->value)
+    return -1;
+  else
+    return 1;
+}
+
+LINKED_LIST_MUTATIVE_OPS_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
+LINKED_LIST_MERGE_SORT_PROTOTYPE (LinkedListWrapperType, ListNodeType, static);
+
+LINKED_LIST_MUTATIVE_OPS_DECL (LinkedListWrapperType, ListNodeType, static)
+LINKED_LIST_MERGE_SORT_DECL (LinkedListWrapperType, ListNodeType, static)
+
+ListNodeType * find_last_node (ListNodeType *head)
+{
+  if (head == NULL)
+    return NULL;
+
+  ListNodeType *n = head;
+  while (n->next != NULL)
+    n = n->next;
+
+  return n;
+}
+
+void l_print (ListNodeType *node)
+{
+  for (ListNodeType *l = node; l != NULL; l = l->next)
+    printf ("%d ", l->value);
+  printf ("\n");
+}
+
+void l_reverse_print (ListNodeType *last_node)
+{
+  for (ListNodeType *l = last_node; l != NULL; l = l->prev)
+    printf ("%d ", l->value);
+  printf ("\n");
+}
+
+struct test_data_t
+{
+  T const *content;
+  size_t size;
+};
+
+bool run_test (const struct test_data_t *expect,
+	       LinkedListWrapperType *current,
+	       bool reversed)
+{
+  ListNodeType *node = (reversed) ? current->last : current->first;
+  bool passed = true;
+  for (int i=0; i<expect->size && node != NULL; ++i)
+    {
+      if (reversed)
+	{
+	  if (expect->content[expect->size - 1 - i] != node->value)
+	    {
+	      printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
+		      expect->content[expect->size - 1 - i], node->value);
+	      passed = false;
+	    }
+	  if (node->prev == NULL && current->first != node)
+	    {
+	      printf ("FAIL: first is not matching the first node.\n");
+	      passed = false;
+	    }
+	}
+      else
+	{
+	  if (expect->content[i] != node->value)
+	    {
+	      printf ("FAIL: mismatching expected (%d) VS current (%d).\n",
+		      expect->content[i], node->value);
+	      passed = false;
+	    }
+	  if (node->next == NULL && current->last != node)
+	    {
+	      printf ("FAIL: last_ is not matching the last node.\n");
+	      passed = false;
+	    }
+	}
+
+      if (!passed)
+	return false;
+
+      if (reversed)
+	node = node->prev;
+      else
+	node = node->next;
+    }
+
+  if (node != NULL)
+    {
+      printf ("FAIL: the list is longer than expected.\n");
+      passed = false;
+    }
+  if (expect->size != current->size)
+    {
+      printf ("FAIL: size (%ld) is not matching the real size of the list (%ld).\n",
+	      current->size, expect->size);
+      passed = false;
+    }
+
+  return passed;
+}
+
+bool check(const char *op,
+	  const struct test_data_t *expect,
+	  LinkedListWrapperType *wrapper)
+{
+  bool success = true;
+  bool res;
+
+  l_print (wrapper->first);
+  res = run_test (expect, wrapper, false);
+  printf ("%s: test-linked-list::%s: check forward conformity\n",
+	  res ? "PASS": "FAIL", op);
+  success &= res;
+
+  l_reverse_print (wrapper->last);
+  res = run_test (expect, wrapper, true);
+  printf ("%s: test-linked-list::%s: check backward conformity\n",
+	  res ? "PASS": "FAIL", op);
+  success &= res;
+
+  printf("\n");
+
+  return success;
+}
+
+const int EXPECT_0 [] = { 10, 4, 3, 1, 9, 2 };
+const int EXPECT_1 [] = { 1, 2, 3, 4, 9, 10 };
+const int EXPECT_2 [] = { 11, 1, 2, 3, 4, 9, 10 };
+const int EXPECT_3 [] = { 11, 1, 2, 3, 4, 9, 8, 10 };
+const int EXPECT_4 [] = { 11, 2, 3, 4, 9, 8, 10 };
+const int EXPECT_5 [] = { 10, 2, 3, 4, 9, 8, 11 };
+const int EXPECT_6 [] = { 10, 3, 2, 4, 9, 8, 11 };
+const int EXPECT_7 [] = { 10, 9, 2, 4, 3, 8, 11 };
+const int EXPECT_8 [] = { 2, 3, 4, 8, 9, 10, 11 };
+const int EXPECT_9 [] = { 3, 4, 8, 9, 10, 11 };
+const int EXPECT_10 [] = { 3, 4, 8, 9, 10 };
+const struct test_data_t test_data[] = {
+  { .content = EXPECT_0, .size = sizeof(EXPECT_0) / sizeof(EXPECT_0[0]) },
+  { .content = EXPECT_1, .size = sizeof(EXPECT_1) / sizeof(EXPECT_1[0]) },
+  { .content = EXPECT_2, .size = sizeof(EXPECT_2) / sizeof(EXPECT_2[0]) },
+  { .content = EXPECT_3, .size = sizeof(EXPECT_3) / sizeof(EXPECT_3[0]) },
+  { .content = EXPECT_4, .size = sizeof(EXPECT_4) / sizeof(EXPECT_4[0]) },
+  { .content = EXPECT_5, .size = sizeof(EXPECT_5) / sizeof(EXPECT_5[0]) },
+  { .content = EXPECT_6, .size = sizeof(EXPECT_6) / sizeof(EXPECT_6[0]) },
+  { .content = EXPECT_7, .size = sizeof(EXPECT_7) / sizeof(EXPECT_7[0]) },
+  { .content = EXPECT_8, .size = sizeof(EXPECT_8) / sizeof(EXPECT_8[0]) },
+  { .content = EXPECT_9, .size = sizeof(EXPECT_9) / sizeof(EXPECT_9[0]) },
+  { .content = EXPECT_10, .size = sizeof(EXPECT_10) / sizeof(EXPECT_10[0]) },
+};
+
+int main (void)
+{
+  int failures = 0;
+
+  LinkedListWrapperType wrapper = {
+    .first = NULL,
+    .last = NULL,
+    .size = 0,
+  };
+
+  /* Append nodes.  */
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (10));
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (4));
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (3));
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (1));
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (9));
+  LINKED_LIST_APPEND(ListNodeType) (&wrapper, l_new_node (2));
+
+  failures += ! check ("append", &test_data[0], &wrapper);
+
+  /* Sort nodes (without updating wrapper).  */
+  wrapper.first =
+    LINKED_LIST_MERGE_SORT_(ListNodeType) (wrapper.first, compare_nodes);
+  wrapper.last = find_last_node (wrapper.first);
+
+  failures += ! check ("sort", &test_data[1], &wrapper);
+
+  /* Save a reference to this node for later.  */
+  ListNodeType *n_to_remove = wrapper.first;
+
+  /* Prepend node.  */
+  LINKED_LIST_PREPEND(ListNodeType) (&wrapper, l_new_node (11));
+  failures += ! check ("prepend", &test_data[2], &wrapper);
+
+  /* Insert node.  */
+  LINKED_LIST_INSERT_BEFORE(ListNodeType) (&wrapper, l_new_node (8), wrapper.last);
+  failures += ! check ("insert_before", &test_data[3], &wrapper);
+
+  /* Remove a node.  */
+  LINKED_LIST_REMOVE(ListNodeType) (&wrapper, n_to_remove);
+  failures += ! check ("remove", &test_data[4], &wrapper);
+
+  /* Swap first and last.  */
+  LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first, wrapper.last);
+  failures += ! check ("swap first and last", &test_data[5], &wrapper);
+
+  /* Swap adjacent nodes.  */
+  LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
+				  wrapper.first->next->next);
+  failures += ! check ("swap adjacent nodes", &test_data[6], &wrapper);
+
+  /* Swap non-adjacent nodes, but neither first nor last.  */
+  LINKED_LIST_SWAP(ListNodeType) (&wrapper, wrapper.first->next,
+				  wrapper.first->next->next->next->next);
+  failures += ! check ("swap non-adjacent nodes", &test_data[7], &wrapper);
+
+  /* Sort nodes.  */
+  LINKED_LIST_MERGE_SORT(ListNodeType) (&wrapper, compare_nodes);
+  failures += ! check ("sort", &test_data[8], &wrapper);
+
+  /* Pop front.  */
+  LINKED_LIST_POP_FRONT(ListNodeType) (&wrapper);
+  failures += ! check ("pop_front", &test_data[9], &wrapper);
+
+  /* Pop back.  */
+  LINKED_LIST_POP_BACK(ListNodeType) (&wrapper);
+  failures += ! check ("pop_back", &test_data[10], &wrapper);
+
+  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}
-- 
2.50.1


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

* [PATCH] libiberty: sync with gcc
@ 2025-05-14 11:49 Andreas Schwab
  0 siblings, 0 replies; 14+ messages in thread
From: Andreas Schwab @ 2025-05-14 11:49 UTC (permalink / raw)
  To: gdb-patches; +Cc: binutils

Import the following commits from GCC as of r16-614-g9d039eff453f77:
	31dd621796f libiberty: add ldirname function
	f3d07779fdb libiberty: Append <libgen.h> to AC_CHECK_DECLS [PR119218].
	90183362524 libiberty, gcc: Add memrchr to libiberty and use it [PR119283].
	43717ee9064 libiberty: Fix off-by-one when collecting range expression

In addition, rename uses of ldirname in ld and gdb to fix conflicts.

ld/:
	* ldlang.c (stat_ldirname): Rename from ldirname, all uses
	changed.
---
 gdb/darwin-nat.c         |  2 +-
 gdb/dwarf2/dwz.c         |  2 +-
 gdb/dwarf2/read.c        |  6 +--
 gdb/python/python.c      |  2 +-
 gdb/symtab.c             |  2 +-
 gdb/utils.c              |  2 +-
 gdb/utils.h              |  2 +-
 gdb/xml-syscall.c        |  2 +-
 gdb/xml-tdesc.c          |  2 +-
 include/libiberty.h      | 22 ++++++++++
 ld/ldlang.c              |  4 +-
 libiberty/ChangeLog      | 41 ++++++++++++++++++
 libiberty/Makefile.in    | 31 ++++++++++---
 libiberty/config.in      |  6 +++
 libiberty/configure      | 17 +++++---
 libiberty/configure.ac   | 14 ++++--
 libiberty/configure.com  |  2 +-
 libiberty/functions.texi | 14 ++++++
 libiberty/ldirname.c     | 94 ++++++++++++++++++++++++++++++++++++++++
 libiberty/makefile.vms   |  2 +-
 libiberty/memrchr.c      | 33 ++++++++++++++
 libiberty/regex.c        |  2 +-
 22 files changed, 274 insertions(+), 30 deletions(-)
 create mode 100644 libiberty/ldirname.c
 create mode 100644 libiberty/memrchr.c

diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
index 6bc0e4f8e7a..ffbf949fe79 100644
--- a/gdb/darwin-nat.c
+++ b/gdb/darwin-nat.c
@@ -1853,7 +1853,7 @@ copy_shell_to_cache (const char *shell, const std::string &new_name)
     error (_("Could not open shell (%s) for reading: %s"),
 	   shell, safe_strerror (errno));
 
-  std::string new_dir = ldirname (new_name.c_str ());
+  std::string new_dir = gdb_ldirname (new_name.c_str ());
   if (!mkdir_recursive (new_dir.c_str ()))
     error (_("Could not make cache directory \"%s\": %s"),
 	   new_dir.c_str (), safe_strerror (errno));
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
index 59fe8e4886b..1aa0d035d22 100644
--- a/gdb/dwarf2/dwz.c
+++ b/gdb/dwarf2/dwz.c
@@ -343,7 +343,7 @@ dwz_file::read_dwz_file (dwarf2_per_objfile *per_objfile)
     {
       gdb::unique_xmalloc_ptr<char> abs = gdb_realpath (per_bfd->filename ());
 
-      filename = ldirname (abs.get ()) + SLASH_STRING + filename;
+      filename = gdb_ldirname (abs.get ()) + SLASH_STRING + filename;
     }
 
   /* First try the file name given in the section.  If that doesn't
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 891e10f6e81..75e13159c64 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -5859,7 +5859,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
       && res.get_name () != nullptr
       && IS_ABSOLUTE_PATH (res.get_name ()))
     {
-      res.set_comp_dir (ldirname (res.get_name ()));
+      res.set_comp_dir (gdb_ldirname (res.get_name ()));
       res.set_name (make_unique_xstrdup (lbasename (res.get_name ())));
     }
 
@@ -7434,7 +7434,7 @@ try_open_dwop_file (dwarf2_per_bfd *per_bfd, const char *file_name, int is_dwp,
     search_path = per_bfd->captured_debug_dir.c_str ();
 
   /* Add the path for the executable binary to the list of search paths.  */
-  std::string objfile_dir = ldirname (per_bfd->filename ());
+  std::string objfile_dir = gdb_ldirname (per_bfd->filename ());
   search_path_holder.reset (concat (objfile_dir.c_str (),
 				    dirname_separator_string,
 				    search_path, nullptr));
@@ -7807,7 +7807,7 @@ open_and_init_dwp_file (dwarf2_per_objfile *per_objfile)
       struct objfile *backlink = objfile->separate_debug_objfile_backlink;
       const char *backlink_basename = lbasename (backlink->original_name);
 
-      dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
+      dwp_name = gdb_ldirname (objfile->original_name) + SLASH_STRING + backlink_basename;
     }
   else
     dwp_name = objfile->original_name;
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 24cb511c3d5..7c3d0d104b5 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2446,7 +2446,7 @@ py_initialize ()
      /foo/lib/pythonX.Y/...
      This must be done before calling Py_Initialize.  */
   gdb::unique_xmalloc_ptr<char> progname
-    (concat (ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin",
+    (concat (gdb_ldirname (python_libdir.c_str ()).c_str (), SLASH_STRING, "bin",
 	      SLASH_STRING, "python", (char *) NULL));
 
   {
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 5147aee55d5..5e347386be2 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4499,7 +4499,7 @@ info_sources_filter::matches (const char *fullname) const
       switch (m_match_type)
 	{
 	case match_on::DIRNAME:
-	  dirname = ldirname (fullname);
+	  dirname = gdb_ldirname (fullname);
 	  to_match = dirname.c_str ();
 	  break;
 	case match_on::BASENAME:
diff --git a/gdb/utils.c b/gdb/utils.c
index 7b0c8127583..8d9f0033225 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3333,7 +3333,7 @@ gdb_argv_as_array_view_test ()
    argument.  */
 
 std::string
-ldirname (const char *filename)
+gdb_ldirname (const char *filename)
 {
   std::string dirname;
   const char *base = lbasename (filename);
diff --git a/gdb/utils.h b/gdb/utils.h
index a8834cf4bc2..b37e8f7d7a1 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -133,7 +133,7 @@ struct set_batch_flag_and_restore_page_info
 extern int gdb_filename_fnmatch (const char *pattern, const char *string,
 				 int flags);
 
-std::string ldirname (const char *filename);
+std::string gdb_ldirname (const char *filename);
 
 extern int count_path_elements (const char *path);
 
diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c
index fe0ea2b75a0..b58fe5d0d2f 100644
--- a/gdb/xml-syscall.c
+++ b/gdb/xml-syscall.c
@@ -319,7 +319,7 @@ xml_init_syscalls_info (const char *filename)
   if (!full_file)
     return NULL;
 
-  const std::string dirname = ldirname (filename);
+  const std::string dirname = gdb_ldirname (filename);
   auto fetch_another = [&dirname] (const char *name)
     {
       return xml_fetch_content_from_file (name, dirname.c_str ());
diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c
index 6c095afa699..2f213dc973d 100644
--- a/gdb/xml-tdesc.c
+++ b/gdb/xml-tdesc.c
@@ -670,7 +670,7 @@ file_read_description_xml (const char *filename)
       return NULL;
     }
 
-  const std::string dirname = ldirname (filename);
+  const std::string dirname = gdb_ldirname (filename);
   auto fetch_another = [&dirname] (const char *name)
     {
       return xml_fetch_content_from_file (name, dirname.c_str ());
diff --git a/include/libiberty.h b/include/libiberty.h
index e39f1870cb7..b88eb643aa3 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -133,6 +133,18 @@ extern const char *dos_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIB
 
 extern const char *unix_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
 
+/* A dirname () that is always compiled in.  */
+
+extern char *ldirname (const char *) ATTRIBUTE_NONNULL(1);
+
+/* Same, but assumes DOS semantics regardless of host.  */
+
+extern char *dos_ldirname (const char *) ATTRIBUTE_NONNULL(1);
+
+/* Same, but assumes Unix semantics regardless of host.  */
+
+extern char *unix_ldirname (const char *) ATTRIBUTE_NONNULL(1);
+
 /* A well-defined realpath () that is always compiled in.  */
 
 extern char *lrealpath (const char *);
@@ -199,6 +211,16 @@ extern int fdmatch (int fd1, int fd2);
 extern int ffs(int);
 #endif
 
+#if defined (HAVE_DECL_MKSTEMPS) && !HAVE_DECL_MKSTEMPS
+extern int mkstemps(char *, int);
+#endif
+
+/* Make memrchr available on systems that do not have it.  */
+#if !defined (__GNU_LIBRARY__ ) && !defined (__linux__) && \
+    !defined (HAVE_MEMRCHR)
+extern void *memrchr(const void *, int, size_t);
+#endif
+
 /* Get the working directory.  The result is cached, so don't call
    chdir() between calls to getpwd().  */
 
diff --git a/ld/ldlang.c b/ld/ldlang.c
index e0368171fa9..32e6e7abdf1 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -322,7 +322,7 @@ spec_match (const struct wildcard_spec *spec, const char *name)
 }
 
 static char *
-ldirname (const char *name)
+stat_ldirname (const char *name)
 {
   const char *base = lbasename (name);
 
@@ -1266,7 +1266,7 @@ new_afile (const char *name,
       /* If name is a relative path, search the directory of the current linker
 	 script first. */
       if (from_filename && !IS_ABSOLUTE_PATH (name))
-	p->extra_search_path = ldirname (from_filename);
+	p->extra_search_path = stat_ldirname (from_filename);
       p->flags.real = true;
       p->flags.search_dirs = true;
       break;
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 83e9120c444..2ae5626ed2e 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,44 @@
+2025-05-13  Andreas Schwab  <schwab@suse.de>
+
+	* regex.c (regex_compile): Don't write beyond array bounds when
+	collecting range expression.
+
+2025-03-29  Iain Sandoe  <iain@sandoe.co.uk>
+
+	PR cobol/119283
+	* Makefile.in: Add memrchr build rules.
+	* config.in: Regenerate.
+	* configure: Regenerate.
+	* configure.ac: Check for memrchr.
+	* functions.texi: Document memrchr.
+	* memrchr.c: New file.
+
+2025-03-25  Iain Sandoe  <iain@sandoe.co.uk>
+
+	PR other/119218
+	* config.in: Regenerate.
+	* configure: Regenerate.
+	* configure.ac: Append <libgen.h> to AC_INCLUDES_DEFAULT
+	when checking for the 'basename' decl.
+
+2025-03-18  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* ldirname.c: New file.
+	* Makefile.in (CFILES): Add ldirname.c.
+	(REQUIRED_OFILES): Add ldirname.$(objext).
+	(./ldirname.$(objext)): New rule.
+	* makefile.vms (OBJS): Add ldirname.obj.
+	* configure.com (FILES): Add ldirname.
+
+2024-12-11  Matthieu Longo  <matthieu.longo@arm.com>
+
+	* configure: Regenerate.
+	* configure.ac: Fix autoupdate warnings.
+
+2024-12-11  Sangamesh Mallayya  <swamy.sangamesh@gmail.com>
+
+	* getopt.c: Remove _NO_PROTO block
+
 2024-11-19  Evgeny Karpov  <evgeny.karpov@microsoft.com>
 
 	* simple-object-coff.c: Add aarch64.
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index b11df756b4b..387975daf58 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -136,10 +136,11 @@ CFILES = alloca.c argv.c asprintf.c atexit.c				\
 	hashtab.c hex.c							\
 	index.c insque.c						\
 	lbasename.c							\
+	ldirname.c							\
 	lrealpath.c							\
 	make-relative-prefix.c						\
-	make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmem.c	\
-	 memmove.c mempcpy.c memset.c mkstemps.c			\
+	make-temp-file.c md5.c memchr.c memrchr.c memcmp.c memcpy.c     \
+	memmem.c memmove.c mempcpy.c memset.c mkstemps.c		\
 	objalloc.c obstack.c						\
 	partition.c pexecute.c						\
 	 pex-common.c pex-djgpp.c pex-msdos.c pex-one.c			\
@@ -179,7 +180,7 @@ REQUIRED_OFILES =							\
 	./fnmatch.$(objext) ./fopen_unlocked.$(objext)			\
 	./getopt.$(objext) ./getopt1.$(objext) ./getpwd.$(objext)	\
 	./getruntime.$(objext) ./hashtab.$(objext) ./hex.$(objext)	\
-	./lbasename.$(objext) ./lrealpath.$(objext)			\
+	./lbasename.$(objext) ./ldirname.$(objext) ./lrealpath.$(objext)\
 	./make-relative-prefix.$(objext) ./make-temp-file.$(objext)	\
 	./objalloc.$(objext)						\
 	./obstack.$(objext)						\
@@ -212,8 +213,8 @@ CONFIGURED_OFILES = ./asprintf.$(objext) ./atexit.$(objext)		\
 	./getcwd.$(objext) ./getpagesize.$(objext)			\
 	 ./gettimeofday.$(objext)					\
 	./index.$(objext) ./insque.$(objext)				\
-	./memchr.$(objext) ./memcmp.$(objext) ./memcpy.$(objext) 	\
-	./memmem.$(objext) ./memmove.$(objext)				\
+	./memchr.$(objext) ./memrchr.$(objext) ./memcmp.$(objext) 	\
+	./memcpy.$(objext) ./memmem.$(objext) ./memmove.$(objext)	\
 	 ./mempcpy.$(objext) ./memset.$(objext) ./mkstemps.$(objext)	\
 	./pex-djgpp.$(objext) ./pex-msdos.$(objext)			\
 	 ./pex-unix.$(objext) ./pex-win32.$(objext)			\
@@ -966,6 +967,17 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/lbasename.c $(OUTPUT_OPTION)
 
+./ldirname.$(objext): $(srcdir)/ldirname.c config.h $(INCDIR)/ansidecl.h \
+	$(INCDIR)/filenames.h $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h \
+	$(INCDIR)/safe-ctype.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/ldirname.c -o pic/$@; \
+	else true; fi
+	if [ x"$(NOASANFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/ldirname.c -o noasan/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/ldirname.c $(OUTPUT_OPTION)
+
 ./lrealpath.$(objext): $(srcdir)/lrealpath.c config.h $(INCDIR)/ansidecl.h \
 	$(INCDIR)/libiberty.h
 	if [ x"$(PICFLAG)" != x ]; then \
@@ -1014,6 +1026,15 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/memchr.c $(OUTPUT_OPTION)
 
+./memrchr.$(objext): $(srcdir)/memrchr.c $(INCDIR)/ansidecl.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/memrchr.c -o pic/$@; \
+	else true; fi
+	if [ x"$(NOASANFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/memrchr.c -o noasan/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/memrchr.c $(OUTPUT_OPTION)
+
 ./memcmp.$(objext): $(srcdir)/memcmp.c $(INCDIR)/ansidecl.h
 	if [ x"$(PICFLAG)" != x ]; then \
 	  $(COMPILE.c) $(PICFLAG) $(srcdir)/memcmp.c -o pic/$@; \
diff --git a/libiberty/config.in b/libiberty/config.in
index 1b1f2b09a8a..3b8716511f0 100644
--- a/libiberty/config.in
+++ b/libiberty/config.in
@@ -153,6 +153,9 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
 /* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
@@ -183,6 +186,9 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `memrchr' function. */
+#undef HAVE_MEMRCHR
+
 /* Define to 1 if you have the `memset' function. */
 #undef HAVE_MEMSET
 
diff --git a/libiberty/configure b/libiberty/configure
index f83b42fb0d5..f0309ff78ad 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5745,7 +5745,7 @@ host_makefile_frag=${frag}
 # It's OK to check for header files.  Although the compiler may not be
 # able to link anything, it had better be able to at least compile
 # something.
-for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h
+for ac_header in sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h libgen.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
@@ -6210,6 +6210,7 @@ funcs="$funcs gettimeofday"
 funcs="$funcs index"
 funcs="$funcs insque"
 funcs="$funcs memchr"
+funcs="$funcs memrchr"
 funcs="$funcs memcmp"
 funcs="$funcs memcpy"
 funcs="$funcs memmem"
@@ -6276,7 +6277,7 @@ if test "x" = "y"; then
     ffs __fsetlocking \
     getcwd getpagesize getrlimit getrusage getsysinfo gettimeofday \
     index insque \
-    memchr memcmp memcpy memmem memmove memset mkstemps \
+    memchr memrchr memcmp memcpy memmem memmove memset mkstemps \
     on_exit \
     pipe2 posix_spawn posix_spawnp psignal \
     pstat_getdynamic pstat_getstatic putenv \
@@ -6691,7 +6692,7 @@ esac
 
     for f in atexit basename bcmp bcopy bsearch bzero calloc clock ffs \
              getcwd getpagesize getrusage gettimeofday \
-             index insque memchr memcmp memcpy memmove memset psignal \
+             index insque memchr memrchr memcmp memcpy memmove memset psignal \
              putenv random rename rindex sbrk setenv stpcpy strcasecmp \
              strchr strdup strerror strncasecmp strrchr strstr strtod \
              strtol strtoul sysconf times tmpnam vfprintf vprintf \
@@ -7389,7 +7390,12 @@ fi
 done
 
   as_ac_Symbol=`$as_echo "ac_cv_have_decl_basename(char *)" | $as_tr_sh`
-ac_fn_c_check_decl "$LINENO" "basename(char *)" "$as_ac_Symbol" "$ac_includes_default"
+ac_fn_c_check_decl "$LINENO" "basename(char *)" "$as_ac_Symbol" "
+$ac_includes_default
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif
+"
 if eval test \"x\$"$as_ac_Symbol"\" = x"yes"; then :
   ac_have_decl=1
 else
@@ -7399,7 +7405,8 @@ fi
 cat >>confdefs.h <<_ACEOF
 #define HAVE_DECL_BASENAME $ac_have_decl
 _ACEOF
-ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "$ac_includes_default"
+
+  ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "$ac_includes_default"
 if test "x$ac_cv_have_decl_ffs" = xyes; then :
   ac_have_decl=1
 else
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index c27e08e1428..3de5eca0df2 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -291,7 +291,7 @@ AC_SUBST_FILE(host_makefile_frag)
 # It's OK to check for header files.  Although the compiler may not be
 # able to link anything, it had better be able to at least compile
 # something.
-AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h)
+AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h stdio_ext.h process.h sys/prctl.h spawn.h libgen.h)
 AC_HEADER_SYS_WAIT
 AC_HEADER_TIME
 
@@ -370,6 +370,7 @@ funcs="$funcs gettimeofday"
 funcs="$funcs index"
 funcs="$funcs insque"
 funcs="$funcs memchr"
+funcs="$funcs memrchr"
 funcs="$funcs memcmp"
 funcs="$funcs memcpy"
 funcs="$funcs memmem"
@@ -436,7 +437,7 @@ if test "x" = "y"; then
     ffs __fsetlocking \
     getcwd getpagesize getrlimit getrusage getsysinfo gettimeofday \
     index insque \
-    memchr memcmp memcpy memmem memmove memset mkstemps \
+    memchr memrchr memcmp memcpy memmem memmove memset mkstemps \
     on_exit \
     pipe2 posix_spawn posix_spawnp psignal \
     pstat_getdynamic pstat_getstatic putenv \
@@ -555,7 +556,7 @@ if test -n "${with_target_subdir}"; then
 
     for f in atexit basename bcmp bcopy bsearch bzero calloc clock ffs \
              getcwd getpagesize getrusage gettimeofday \
-             index insque memchr memcmp memcpy memmove memset psignal \
+             index insque memchr memrchr memcmp memcpy memmove memset psignal \
              putenv random rename rindex sbrk setenv stpcpy strcasecmp \
              strchr strdup strerror strncasecmp strrchr strstr strtod \
              strtol strtoul sysconf times tmpnam vfprintf vprintf \
@@ -723,7 +724,12 @@ if test -z "${setobjs}"; then
     [AC_MSG_RESULT([no])])
 
   AC_CHECK_FUNCS($checkfuncs)
-  AC_CHECK_DECLS([basename(char *), ffs, asprintf, vasprintf, snprintf, vsnprintf])
+  AC_CHECK_DECLS([basename(char *)], [], [], [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_LIBGEN_H
+# include <libgen.h>
+#endif])
+  AC_CHECK_DECLS([ffs, asprintf, vasprintf, snprintf, vsnprintf])
   AC_CHECK_DECLS([calloc, getenv, getopt, malloc, realloc])
   case "${host}" in
       *-*-darwin*) ;; # Darwin's sbrk implementation is deprecated.
diff --git a/libiberty/configure.com b/libiberty/configure.com
index 030182914f7..55aee2f78f9 100644
--- a/libiberty/configure.com
+++ b/libiberty/configure.com
@@ -17,7 +17,7 @@ $DECK
 $ FILES="getopt,obstack,xexit,xmalloc,hex,getopt1,cplus-dem,cp-demangle,"+-
     "cp-demint,asprintf,vasprintf,mkstemps,concat,getruntime,getpagesize,"+-
     "getpwd,xstrerror,xmemdup,xstrdup,xatexit,choose-temp,fnmatch,objalloc,"+-
-    "safe-ctype,hashtab,lbasename,argv,lrealpath,make-temp-file,"+-
+    "safe-ctype,hashtab,lbasename,ldirname,argv,lrealpath,make-temp-file,"+-
     "stpcpy,unlink-if-ordinary"
 $ OPT="/noopt/debug/warnings=disable=(missingreturn)"
 $ CFLAGS=OPT + "/include=([],[-.include])/name=(as_is,shortened)" +-
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index b56b02e0686..7c7da1ba296 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -749,6 +749,20 @@ returned.
 
 @end deftypefn
 
+@c memrchr.c:3
+@deftypefn Supplemental void* memrchr (const void *@var{s}, int @var{c}, @
+  size_t @var{n})
+
+This function searches memory for the character @var{c} in reverse order,
+starting at @code{*@var{s}+@var{n}-1} .  The search only ends with
+the first occurrence of @var{c}, or when the start us reached; in particular,
+a null character does not terminate the search.  If the character @var{c} is
+found within @var{length} characters of @code{*@var{s}}, a pointer
+to the character is returned.  If @var{c} is not found, then @code{NULL} is
+returned.
+
+@end deftypefn
+
 @c memcmp.c:6
 @deftypefn Supplemental int memcmp (const void *@var{x}, const void *@var{y}, @
   size_t @var{count})
diff --git a/libiberty/ldirname.c b/libiberty/ldirname.c
new file mode 100644
index 00000000000..e3cd5c816c1
--- /dev/null
+++ b/libiberty/ldirname.c
@@ -0,0 +1,94 @@
+/* Libiberty dirname.  Like dirname, but is not overridden by the
+   system C library.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/*
+
+@deftypefn Replacement {char*} ldirname (const char *@var{name})
+
+Given a pointer to a string containing a typical pathname
+(@samp{/usr/src/cmd/ls/ls.c} for example), returns a string containing the
+passed string up to, but not including, the final directory separator.
+
+If the given pathname doesn't contain a directory separator then this funtion
+returns the empty string; this includes an empty given pathname.  @code{NULL}
+is returned on memory allocation error.
+
+@end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+#include "safe-ctype.h"
+#include "filenames.h"
+
+/* For malloc.  */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/* For memcpy.  */
+# if HAVE_STRING_H
+#  include <string.h>
+# else
+#  if HAVE_STRINGS_H
+#   include <strings.h>
+#  endif
+# endif
+
+#define LDIRNAME(FPREFIX,DIRSEP)					\
+  char *FPREFIX##_ldirname (const char *name)				\
+  {									\
+    /* Note that lbasename guarantees that the returned */		\
+    /* pointer lies within the passed string.  */			\
+    const char *basename = FPREFIX##_lbasename (name);			\
+    size_t size = basename - name;					\
+    char *res = NULL;							\
+    									\
+    res = (char*) malloc (size + 1);					\
+    if (res != NULL)							\
+      {									\
+	if (size > 0)							\
+	  {								\
+	    if (IS_DIR_SEPARATOR_1 ((DIRSEP),name[size - 1]))		\
+	      size -= 1;						\
+	    memcpy (res, name, size);					\
+	  }								\
+	res[size] = '\0';						\
+      }									\
+    									\
+    return res;								\
+  }
+
+LDIRNAME(dos,1)
+LDIRNAME(unix,0)
+
+char *
+ldirname (const char *name)
+{
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  return dos_ldirname (name);
+#else
+  return unix_ldirname (name);
+#endif
+}
diff --git a/libiberty/makefile.vms b/libiberty/makefile.vms
index 15a7d0a206b..4cfcc986f66 100644
--- a/libiberty/makefile.vms
+++ b/libiberty/makefile.vms
@@ -12,7 +12,7 @@ OBJS=getopt.obj,obstack.obj,xexit.obj,xmalloc.obj,hex.obj,\
     asprintf.obj vasprintf.obj,mkstemps.obj,filename_cmp.obj,\
     concat.obj,getruntime.obj,getpagesize.obj,getpwd.obj,xstrerror.obj,\
     xmemdup.obj,xstrdup.obj,xatexit.obj,choose-temp.obj,fnmatch.obj,\
-    objalloc.obj,safe-ctype.obj,hashtab.obj,lbasename.obj,argv.obj,\
+    objalloc.obj,safe-ctype.obj,hashtab.obj,lbasename.obj,ldirname.obj,argv.obj,\
     lrealpath.obj,make-temp-file.obj,stpcpy.obj,unlink-if-ordinary.obj,\
     dwarfnames.obj
 
diff --git a/libiberty/memrchr.c b/libiberty/memrchr.c
new file mode 100644
index 00000000000..fe7713ecce5
--- /dev/null
+++ b/libiberty/memrchr.c
@@ -0,0 +1,33 @@
+/*
+
+@deftypefn Supplemental void* memrchr (const void *@var{s}, int @var{c}, @
+  size_t @var{n})
+
+This function searches memory for the character @var{c} in reverse order,
+starting at @code{*@var{s}+@var{n}-1} .  The search only ends with
+the first occurrence of @var{c}, or when the start us reached; in particular,
+a null character does not terminate the search.  If the character @var{c} is
+found within @var{length} characters of @code{*@var{s}}, a pointer
+to the character is returned.  If @var{c} is not found, then @code{NULL} is
+returned.
+
+@end deftypefn
+
+*/
+
+#include <ansidecl.h>
+#include <stddef.h>
+
+void *
+memrchr (const void *src_void, int c, size_t length)
+{
+  if (length == 0)
+    return NULL;
+
+  const unsigned char *p = (const unsigned char*)src_void;
+  p += length;
+  while (*--p != (unsigned char)c)
+    if (src_void == p)
+      return NULL;
+  return (void *)p;
+}
diff --git a/libiberty/regex.c b/libiberty/regex.c
index bc36f43d450..8337deaef5a 100644
--- a/libiberty/regex.c
+++ b/libiberty/regex.c
@@ -3468,7 +3468,7 @@ PREFIX(regex_compile) (const char *ARG_PREFIX(pattern),
 			PATFETCH (c);
 			if ((c == '.' && *p == ']') || p == pend)
 			  break;
-			if (c1 < sizeof (str))
+			if (c1 < sizeof (str) - 1)
 			  str[c1++] = c;
 			else
 			  /* This is in any case an invalid class name.  */
-- 
2.49.0


-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

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

* Re: [PATCH] libiberty: sync with gcc
  2024-11-22 15:46   ` Sam James
@ 2024-11-22 23:43     ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2024-11-22 23:43 UTC (permalink / raw)
  To: Sam James; +Cc: Tom Tromey, binutils, gdb-patches

>>>>> "Sam" == Sam James <sam@gentoo.org> writes:

>> Thank you.  Please check this in.
>> Approved-By: Tom Tromey <tom@tromey.com>

Sam> Thanks. I'm going to add this commit on top to catch another change
Sam> which went in later:

That's totally fine, thank you.  I think these kind of merges are
basically pre-approved and the main thing is to discuss if there's
something difficult or contentious in there.  If we could automate this
I probably would.

Tom

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

* Re: [PATCH] libiberty: sync with gcc
  2024-11-22 15:30 ` Tom Tromey
@ 2024-11-22 15:46   ` Sam James
  2024-11-22 23:43     ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Sam James @ 2024-11-22 15:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: binutils, gdb-patches

Tom Tromey <tom@tromey.com> writes:

>>>>>> "Sam" == Sam James <sam@gentoo.org> writes:
>
> Sam> This imports the following commits from GCC as of r15-5375-gbeec291225be9b:
> Sam> 	94bea5dd6c9a libiberity: ANSIfy test-demangle.c
> Sam> 	aa84020b2edb libiberty: Fix comment typos
> Sam> 	c1b2100e736c libiberty: Restore build with CP_DEMANGLE_DEBUG defined
> Sam> 	bb8dd0980b39 libiberty: Fix up > 64K section handling in simple_object_elf_copy_lto_debug_section [PR116614]
> Sam> ---
> Sam> OK? This primarily fixes a C23 issue in test-demangle.c.
>
> Thank you.  Please check this in.
> Approved-By: Tom Tromey <tom@tromey.com>

Thanks. I'm going to add this commit on top to catch another change
which went in later:

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 4a461602ac0..83e9120c444 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,7 @@
+2024-11-19  Evgeny Karpov  <evgeny.karpov@microsoft.com>
+
+       * simple-object-coff.c: Add aarch64.
+
 2024-11-16  Andrew Pinski  <quic_apinski@quicinc.com>

        * testsuite/test-demangle.c (get_line): Change K&R style
diff --git a/libiberty/simple-object-coff.c b/libiberty/simple-object-coff.c
index e748205972f..fd3c310db51 100644
--- a/libiberty/simple-object-coff.c
+++ b/libiberty/simple-object-coff.c
@@ -219,7 +219,9 @@ static const struct coff_magic_struct coff_magic[] =
   /* i386.  */
   { 0x14c, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
   /* x86_64.  */
-  { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
+  { 0x8664, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL },
+  /* AArch64.  */
+  { 0xaa64, 0, F_EXEC | IMAGE_FILE_SYSTEM | IMAGE_FILE_DLL }
 };

 /* See if we have a COFF file.  */
 
>
> Tom

thanks,
sam

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

* Re: [PATCH] libiberty: sync with gcc
  2024-11-18  6:02 Sam James
@ 2024-11-22 15:30 ` Tom Tromey
  2024-11-22 15:46   ` Sam James
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2024-11-22 15:30 UTC (permalink / raw)
  To: Sam James; +Cc: binutils, gdb-patches

>>>>> "Sam" == Sam James <sam@gentoo.org> writes:

Sam> This imports the following commits from GCC as of r15-5375-gbeec291225be9b:
Sam> 	94bea5dd6c9a libiberity: ANSIfy test-demangle.c
Sam> 	aa84020b2edb libiberty: Fix comment typos
Sam> 	c1b2100e736c libiberty: Restore build with CP_DEMANGLE_DEBUG defined
Sam> 	bb8dd0980b39 libiberty: Fix up > 64K section handling in simple_object_elf_copy_lto_debug_section [PR116614]
Sam> ---
Sam> OK? This primarily fixes a C23 issue in test-demangle.c.

Thank you.  Please check this in.
Approved-By: Tom Tromey <tom@tromey.com>

Tom

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

* [PATCH] libiberty: sync with gcc
@ 2024-11-18  6:02 Sam James
  2024-11-22 15:30 ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Sam James @ 2024-11-18  6:02 UTC (permalink / raw)
  To: binutils, gdb-patches; +Cc: Sam James

This imports the following commits from GCC as of r15-5375-gbeec291225be9b:
	94bea5dd6c9a libiberity: ANSIfy test-demangle.c
	aa84020b2edb libiberty: Fix comment typos
	c1b2100e736c libiberty: Restore build with CP_DEMANGLE_DEBUG defined
	bb8dd0980b39 libiberty: Fix up > 64K section handling in simple_object_elf_copy_lto_debug_section [PR116614]
---
OK? This primarily fixes a C23 issue in test-demangle.c.

 libiberty/ChangeLog                 |  37 +++++
 libiberty/cp-demangle.c             |   4 +-
 libiberty/cplus-dem.c               |   2 +-
 libiberty/simple-object-elf.c       | 210 +++++++++++++++++++---------
 libiberty/testsuite/test-demangle.c |  15 +-
 5 files changed, 187 insertions(+), 81 deletions(-)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 949fec62fe4..4a461602ac0 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,40 @@
+2024-11-16  Andrew Pinski  <quic_apinski@quicinc.com>
+
+	* testsuite/test-demangle.c (get_line): Change K&R style
+	definition into ANSI C90 definitions.
+	(fail): Likewise.
+	(main): Likewise.
+
+2024-10-31  Mark Wielaard  <mark@klomp.org>
+
+	* cplus-dem.c: Change preceeded to preceded.
+
+2024-10-10  Simon Martin  <simon@nasilyan.com>
+
+	* cp-demangle.c (d_dump): Fix compilation when CP_DEMANGLE_DEBUG
+	is defined.
+
+2024-09-07  Jakub Jelinek  <jakub@redhat.com>
+
+	PR lto/116614
+	* simple-object-elf.c (SHN_COMMON): Align comment with neighbouring
+	comments.
+	(SHN_HIRESERVE): Use uppercase hex digits instead of lowercase for
+	consistency.
+	(simple_object_elf_find_sections): Formatting fixes.
+	(simple_object_elf_fetch_attributes): Likewise.
+	(simple_object_elf_attributes_merge): Likewise.
+	(simple_object_elf_start_write): Likewise.
+	(simple_object_elf_write_ehdr): Likewise.
+	(simple_object_elf_write_shdr): Likewise.
+	(simple_object_elf_write_to_file): Likewise.
+	(simple_object_elf_copy_lto_debug_section): Likewise.  Don't fail for
+	new_i - 1 >= SHN_LORESERVE, instead arrange in that case to copy
+	over .symtab_shndx sections, though emit those last and compute their
+	section content when processing associated .symtab sections.  Handle
+	simple_object_internal_read failure even in the .symtab_shndx reading
+	case.
+
 2024-08-05  Andrew Burgess  <aburgess@redhat.com>
 
 	* argv.c (only_whitespace): Delete.
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index fc2cf64e6e0..5b1bd5dff22 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -655,9 +655,9 @@ d_dump (struct demangle_component *dc, int indent)
       return;
     case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
       {
-	char suffix[2] = { dc->u.s_extended_builtin.type->suffix, 0 };
+	char suffix[2] = { dc->u.s_extended_builtin.suffix, 0 };
 	printf ("builtin type %s%d%s\n", dc->u.s_extended_builtin.type->name,
-		dc->u.s_extended_builtin.type->arg, suffix);
+		dc->u.s_extended_builtin.arg, suffix);
       }
       return;
     case DEMANGLE_COMPONENT_OPERATOR:
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index ee9e84f5d6b..e67ae930049 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -215,7 +215,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
     goto unknown;
 
   /* Most of the demangling will trivially remove chars.  Operator names
-     may add one char but because they are always preceeded by '__' which is
+     may add one char but because they are always preceded by '__' which is
      replaced by '.', they eventually never expand the size.
      A few special names such as '___elabs' add a few chars (at most 7), but
      they occur only once.  */
diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c
index c09c216656c..5e95297b2fc 100644
--- a/libiberty/simple-object-elf.c
+++ b/libiberty/simple-object-elf.c
@@ -128,9 +128,9 @@ typedef struct {
 
 #define SHN_UNDEF	0		/* Undefined section */
 #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
-#define SHN_COMMON	0xFFF2	/* Associated symbol is in common */
+#define SHN_COMMON	0xFFF2		/* Associated symbol is in common */
 #define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
-#define SHN_HIRESERVE	0xffff		/* End of reserved indices */
+#define SHN_HIRESERVE	0xFFFF		/* End of reserved indices */
 
 
 /* 32-bit ELF program header.  */
@@ -569,8 +569,8 @@ simple_object_elf_find_sections (simple_object_read *sobj,
 				 void *data,
 				 int *err)
 {
-  struct simple_object_elf_read *eor =
-    (struct simple_object_elf_read *) sobj->data;
+  struct simple_object_elf_read *eor
+    = (struct simple_object_elf_read *) sobj->data;
   const struct elf_type_functions *type_functions = eor->type_functions;
   unsigned char ei_class = eor->ei_class;
   size_t shdr_size;
@@ -662,8 +662,8 @@ simple_object_elf_fetch_attributes (simple_object_read *sobj,
 				    const char **errmsg ATTRIBUTE_UNUSED,
 				    int *err ATTRIBUTE_UNUSED)
 {
-  struct simple_object_elf_read *eor =
-    (struct simple_object_elf_read *) sobj->data;
+  struct simple_object_elf_read *eor
+    = (struct simple_object_elf_read *) sobj->data;
   struct simple_object_elf_attributes *ret;
 
   ret = XNEW (struct simple_object_elf_attributes);
@@ -689,10 +689,10 @@ simple_object_elf_release_read (void *data)
 static const char *
 simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
 {
-  struct simple_object_elf_attributes *to =
-    (struct simple_object_elf_attributes *) todata;
-  struct simple_object_elf_attributes *from =
-    (struct simple_object_elf_attributes *) fromdata;
+  struct simple_object_elf_attributes *to
+    = (struct simple_object_elf_attributes *) todata;
+  struct simple_object_elf_attributes *from
+    = (struct simple_object_elf_attributes *) fromdata;
 
   if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
     {
@@ -751,8 +751,8 @@ simple_object_elf_start_write (void *attributes_data,
 			       const char **errmsg ATTRIBUTE_UNUSED,
 			       int *err ATTRIBUTE_UNUSED)
 {
-  struct simple_object_elf_attributes *attrs =
-    (struct simple_object_elf_attributes *) attributes_data;
+  struct simple_object_elf_attributes *attrs
+    = (struct simple_object_elf_attributes *) attributes_data;
   struct simple_object_elf_write *ret;
 
   /* We're just going to record the attributes, but we need to make a
@@ -769,8 +769,8 @@ static int
 simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
 			      const char **errmsg, int *err)
 {
-  struct simple_object_elf_attributes *attrs =
-    (struct simple_object_elf_attributes *) sobj->data;
+  struct simple_object_elf_attributes *attrs
+    = (struct simple_object_elf_attributes *) sobj->data;
   const struct elf_type_functions* fns;
   unsigned char cl;
   size_t ehdr_size;
@@ -852,8 +852,8 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
 			      size_t sh_entsize,
 			      const char **errmsg, int *err)
 {
-  struct simple_object_elf_attributes *attrs =
-    (struct simple_object_elf_attributes *) sobj->data;
+  struct simple_object_elf_attributes *attrs
+    = (struct simple_object_elf_attributes *) sobj->data;
   const struct elf_type_functions* fns;
   unsigned char cl;
   size_t shdr_size;
@@ -894,8 +894,8 @@ static const char *
 simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
 				 int *err)
 {
-  struct simple_object_elf_write *eow =
-    (struct simple_object_elf_write *) sobj->data;
+  struct simple_object_elf_write *eow
+    = (struct simple_object_elf_write *) sobj->data;
   struct simple_object_elf_attributes *attrs = &eow->attrs;
   unsigned char cl;
   size_t ehdr_size;
@@ -1088,11 +1088,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 					   char *(*pfn) (const char *),
 					   int *err)
 {
-  struct simple_object_elf_read *eor =
-    (struct simple_object_elf_read *) sobj->data;
+  struct simple_object_elf_read *eor
+    = (struct simple_object_elf_read *) sobj->data;
   const struct elf_type_functions *type_functions = eor->type_functions;
-  struct simple_object_elf_write *eow =
-    (struct simple_object_elf_write *) dobj->data;
+  struct simple_object_elf_write *eow
+    = (struct simple_object_elf_write *) dobj->data;
   unsigned char ei_class = eor->ei_class;
   size_t shdr_size;
   unsigned int shnum;
@@ -1106,10 +1106,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
   int changed;
   int *pfnret;
   const char **pfnname;
-  unsigned new_i;
+  unsigned new_i, new_count;
   unsigned *sh_map;
   unsigned first_shndx = 0;
   unsigned int *symtab_indices_shndx;
+  int pass_symtab_indices_shndx;
+  unsigned int first_symtab_indices_shndx;
+  unsigned char **symtab_indices_shndx_buf;
 
   shdr_size = (ei_class == ELFCLASS32
 	       ? sizeof (Elf32_External_Shdr)
@@ -1179,8 +1182,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       ret = (*pfn) (name);
       pfnret[i - 1] = ret == NULL ? -1 : 0;
       pfnname[i - 1] = ret == NULL ? name : ret;
-      if (first_shndx == 0
-	  && pfnret[i - 1] == 0)
+      if (first_shndx == 0 && pfnret[i - 1] == 0)
 	first_shndx = i;
 
       /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections.  */
@@ -1191,11 +1193,12 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	  unsigned int sh_link;
 	  sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 				     shdr, sh_link, Elf_Word);
-	  symtab_indices_shndx[sh_link - 1] = i - 1;
-	  /* Always discard the extended index sections, after
-	     copying it will not be needed.  This way we don't need to
-	     update it and deal with the ordering constraints of
-	     processing the existing symtab and changing the index.  */
+	  symtab_indices_shndx[sh_link - 1] = i;
+	  /* Discard the extended index sections, after copying it will not
+	     be needed, unless we need more than SHN_LORESERVE - 1 sections
+	     in the output.  This way we don't need to update it and deal with
+	     the ordering constraints of processing the existing symtab and
+	     changing the index.  */
 	  pfnret[i - 1] = -1;
 	}
     }
@@ -1291,16 +1294,25 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       else
 	sh_map[i] = new_i++;
     }
+  first_symtab_indices_shndx = new_i;
+  symtab_indices_shndx_buf = NULL;
   if (new_i - 1 >= SHN_LORESERVE)
-    {
-      *err = ENOTSUP;
-      return "Too many copied sections";
-    }
-  eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
+    for (i = 1; i < shnum; ++i)
+      if (pfnret[i - 1] == 0 && symtab_indices_shndx[i - 1] != 0)
+	{
+	  pfnret[symtab_indices_shndx[i - 1] - 1] = 0;
+	  sh_map[symtab_indices_shndx[i - 1]] = new_i++;
+	}
+  new_count = new_i;
+  if (new_count != first_symtab_indices_shndx)
+    symtab_indices_shndx_buf
+      = XNEWVEC (unsigned char *, new_count - first_symtab_indices_shndx);
+  eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_count - 1));
 
   /* Then perform the actual copying.  */
   new_i = 0;
-  for (i = 1; i < shnum; ++i)
+  pass_symtab_indices_shndx = 0;
+  for (i = 1; i <= shnum; ++i)
     {
       unsigned char *shdr;
       unsigned int sh_name, sh_type;
@@ -1311,11 +1323,30 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
       off_t flags;
       unsigned char *buf;
 
+      if (i == shnum)
+	{
+	  if (new_count - 1 < SHN_LORESERVE || pass_symtab_indices_shndx)
+	    break;
+	  i = 0;
+	  pass_symtab_indices_shndx = 1;
+	  continue;
+	}
+
       if (pfnret[i - 1])
 	continue;
 
-      new_i++;
       shdr = shdrs + (i - 1) * shdr_size;
+      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
+				 shdr, sh_type, Elf_Word);
+      if (sh_type == SHT_SYMTAB_SHNDX)
+	{
+	  if (!pass_symtab_indices_shndx)
+	    continue;
+	}
+      else if (pass_symtab_indices_shndx)
+	continue;
+
+      new_i++;
       sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 				 shdr, sh_name, Elf_Word);
       if (sh_name >= name_size)
@@ -1324,6 +1355,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	  XDELETEVEC (names);
 	  XDELETEVEC (shdrs);
 	  XDELETEVEC (symtab_indices_shndx);
+	  XDELETEVEC (symtab_indices_shndx_buf);
 	  return "ELF section name out of range";
 	}
 
@@ -1332,16 +1364,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 				shdr, sh_offset, Elf_Addr);
       length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 				shdr, sh_size, Elf_Addr);
-      sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-				 shdr, sh_type, Elf_Word);
 
-      dest = simple_object_write_create_section (dobj, pfnname[i - 1],
-						 0, &errmsg, err);
+      dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err);
       if (dest == NULL)
 	{
 	  XDELETEVEC (names);
 	  XDELETEVEC (shdrs);
 	  XDELETEVEC (symtab_indices_shndx);
+	  XDELETEVEC (symtab_indices_shndx_buf);
 	  return errmsg;
 	}
 
@@ -1363,6 +1393,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	  XDELETEVEC (names);
 	  XDELETEVEC (shdrs);
 	  XDELETEVEC (symtab_indices_shndx);
+	  XDELETEVEC (symtab_indices_shndx_buf);
 	  return errmsg;
 	}
 
@@ -1378,7 +1409,8 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	  /* Read the section index table if present.  */
 	  if (symtab_indices_shndx[i - 1] != 0)
 	    {
-	      unsigned char *sidxhdr = shdrs + symtab_indices_shndx[i - 1] * shdr_size;
+	      unsigned char *sidxhdr
+		= shdrs + (symtab_indices_shndx[i - 1] - 1) * shdr_size;
 	      off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
 					       sidxhdr, sh_offset, Elf_Addr);
 	      size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
@@ -1388,11 +1420,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 				   sidxhdr, sh_type, Elf_Word);
 	      if (shndx_type != SHT_SYMTAB_SHNDX)
 		return "Wrong section type of a SYMTAB SECTION INDICES section";
-	      shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
-	      simple_object_internal_read (sobj->descriptor,
-					   sobj->offset + sidxoff,
-					   (unsigned char *)shndx_table,
-					   sidxsz, &errmsg, err);
+	      shndx_table = (unsigned *) XNEWVEC (char, sidxsz);
+	      if (!simple_object_internal_read (sobj->descriptor,
+						sobj->offset + sidxoff,
+						(unsigned char *) shndx_table,
+						sidxsz, &errmsg, err))
+		{
+		  XDELETEVEC (buf);
+		  XDELETEVEC (names);
+		  XDELETEVEC (shdrs);
+		  XDELETEVEC (symtab_indices_shndx);
+		  XDELETEVEC (shndx_table);
+		  XDELETEVEC (symtab_indices_shndx_buf);
+		  return errmsg;
+		}
 	    }
 
 	  /* Find a WEAK HIDDEN symbol which name we will use for removed
@@ -1407,17 +1448,20 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	      unsigned char *st_other;
 	      if (ei_class == ELFCLASS32)
 		{
-		  st_info = &((Elf32_External_Sym *)ent)->st_info;
-		  st_other = &((Elf32_External_Sym *)ent)->st_other;
+		  st_info = &((Elf32_External_Sym *) ent)->st_info;
+		  st_other = &((Elf32_External_Sym *) ent)->st_other;
 		}
 	      else
 		{
-		  st_info = &((Elf64_External_Sym *)ent)->st_info;
-		  st_other = &((Elf64_External_Sym *)ent)->st_other;
+		  st_info = &((Elf64_External_Sym *) ent)->st_info;
+		  st_other = &((Elf64_External_Sym *) ent)->st_other;
 		}
 	      if (st_shndx == SHN_XINDEX)
-		st_shndx = type_functions->fetch_Elf_Word
-		    ((unsigned char *)(shndx_table + (ent - buf) / entsize));
+		{
+		  unsigned char *ndx_ptr
+		    = (unsigned char *) (shndx_table + (ent - buf) / entsize);
+		  st_shndx = type_functions->fetch_Elf_Word (ndx_ptr);
+		}
 
 	      if (st_shndx != SHN_COMMON
 		  && !(st_shndx != SHN_UNDEF
@@ -1442,19 +1486,26 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	      unsigned char *st_info;
 	      unsigned char *st_other;
 	      int discard = 0;
+	      unsigned char *ndx_ptr = NULL;
 	      if (ei_class == ELFCLASS32)
 		{
-		  st_info = &((Elf32_External_Sym *)ent)->st_info;
-		  st_other = &((Elf32_External_Sym *)ent)->st_other;
+		  st_info = &((Elf32_External_Sym *) ent)->st_info;
+		  st_other = &((Elf32_External_Sym *) ent)->st_other;
 		}
 	      else
 		{
-		  st_info = &((Elf64_External_Sym *)ent)->st_info;
-		  st_other = &((Elf64_External_Sym *)ent)->st_other;
+		  st_info = &((Elf64_External_Sym *) ent)->st_info;
+		  st_other = &((Elf64_External_Sym *) ent)->st_other;
 		}
+	      if (shndx_table)
+		ndx_ptr
+		  = (unsigned char *) (shndx_table + (ent - buf) / entsize);
+
 	      if (st_shndx == SHN_XINDEX)
-		st_shndx = type_functions->fetch_Elf_Word
-		    ((unsigned char *)(shndx_table + (ent - buf) / entsize));
+		{
+		  st_shndx = type_functions->fetch_Elf_Word (ndx_ptr);
+		  type_functions->set_Elf_Word (ndx_ptr, SHN_UNDEF);
+		}
 	      /* Eliminate all COMMONs - this includes __gnu_lto_slim
 		 which otherwise cause endless LTO plugin invocation.
 		 FIXME: remove the condition once we remove emission
@@ -1488,9 +1539,14 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 			 defined in the first prevailing section.  */
 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
 				     ent, st_name, Elf_Word, 0);
+		      st_shndx = sh_map[first_shndx];
+		      if (st_shndx >= SHN_LORESERVE)
+			{
+			  type_functions->set_Elf_Word (ndx_ptr, st_shndx);
+			  st_shndx = SHN_XINDEX;
+			}
 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
-				     ent, st_shndx, Elf_Half,
-				     sh_map[first_shndx]);
+				     ent, st_shndx, Elf_Half, st_shndx);
 		    }
 		  else
 		    {
@@ -1514,11 +1570,24 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 		}
 	      else if (raw_st_shndx < SHN_LORESERVE
 		       || raw_st_shndx == SHN_XINDEX)
-		/* Remap the section reference.  */
-		ELF_SET_FIELD (type_functions, ei_class, Sym,
-			       ent, st_shndx, Elf_Half, sh_map[st_shndx]);
+		{
+		  /* Remap the section reference.  */
+		  st_shndx = sh_map[st_shndx];
+		  if (st_shndx >= SHN_LORESERVE)
+		    {
+		      type_functions->set_Elf_Word (ndx_ptr, st_shndx);
+		      st_shndx = SHN_XINDEX;
+		    }
+		  ELF_SET_FIELD (type_functions, ei_class, Sym,
+				 ent, st_shndx, Elf_Half, st_shndx);
+		}
 	    }
-	  XDELETEVEC (shndx_table);
+	  if (symtab_indices_shndx_buf)
+	    symtab_indices_shndx_buf[sh_map[symtab_indices_shndx[i - 1]]
+				     - first_symtab_indices_shndx]
+	      = (unsigned char *) shndx_table;
+	  else
+	    XDELETEVEC (shndx_table);
 	}
       else if (sh_type == SHT_GROUP)
 	{
@@ -1538,15 +1607,21 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
 	  /* Adjust the length.  */
 	  length = dst - buf;
 	}
+      else if (sh_type == SHT_SYMTAB_SHNDX)
+	{
+	  XDELETEVEC (buf);
+	  buf = symtab_indices_shndx_buf[new_i - first_symtab_indices_shndx];
+	  symtab_indices_shndx_buf[new_i - first_symtab_indices_shndx] = NULL;
+	}
 
-      errmsg = simple_object_write_add_data (dobj, dest,
-					     buf, length, 1, err);
+      errmsg = simple_object_write_add_data (dobj, dest, buf, length, 1, err);
       XDELETEVEC (buf);
       if (errmsg)
 	{
 	  XDELETEVEC (names);
 	  XDELETEVEC (shdrs);
 	  XDELETEVEC (symtab_indices_shndx);
+	  XDELETEVEC (symtab_indices_shndx_buf);
 	  return errmsg;
 	}
 
@@ -1586,6 +1661,7 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
   XDELETEVEC (pfnname);
   XDELETEVEC (symtab_indices_shndx);
   XDELETEVEC (sh_map);
+  XDELETEVEC (symtab_indices_shndx_buf);
 
   return NULL;
 }
diff --git a/libiberty/testsuite/test-demangle.c b/libiberty/testsuite/test-demangle.c
index abe9015c316..f79cd89277a 100644
--- a/libiberty/testsuite/test-demangle.c
+++ b/libiberty/testsuite/test-demangle.c
@@ -49,8 +49,7 @@ static unsigned int lineno;
 #define LINELEN 80
 
 static void
-get_line(buf)
-     struct line *buf;
+get_line(struct line *buf)
 {
   char *data = buf->data;
   size_t alloc = buf->alloced;
@@ -134,12 +133,8 @@ protect_end (const char * s)
 }
 
 static void
-fail (lineno, opts, in, out, exp)
-     int lineno;
-     const char *opts;
-     const char *in;
-     const char *out;
-     const char *exp;
+fail (int lineno, const char *opts, const char *in,
+      const char *out, const char *exp)
 {
   printf ("\
 FAIL at line %d, options %s:\n\
@@ -170,9 +165,7 @@ exp: %s\n",
 */
 
 int
-main(argc, argv)
-     int argc;
-     char **argv;
+main(int argc, char **argv)
 {
   enum demangling_styles style = auto_demangling;
   int no_params;

base-commit: a2f774427e078f3da2c06bdea25f77a61979a695
-- 
2.47.0


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

* Re: [PATCH] libiberty: sync with gcc
  2024-08-20 17:01 Andrew Burgess
@ 2024-09-04 16:07 ` Andrew Burgess
  0 siblings, 0 replies; 14+ messages in thread
From: Andrew Burgess @ 2024-09-04 16:07 UTC (permalink / raw)
  To: binutils, gdb-patches

Andrew Burgess <aburgess@redhat.com> writes:

> This syncs binutils-gdb/libiberty with gcc/libiberty up to GCC commit
> 64028d626a50410dbf29.  This picks up the follow 3 GCC commits:
>
>   ea238096883 (gcc-delete-unused-func) libiberty/argv.c: remove only_whitespace
>   5e1d530da87 (gcc-buildargv) libiberty/buildargv: handle input consisting of only white space
>   a87954610f5 libiberty/buildargv: POSIX behaviour for backslash handling

I've gone ahead and checked this in.

If there are any issues then let me know.

Thanks,
Andrew


> ---
>  libiberty/ChangeLog                   |  21 ++++
>  libiberty/argv.c                      | 113 ++++++++---------
>  libiberty/testsuite/test-expandargv.c | 170 ++++++++++++++++++++++----
>  3 files changed, 221 insertions(+), 83 deletions(-)
>
> diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
> index cdcd4b3ced8..949fec62fe4 100644
> --- a/libiberty/ChangeLog
> +++ b/libiberty/ChangeLog
> @@ -1,3 +1,24 @@
> +2024-08-05  Andrew Burgess  <aburgess@redhat.com>
> +
> +	* argv.c (only_whitespace): Delete.
> +
> +2024-07-16  Andrew Burgess  <aburgess@redhat.com>
> +
> +	* argv.c (buildargv): Treat input of only whitespace as an empty
> +	argument list.
> +	(expandargv): Remove work around for intput that is only
> +	whitespace.
> +	* testsuite/test-expandargv.c: Add new tests 10, 11, and 12.
> +	Extend testing to call buildargv in more cases.
> +
> +2024-07-16  Andrew Burgess  <aburgess@redhat.com>
> +
> +	* argv.c (buildargv): Backslashes within single quotes are
> +	literal, backslashes only escape POSIX defined special characters
> +	within double quotes, and backslashed newlines should act as line
> +	continuations.
> +	* testsuite/test-expandargv.c: Add new tests 7, 8, and 9.
> +
>  2024-04-02  Tom Tromey  <tom@tromey.com>
>  
>  	* cplus-dem.c (cplus_demangle): Try the D demangler with
> diff --git a/libiberty/argv.c b/libiberty/argv.c
> index 45f16854603..f889432a868 100644
> --- a/libiberty/argv.c
> +++ b/libiberty/argv.c
> @@ -124,15 +124,6 @@ consume_whitespace (const char **input)
>      }
>  }
>  
> -static int
> -only_whitespace (const char* input)
> -{
> -  while (*input != EOS && ISSPACE (*input))
> -    input++;
> -
> -  return (*input == EOS);
> -}
> -
>  /*
>  
>  @deftypefn Extension char** buildargv (char *@var{sp})
> @@ -212,67 +203,74 @@ char **buildargv (const char *input)
>  	      argv[argc] = NULL;
>  	    }
>  	  /* Begin scanning arg */
> -	  arg = copybuf;
> -	  while (*input != EOS)
> +	  if (*input != EOS)
>  	    {
> -	      if (ISSPACE (*input) && !squote && !dquote && !bsquote)
> -		{
> -		  break;
> -		}
> -	      else
> +	      arg = copybuf;
> +	      while (*input != EOS)
>  		{
> -		  if (bsquote)
> -		    {
> -		      bsquote = 0;
> -		      *arg++ = *input;
> -		    }
> -		  else if (*input == '\\')
> +		  if (ISSPACE (*input) && !squote && !dquote && !bsquote)
>  		    {
> -		      bsquote = 1;
> -		    }
> -		  else if (squote)
> -		    {
> -		      if (*input == '\'')
> -			{
> -			  squote = 0;
> -			}
> -		      else
> -			{
> -			  *arg++ = *input;
> -			}
> +		      break;
>  		    }
> -		  else if (dquote)
> +		  else
>  		    {
> -		      if (*input == '"')
> +		      if (bsquote)
>  			{
> -			  dquote = 0;
> +			  bsquote = 0;
> +			  if (*input != '\n')
> +			    *arg++ = *input;
>  			}
> -		      else
> +		      else if (*input == '\\'
> +			       && !squote
> +			       && (!dquote
> +				   || strchr ("$`\"\\\n", *(input + 1)) != NULL))
>  			{
> -			  *arg++ = *input;
> +			  bsquote = 1;
>  			}
> -		    }
> -		  else
> -		    {
> -		      if (*input == '\'')
> +		      else if (squote)
>  			{
> -			  squote = 1;
> +			  if (*input == '\'')
> +			    {
> +			      squote = 0;
> +			    }
> +			  else
> +			    {
> +			      *arg++ = *input;
> +			    }
>  			}
> -		      else if (*input == '"')
> +		      else if (dquote)
>  			{
> -			  dquote = 1;
> +			  if (*input == '"')
> +			    {
> +			      dquote = 0;
> +			    }
> +			  else
> +			    {
> +			      *arg++ = *input;
> +			    }
>  			}
>  		      else
>  			{
> -			  *arg++ = *input;
> +			  if (*input == '\'')
> +			    {
> +			      squote = 1;
> +			    }
> +			  else if (*input == '"')
> +			    {
> +			      dquote = 1;
> +			    }
> +			  else
> +			    {
> +			      *arg++ = *input;
> +			    }
>  			}
> +		      input++;
>  		    }
> -		  input++;
>  		}
> +	      *arg = EOS;
> +	      argv[argc] = xstrdup (copybuf);
> +	      argc++;
>  	    }
> -	  *arg = EOS;
> -	  argv[argc] = xstrdup (copybuf);
> -	  argc++;
>  	  argv[argc] = NULL;
>  
>  	  consume_whitespace (&input);
> @@ -435,17 +433,8 @@ expandargv (int *argcp, char ***argvp)
>  	}
>        /* Add a NUL terminator.  */
>        buffer[len] = '\0';
> -      /* If the file is empty or contains only whitespace, buildargv would
> -	 return a single empty argument.  In this context we want no arguments,
> -	 instead.  */
> -      if (only_whitespace (buffer))
> -	{
> -	  file_argv = (char **) xmalloc (sizeof (char *));
> -	  file_argv[0] = NULL;
> -	}
> -      else
> -	/* Parse the string.  */
> -	file_argv = buildargv (buffer);
> +      /* Parse the string.  */
> +      file_argv = buildargv (buffer);
>        /* If *ARGVP is not already dynamically allocated, copy it.  */
>        if (*argvp == original_argv)
>  	*argvp = dupargv (*argvp);
> diff --git a/libiberty/testsuite/test-expandargv.c b/libiberty/testsuite/test-expandargv.c
> index 1e9cb0a0d5a..ca7031eaf68 100644
> --- a/libiberty/testsuite/test-expandargv.c
> +++ b/libiberty/testsuite/test-expandargv.c
> @@ -142,6 +142,64 @@ const char *test_data[] = {
>    "b",
>    0,
>  
> +  /* Test 7 - No backslash removal within single quotes.  */
> +  "'a\\$VAR' '\\\"'",    /* Test 7 data */
> +  ARGV0,
> +  "@test-expandargv-7.lst",
> +  0,
> +  ARGV0,
> +  "a\\$VAR",
> +  "\\\"",
> +  0,
> +
> +  /* Test 8 - Remove backslash / newline pairs.  */
> +  "\"ab\\\ncd\" ef\\\ngh",    /* Test 8 data */
> +  ARGV0,
> +  "@test-expandargv-8.lst",
> +  0,
> +  ARGV0,
> +  "abcd",
> +  "efgh",
> +  0,
> +
> +  /* Test 9 - Backslash within double quotes.  */
> +  "\"\\$VAR\" \"\\`\" \"\\\"\" \"\\\\\" \"\\n\" \"\\t\"",    /* Test 9 data */
> +  ARGV0,
> +  "@test-expandargv-9.lst",
> +  0,
> +  ARGV0,
> +  "$VAR",
> +  "`",
> +  "\"",
> +  "\\",
> +  "\\n",
> +  "\\t",
> +  0,
> +
> +  /* Test 10 - Mixed white space characters.  */
> +  "\t \n \t ",		/* Test 10 data */
> +  ARGV0,
> +  "@test-expandargv-10.lst",
> +  0,
> +  ARGV0,
> +  0,
> +
> +  /* Test 11 - Single ' ' character.  */
> +  " ",		/* Test 11 data */
> +  ARGV0,
> +  "@test-expandargv-11.lst",
> +  0,
> +  ARGV0,
> +  0,
> +
> +  /* Test 12 - Multiple ' ' characters.  */
> +  "   ",		/* Test 12 data */
> +  ARGV0,
> +  "@test-expandargv-12.lst",
> +  0,
> +  ARGV0,
> +  0,
> +
>    0 /* Test done marker, don't remove. */
>  };
>  
> @@ -231,6 +289,78 @@ erase_test (int test)
>      fatal_error (__LINE__, "Failed to erase test file.", errno);
>  }
>  
> +/* compare_argv:
> +     TEST is the current test number, and NAME is a short string to identify
> +     which libibery function is being tested.  ARGC_A and ARGV_A describe an
> +     argument array, and this is compared to ARGC_B and ARGV_B, return 0 if
> +     the two arrays match, otherwise return 1.  */
> +
> +static int
> +compare_argv (int test, const char *name, int argc_a, char *argv_a[],
> +	      int argc_b, char *argv_b[])
> +{
> +  int failed = 0, k;
> +
> +  if (argc_a != argc_b)
> +    {
> +      printf ("FAIL: test-%s-%d.  Argument count didn't match\n", name, test);
> +      failed = 1;
> +    }
> +  /* Compare each of the argv's ... */
> +  else
> +    for (k = 0; k < argc_a; k++)
> +      if (strcmp (argv_a[k], argv_b[k]) != 0)
> +	{
> +	  printf ("FAIL: test-%s-%d. Arguments don't match.\n", name, test);
> +	  failed = 1;
> +	  break;
> +	}
> +
> +  if (!failed)
> +    printf ("PASS: test-%s-%d.\n", name, test);
> +
> +  return failed;
> +}
> +
> +/* test_buildargv
> +     Test the buildargv function from libiberty.  TEST is the current test
> +     number and TEST_INPUT is the string to pass to buildargv (after calling
> +     run_replaces on it).  ARGC_AFTER and ARGV_AFTER are the expected
> +     results.  Return 0 if the test passes, otherwise return 1.  */
> +
> +static int
> +test_buildargv (int test, const char * test_input, int argc_after,
> +		char *argv_after[])
> +{
> +  char * input, ** argv;
> +  size_t len;
> +  int argc, failed;
> +
> +  /* Generate RW copy of data for replaces */
> +  len = strlen (test_input);
> +  input = malloc (sizeof (char) * (len + 1));
> +  if (input == NULL)
> +    fatal_error (__LINE__, "Failed to malloc buildargv input buffer.", errno);
> +
> +  memcpy (input, test_input, sizeof (char) * (len + 1));
> +  /* Run all possible replaces */
> +  run_replaces (input);
> +
> +  /* Split INPUT into separate arguments.  */
> +  argv = buildargv (input);
> +
> +  /* Count the arguments we got back.  */
> +  argc = 0;
> +  while (argv[argc])
> +    ++argc;
> +
> +  failed = compare_argv (test, "buildargv", argc_after, argv_after, argc, argv);
> +
> +  free (input);
> +  freeargv (argv);
> +
> +  return failed;
> +}
>  
>  /* run_tests:
>      Run expandargv
> @@ -242,12 +372,16 @@ run_tests (const char **test_data)
>  {
>    int argc_after, argc_before;
>    char ** argv_before, ** argv_after;
> -  int i, j, k, fails, failed;
> +  int i, j, k, fails;
> +  const char * input_str;
>  
>    i = j = fails = 0;
>    /* Loop over all the tests */
>    while (test_data[j])
>      {
> +      /* Save original input in case we run a buildargv test.  */
> +      input_str = test_data[j];
> +
>        /* Write test data */
>        writeout_test (i, test_data[j++]);
>        /* Copy argv before */
> @@ -271,29 +405,23 @@ run_tests (const char **test_data)
>        for (k = 0; k < argc_after; k++)
>          run_replaces (argv_after[k]);
>  
> +      /* If the test input is just a file to expand then we can also test
> +	 calling buildargv directly as the expected output is equivalent to
> +	 calling buildargv on the contents of the file.
> +
> +	 The results of calling buildargv will not include the ARGV0 constant,
> +	 which is why we pass 'argc_after - 1' and 'argv_after + 1', this skips
> +	 over the ARGV0 in the expected results.  */
> +      if (argc_before == 2)
> +	fails += test_buildargv (i, input_str, argc_after - 1, argv_after + 1);
> +      else
> +	printf ("SKIP: test-buildargv-%d.  This test isn't for buildargv\n", i);
> +
>        /* Run test: Expand arguments */
>        expandargv (&argc_before, &argv_before);
>  
> -      failed = 0;
> -      /* Compare size first */
> -      if (argc_before != argc_after)
> -        {
> -          printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
> -	  failed++;
> -        }
> -      /* Compare each of the argv's ... */
> -      else
> -        for (k = 0; k < argc_after; k++)
> -          if (strcmp (argv_before[k], argv_after[k]) != 0)
> -            {
> -              printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
> -              failed++;
> -            }
> -
> -      if (!failed)
> -        printf ("PASS: test-expandargv-%d.\n", i);
> -      else
> -        fails++;
> +      fails += compare_argv (i, "expandargv", argc_before, argv_before,
> +			     argc_after, argv_after);
>  
>        freeargv (argv_before);
>        freeargv (argv_after);
>
> base-commit: 40a1603112d2b1d330e11792b5506457d5584648
> -- 
> 2.25.4


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

* [PATCH] libiberty: sync with gcc
@ 2024-08-20 17:01 Andrew Burgess
  2024-09-04 16:07 ` Andrew Burgess
  0 siblings, 1 reply; 14+ messages in thread
From: Andrew Burgess @ 2024-08-20 17:01 UTC (permalink / raw)
  To: binutils, gdb-patches; +Cc: Andrew Burgess

This syncs binutils-gdb/libiberty with gcc/libiberty up to GCC commit
64028d626a50410dbf29.  This picks up the follow 3 GCC commits:

  ea238096883 (gcc-delete-unused-func) libiberty/argv.c: remove only_whitespace
  5e1d530da87 (gcc-buildargv) libiberty/buildargv: handle input consisting of only white space
  a87954610f5 libiberty/buildargv: POSIX behaviour for backslash handling
---
 libiberty/ChangeLog                   |  21 ++++
 libiberty/argv.c                      | 113 ++++++++---------
 libiberty/testsuite/test-expandargv.c | 170 ++++++++++++++++++++++----
 3 files changed, 221 insertions(+), 83 deletions(-)

diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index cdcd4b3ced8..949fec62fe4 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,24 @@
+2024-08-05  Andrew Burgess  <aburgess@redhat.com>
+
+	* argv.c (only_whitespace): Delete.
+
+2024-07-16  Andrew Burgess  <aburgess@redhat.com>
+
+	* argv.c (buildargv): Treat input of only whitespace as an empty
+	argument list.
+	(expandargv): Remove work around for intput that is only
+	whitespace.
+	* testsuite/test-expandargv.c: Add new tests 10, 11, and 12.
+	Extend testing to call buildargv in more cases.
+
+2024-07-16  Andrew Burgess  <aburgess@redhat.com>
+
+	* argv.c (buildargv): Backslashes within single quotes are
+	literal, backslashes only escape POSIX defined special characters
+	within double quotes, and backslashed newlines should act as line
+	continuations.
+	* testsuite/test-expandargv.c: Add new tests 7, 8, and 9.
+
 2024-04-02  Tom Tromey  <tom@tromey.com>
 
 	* cplus-dem.c (cplus_demangle): Try the D demangler with
diff --git a/libiberty/argv.c b/libiberty/argv.c
index 45f16854603..f889432a868 100644
--- a/libiberty/argv.c
+++ b/libiberty/argv.c
@@ -124,15 +124,6 @@ consume_whitespace (const char **input)
     }
 }
 
-static int
-only_whitespace (const char* input)
-{
-  while (*input != EOS && ISSPACE (*input))
-    input++;
-
-  return (*input == EOS);
-}
-
 /*
 
 @deftypefn Extension char** buildargv (char *@var{sp})
@@ -212,67 +203,74 @@ char **buildargv (const char *input)
 	      argv[argc] = NULL;
 	    }
 	  /* Begin scanning arg */
-	  arg = copybuf;
-	  while (*input != EOS)
+	  if (*input != EOS)
 	    {
-	      if (ISSPACE (*input) && !squote && !dquote && !bsquote)
-		{
-		  break;
-		}
-	      else
+	      arg = copybuf;
+	      while (*input != EOS)
 		{
-		  if (bsquote)
-		    {
-		      bsquote = 0;
-		      *arg++ = *input;
-		    }
-		  else if (*input == '\\')
+		  if (ISSPACE (*input) && !squote && !dquote && !bsquote)
 		    {
-		      bsquote = 1;
-		    }
-		  else if (squote)
-		    {
-		      if (*input == '\'')
-			{
-			  squote = 0;
-			}
-		      else
-			{
-			  *arg++ = *input;
-			}
+		      break;
 		    }
-		  else if (dquote)
+		  else
 		    {
-		      if (*input == '"')
+		      if (bsquote)
 			{
-			  dquote = 0;
+			  bsquote = 0;
+			  if (*input != '\n')
+			    *arg++ = *input;
 			}
-		      else
+		      else if (*input == '\\'
+			       && !squote
+			       && (!dquote
+				   || strchr ("$`\"\\\n", *(input + 1)) != NULL))
 			{
-			  *arg++ = *input;
+			  bsquote = 1;
 			}
-		    }
-		  else
-		    {
-		      if (*input == '\'')
+		      else if (squote)
 			{
-			  squote = 1;
+			  if (*input == '\'')
+			    {
+			      squote = 0;
+			    }
+			  else
+			    {
+			      *arg++ = *input;
+			    }
 			}
-		      else if (*input == '"')
+		      else if (dquote)
 			{
-			  dquote = 1;
+			  if (*input == '"')
+			    {
+			      dquote = 0;
+			    }
+			  else
+			    {
+			      *arg++ = *input;
+			    }
 			}
 		      else
 			{
-			  *arg++ = *input;
+			  if (*input == '\'')
+			    {
+			      squote = 1;
+			    }
+			  else if (*input == '"')
+			    {
+			      dquote = 1;
+			    }
+			  else
+			    {
+			      *arg++ = *input;
+			    }
 			}
+		      input++;
 		    }
-		  input++;
 		}
+	      *arg = EOS;
+	      argv[argc] = xstrdup (copybuf);
+	      argc++;
 	    }
-	  *arg = EOS;
-	  argv[argc] = xstrdup (copybuf);
-	  argc++;
 	  argv[argc] = NULL;
 
 	  consume_whitespace (&input);
@@ -435,17 +433,8 @@ expandargv (int *argcp, char ***argvp)
 	}
       /* Add a NUL terminator.  */
       buffer[len] = '\0';
-      /* If the file is empty or contains only whitespace, buildargv would
-	 return a single empty argument.  In this context we want no arguments,
-	 instead.  */
-      if (only_whitespace (buffer))
-	{
-	  file_argv = (char **) xmalloc (sizeof (char *));
-	  file_argv[0] = NULL;
-	}
-      else
-	/* Parse the string.  */
-	file_argv = buildargv (buffer);
+      /* Parse the string.  */
+      file_argv = buildargv (buffer);
       /* If *ARGVP is not already dynamically allocated, copy it.  */
       if (*argvp == original_argv)
 	*argvp = dupargv (*argvp);
diff --git a/libiberty/testsuite/test-expandargv.c b/libiberty/testsuite/test-expandargv.c
index 1e9cb0a0d5a..ca7031eaf68 100644
--- a/libiberty/testsuite/test-expandargv.c
+++ b/libiberty/testsuite/test-expandargv.c
@@ -142,6 +142,64 @@ const char *test_data[] = {
   "b",
   0,
 
+  /* Test 7 - No backslash removal within single quotes.  */
+  "'a\\$VAR' '\\\"'",    /* Test 7 data */
+  ARGV0,
+  "@test-expandargv-7.lst",
+  0,
+  ARGV0,
+  "a\\$VAR",
+  "\\\"",
+  0,
+
+  /* Test 8 - Remove backslash / newline pairs.  */
+  "\"ab\\\ncd\" ef\\\ngh",    /* Test 8 data */
+  ARGV0,
+  "@test-expandargv-8.lst",
+  0,
+  ARGV0,
+  "abcd",
+  "efgh",
+  0,
+
+  /* Test 9 - Backslash within double quotes.  */
+  "\"\\$VAR\" \"\\`\" \"\\\"\" \"\\\\\" \"\\n\" \"\\t\"",    /* Test 9 data */
+  ARGV0,
+  "@test-expandargv-9.lst",
+  0,
+  ARGV0,
+  "$VAR",
+  "`",
+  "\"",
+  "\\",
+  "\\n",
+  "\\t",
+  0,
+
+  /* Test 10 - Mixed white space characters.  */
+  "\t \n \t ",		/* Test 10 data */
+  ARGV0,
+  "@test-expandargv-10.lst",
+  0,
+  ARGV0,
+  0,
+
+  /* Test 11 - Single ' ' character.  */
+  " ",		/* Test 11 data */
+  ARGV0,
+  "@test-expandargv-11.lst",
+  0,
+  ARGV0,
+  0,
+
+  /* Test 12 - Multiple ' ' characters.  */
+  "   ",		/* Test 12 data */
+  ARGV0,
+  "@test-expandargv-12.lst",
+  0,
+  ARGV0,
+  0,
+
   0 /* Test done marker, don't remove. */
 };
 
@@ -231,6 +289,78 @@ erase_test (int test)
     fatal_error (__LINE__, "Failed to erase test file.", errno);
 }
 
+/* compare_argv:
+     TEST is the current test number, and NAME is a short string to identify
+     which libibery function is being tested.  ARGC_A and ARGV_A describe an
+     argument array, and this is compared to ARGC_B and ARGV_B, return 0 if
+     the two arrays match, otherwise return 1.  */
+
+static int
+compare_argv (int test, const char *name, int argc_a, char *argv_a[],
+	      int argc_b, char *argv_b[])
+{
+  int failed = 0, k;
+
+  if (argc_a != argc_b)
+    {
+      printf ("FAIL: test-%s-%d.  Argument count didn't match\n", name, test);
+      failed = 1;
+    }
+  /* Compare each of the argv's ... */
+  else
+    for (k = 0; k < argc_a; k++)
+      if (strcmp (argv_a[k], argv_b[k]) != 0)
+	{
+	  printf ("FAIL: test-%s-%d. Arguments don't match.\n", name, test);
+	  failed = 1;
+	  break;
+	}
+
+  if (!failed)
+    printf ("PASS: test-%s-%d.\n", name, test);
+
+  return failed;
+}
+
+/* test_buildargv
+     Test the buildargv function from libiberty.  TEST is the current test
+     number and TEST_INPUT is the string to pass to buildargv (after calling
+     run_replaces on it).  ARGC_AFTER and ARGV_AFTER are the expected
+     results.  Return 0 if the test passes, otherwise return 1.  */
+
+static int
+test_buildargv (int test, const char * test_input, int argc_after,
+		char *argv_after[])
+{
+  char * input, ** argv;
+  size_t len;
+  int argc, failed;
+
+  /* Generate RW copy of data for replaces */
+  len = strlen (test_input);
+  input = malloc (sizeof (char) * (len + 1));
+  if (input == NULL)
+    fatal_error (__LINE__, "Failed to malloc buildargv input buffer.", errno);
+
+  memcpy (input, test_input, sizeof (char) * (len + 1));
+  /* Run all possible replaces */
+  run_replaces (input);
+
+  /* Split INPUT into separate arguments.  */
+  argv = buildargv (input);
+
+  /* Count the arguments we got back.  */
+  argc = 0;
+  while (argv[argc])
+    ++argc;
+
+  failed = compare_argv (test, "buildargv", argc_after, argv_after, argc, argv);
+
+  free (input);
+  freeargv (argv);
+
+  return failed;
+}
 
 /* run_tests:
     Run expandargv
@@ -242,12 +372,16 @@ run_tests (const char **test_data)
 {
   int argc_after, argc_before;
   char ** argv_before, ** argv_after;
-  int i, j, k, fails, failed;
+  int i, j, k, fails;
+  const char * input_str;
 
   i = j = fails = 0;
   /* Loop over all the tests */
   while (test_data[j])
     {
+      /* Save original input in case we run a buildargv test.  */
+      input_str = test_data[j];
+
       /* Write test data */
       writeout_test (i, test_data[j++]);
       /* Copy argv before */
@@ -271,29 +405,23 @@ run_tests (const char **test_data)
       for (k = 0; k < argc_after; k++)
         run_replaces (argv_after[k]);
 
+      /* If the test input is just a file to expand then we can also test
+	 calling buildargv directly as the expected output is equivalent to
+	 calling buildargv on the contents of the file.
+
+	 The results of calling buildargv will not include the ARGV0 constant,
+	 which is why we pass 'argc_after - 1' and 'argv_after + 1', this skips
+	 over the ARGV0 in the expected results.  */
+      if (argc_before == 2)
+	fails += test_buildargv (i, input_str, argc_after - 1, argv_after + 1);
+      else
+	printf ("SKIP: test-buildargv-%d.  This test isn't for buildargv\n", i);
+
       /* Run test: Expand arguments */
       expandargv (&argc_before, &argv_before);
 
-      failed = 0;
-      /* Compare size first */
-      if (argc_before != argc_after)
-        {
-          printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
-	  failed++;
-        }
-      /* Compare each of the argv's ... */
-      else
-        for (k = 0; k < argc_after; k++)
-          if (strcmp (argv_before[k], argv_after[k]) != 0)
-            {
-              printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
-              failed++;
-            }
-
-      if (!failed)
-        printf ("PASS: test-expandargv-%d.\n", i);
-      else
-        fails++;
+      fails += compare_argv (i, "expandargv", argc_before, argv_before,
+			     argc_after, argv_after);
 
       freeargv (argv_before);
       freeargv (argv_after);

base-commit: 40a1603112d2b1d330e11792b5506457d5584648
-- 
2.25.4


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

end of thread, other threads:[~2025-07-25  9:18 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-29 17:17 [PATCH] libiberty: sync with gcc Sam James
2024-07-12  7:55 ` Sam James
2024-07-12  8:06   ` Nick Clifton
2024-07-12 21:49     ` Sam James
2024-08-20 17:01 Andrew Burgess
2024-09-04 16:07 ` Andrew Burgess
2024-11-18  6:02 Sam James
2024-11-22 15:30 ` Tom Tromey
2024-11-22 15:46   ` Sam James
2024-11-22 23:43     ` Tom Tromey
2025-05-14 11:49 Andreas Schwab
2025-07-10 13:30 Matthieu Longo
2025-07-23 17:36 ` Tom Tromey
2025-07-25  9:17   ` Matthieu Longo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox